# General configuration for cmake:
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
+IF(NOT ${CMAKE_VERSION} VERSION_LESS 3.0.0)
+ CMAKE_POLICY(SET CMP0026 OLD) # enable target LOCATION property
+ CMAKE_POLICY(SET CMP0037 OLD) # allow to override the generic 'help' target
+ENDIF()
+
MESSAGE(STATUS "This is CMake ${CMAKE_VERSION}")
LIST(APPEND CMAKE_MODULE_PATH
ENDIF()
-IF(FEATURE_FUNCTIONPARSER_BUNDLED_CONFIGURED)
- ADD_SUBDIRECTORY(${FUNCTIONPARSER_FOLDER})
-ENDIF()
-
-
IF(FEATURE_THREADS_BUNDLED_CONFIGURED)
INSTALL(DIRECTORY ${TBB_FOLDER}/include/tbb
DESTINATION ${DEAL_II_INCLUDE_RELDIR}/deal.II/bundled
ENDIF()
+IF(FEATURE_MUPARSER_BUNDLED_CONFIGURED)
+ ADD_SUBDIRECTORY(${MUPARSER_FOLDER})
+ENDIF()
+
+
+
MESSAGE(STATUS "Setting up bundled features - Done")
A full version of the library can be downloaded at http://www.boost.org/.
-./functionparser (FunctionParser 4.5)
+./muparser_v2_2_3
==============
-Contains the FunctionParser project which is copyrighted by Juha Nieminen
-and licensed under the GNU Lesser General Public License (LGPL) Version 3.
-See functionparser/README, functionparser/lgpl-3.0.txt or
-http://warp.povusers.org/FunctionParser/
+Contains the MuParser project licensed under the MIT license.
A full version of the FunctionParser project can be downloaded at
-http://warp.povusers.org/FunctionParser/.
-
+http://muparser.beltoforion.de/.
./tbb30_104oss
==============
+++ /dev/null
-This directory contains the functionparser project which is copyrighted
-by Juha Nieminen and licensed under the GNU Lesser General Public License
-(LGPL) Version 3. See ./docs/fparser.html or
-http://warp.povusers.org/FunctionParser/.
-
-A full version of the functionparser project can be downloaded at
-http://warp.povusers.org/FunctionParser/.
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <link href="style.css" rel="stylesheet" type="text/css" title="normal" media=screen>
- <title>Function Parser for C++ v4.5.1 : Documentation</title>
-</head>
-
-<body>
-<h1>Function Parser for C++ v4.5.1 </h1>
-
-<p>Authors: Juha Nieminen
-(<a href="http://iki.fi/warp/">http://iki.fi/warp/</a>),
-Joel Yliluoma
-(<a href="http://iki.fi/bisqwit/">http://iki.fi/bisqwit/</a>).
-
-<p>The usage license of this library is located at the end of this file.
-
-<h2>Table of contents:</h2>
-
-<ul>
- <li><a href="#whatsnew">What's new</a>
- <li><a href="#preface">Preface</a>
- <li><a href="#usage">Usage</a>
- <ul>
- <li><a href="#parsertypes">Parser types</a>
- <li><a href="#configuring">Configuring the compilation</a>
- <li><a href="#copyassignment">Copying and assignment</a>
- <li><a href="#shortdesc">Short descriptions of FunctionParser methods</a>
- <li><a href="#longdesc">Long descriptions of FunctionParser methods</a>
- <ul>
- <li><a href="#longdesc_Parse"><code>Parse()</code></a>
- <li><a href="#longdesc_setDelimiterChar"><code>setDelimiterChar()</code></a>
- <li><a href="#longdesc_ErrorMsg"><code>ErrorMsg()</code></a>
- <li><a href="#longdesc_GetParseErrorType"><code>GetParseErrorType()</code></a>
- <li><a href="#longdesc_Eval"><code>Eval()</code></a>
- <li><a href="#longdesc_EvalError"><code>EvalError()</code></a>
- <li><a href="#longdesc_Optimize"><code>Optimize()</code></a>
- <li><a href="#longdesc_AddConstant"><code>AddConstant()</code></a>
- <li><a href="#longdesc_AddUnit"><code>AddUnit()</code></a>
- <li><a href="#longdesc_AddFunction1"><code>AddFunction()</code></a> (C++ function)
- <li><a href="#longdesc_AddFunction2"><code>AddFunction()</code></a> (FunctionParser)
- <li><a href="#longdesc_AddFunction3"><code>AddFunctionWrapper()</code></a>
- <li><a href="#longdesc_RemoveIdentifier"><code>RemoveIdentifier()</code></a>
- <li><a href="#longdesc_ParseAndDeduceVariables"><code>ParseAndDeduceVariables()</code></a>
- </ul>
- <li><a href="#functionobjects">Specialized function objects</a>
- <li><a href="#base">FunctionParserBase</a>
- </ul>
- <li>Syntax
- <ul>
- <li><a href="#literals">Numeric literals</a>
- <li><a href="#identifiers">Identifier names</a>
- <li><a href="#functionsyntax">The function string syntax</a>
- <li><a href="#inlinevars">Inline variables</a>
- <li><a href="#whitespace">Whitespace</a>
- </ul>
- <li>Miscellaneous
- <ul>
- <li><a href="#fpaccuracy">About floating point accuracy</a>
- <li><a href="#evaluationchecks">About evaluation-time checks</a>
- <li><a href="#threadsafety">About thread safety</a>
- <li><a href="#tipsandtricks">Tips and tricks</a>
- <li><a href="#contact">Contacting the author</a>
- </ul>
-<!-- <li><a href="#algorithm">The algorithm used in the library</a> -->
- <li><a href="#license">Usage license</a>
-</ul>
-
-<a name="whatsnew"></a>
-<h2>What's new</h2>
-
-<p>What's new in v4.5.1
- <ul>
- <li>Reverted the automatic C++11 detection to a precompiler macro setting
- (<code>FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS</code>) because not all
- compilers yet fully support the C++11 math functions.
- <li>Fixed a potential duplicate symbol problem that happens with explicit
- template instantiations.
- </ul>
-
-<p>What's new in v4.5
- <ul>
- <li>Removed support for the <code>"eval()"</code> function from the
- supported syntax. (This function was too dangerous, too difficult to
- maintain internally, not very useful, and more or less a gimmick in
- the first place.)
- <li>Removed several of the conditional compiling macro definitions, namely
- <code>FP_SUPPORT_TR1_MATH</code>, <code>FP_ENABLE_EVAL</code>,
- <code>FP_EVAL_MAX_REC_LEVEL</code>, <code>FP_NO_EVALUATION_CHECKS</code>
- and <code>FP_EPSILON</code>.
- <li>The epsilon value used in comparisons is now set with a member function
- of FunctionParser (which allows setting different values for different
- versions of the parser).
- <li>The math functions previously turned on with
- <code>FP_SUPPORT_TR1_MATH</code> are now automatically used if
- <code>__cplusplus</code> indicates that C++11 is in use.
- <li>Fixed some compilation problems with clang++.
- </ul>
-
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="preface"></a>
-<h2>Preface</h2>
-
-<p>This C++ library offers a class which can be used to parse and evaluate a
-mathematical function from a string (which might be eg. requested from the
-user). The syntax of the function string is similar to mathematical expressions
-written in C/C++ (the exact syntax is specified later in this document).
-The function can then be evaluated with different values of variables.
-
-<p>For example, a function like "<code>sin(sqrt(x*x+y*y))</code>" can be
-parsed from a string (either <code>std::string</code> or a C-style string)
-and then evaluated with different values of <code>x</code> and <code>y</code>.
-This library can be useful for evaluating user-inputted functions, or in
-some cases interpreting mathematical expressions in a scripting language.
-
-<p>This library aims for maximum speed in both parsing and evaluation, while
-keeping maximum portability. The library should compile and work with any
-standard-conforming C++ compiler.
-
-<p>Different numerical types are supported: <code>double</code>,
- <code>float</code>, <code>long double</code>, <code>long int</code>,
- <code>std::complex</code> (of types <code>double</code>,
- <code>float</code> and <code>long double</code>),
- multiple-precision floating point numbers using the MPFR library, and
- arbitrary precision integers using the GMP library. (Note that it's
- not necessary for these two libraries to exist in the system in order
- to use the Function Parser library with the other numerical types. Support
- for these libraries is optionally compiled in using preprocessor settings.)
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="usage"></a>
-<h2>Usage</h2>
-
-<p>To use the <code>FunctionParser</code> class, you have to include
-<code>"fparser.hh"</code> in your source code files which use the
-<code>FunctionParser</code> class.
-
-<p>If you are going to use the MPFR version of the library, you need to
-include <code>"fparser_mpfr.hh"</code>. If you are going to use the GMP
-version of the library, you need to include <code>"fparser_gmpint.hh"</code>.
-(Note that support for these special parser versions needs to be specified
-with preprocessor macros. See the <a href="#parsertypes">documentation
-below</a> for details.)
-
-<p>When compiling, you have to compile <code>fparser.cc</code> and
-<code>fpoptimizer.cc</code> and link them to the main program. In many
-developement environments it's enough to add those two files to your
-current project (usually header files don't have to be added to the
-project for the compilation to work).
-
-<p>If you are going to use the MPFR or the GMP versions of the library,
-you also need to add <code>mpfr/MpfrFloat.cc</code> or
-<code>mpfr/GmpInt.cc</code> files to your project, respectively. Otherwise
-they should not be added to the project.
-
-<p>Note that part of the library source code is inside several
-<code>.inc</code> files inside the <code>extrasrc</code> subdirectory
-(these files contain auto-generated C++ code), provided in the library
-package. These files are used by <code>fparser.cc</code> and don't need
-to be added explicitly to the project in most IDEs (such as Visual Studio).
-Basically, you don't need to do anything with these files, other than keep
-them in the <code>extrasrc</code> subdirectory.
-
-<p>Simple usage example of the library:
-
-<pre>
- FunctionParser fp;
- fp.Parse("sqrt(x*x + y*y)", "x,y");
- double variables[2] = { 1.5, 2.9 };
- double result = fp.Eval(variables);
-</pre>
-
-<!-- -------------------------------------------------------------------- -->
-<a name="parsertypes"></a>
-<h3>Parser types</h3>
-
-<p>Different versions of the function parser class are supported, using
- different floating point or integral types for function evaluation.
-
-<p>All the classes other than the default one, <code>FunctionParser</code>,
- need to be enabled at compile time by defining a preprocessor macro
- (specified below) either in the <code>fpconfig.hh</code> file or your
- compiler settings. (The reason for this is that every parser that is
- included in the compilation process will make the compilation slower
- and increase the size of the executable, so they are compiled only on
- demand. Also, the GMP and MPFR versions of the parser require for those
- libraries to be available, which is often not the case.)
-
-<p>Note that if you try to use the other class types without enabling them
- with the correspondent preprocessor macro, you will get a linker error
- (rather than a compiler error) because those classes will not have been
- instantiated when the library was compiled.
-
-<p>Currently the <code>Optimize()</code> method works only for the
- <code>FunctionParser</code>, <code>FunctionParser_f</code> and
- <code>FunctionParser_ld</code> classes. For the other types it can be
- called but it does nothing.
-
-<p>
-<dl>
- <dt><p><code>FunctionParser</code></dt>
- <dd>
- <p>This is the default class, which uses <code>double</code> as its
- numerical type. This is the only class enabled by default.
- <p>If you use some other type than this one, and you don't want this
- version of the class compiled into the library, you can define the
- preprocessor macro <code>FP_DISABLE_DOUBLE_TYPE</code>.
- </dd>
-
- <dt><p><code>FunctionParser_f</code></dt>
- <dd>
- <p>This parser uses <code>float</code> as its numerical type.
- <p>The <code>FP_SUPPORT_FLOAT_TYPE</code> preprocessor macro needs to be
- defined for this class to be enabled.
- </dd>
-
- <dt><p><code>FunctionParser_ld</code></dt>
- <dd>
- <p>This parser uses <code>long double</code> as its numerical type.
- <p>The <code>FP_SUPPORT_LONG_DOUBLE_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that the <code>FP_USE_STRTOLD</code> preprocessor macro should
- also be defined when using this version of the parser if the compiler
- supports the (C99) function <code>strtold()</code>. (See
- <a href="#configuring">documentation</a> below.)
- </dd>
-
- <dt><p><code>FunctionParser_li</code></dt>
- <dd>
- <p>This parser uses <code>long int</code> as its numerical type.
- <p>The <code>FP_SUPPORT_LONG_INT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that this version of the class uses a reduced function syntax
- with support only for functions which are feasible to be used with
- integral types (namely <code>abs()</code>, <code>eval()</code>,
- <code>if()</code>, <code>min()</code> and <code>max()</code>, besides
- basic arithmetic operators, except for the power operator).
- </dd>
-
- <dt><p><code>FunctionParser_cd</code>, <code>FunctionParser_cf</code>,
- <code>FunctionParser_cld</code></dt>
- <dd>
- <p>These parsers use <code>std::complex<double></code>,
- <code>std::complex<float></code> and
- <code>std::complex<long double></code> as their numerical type,
- respectively.
- <p>The preprocessor macros to enable them are
- <code>FP_SUPPORT_COMPLEX_DOUBLE_TYPE</code>,
- <code>FP_SUPPORT_COMPLEX_FLOAT_TYPE</code> and
- <code>FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE</code>.
- <p>If <code>FunctionParser_cld</code> is used, the
- <code>FP_USE_STRTOLD</code> macro should also be defined if the compiler
- supports the <code>strtold()</code> function.
- </dd>
-
- <dt><p><code>FunctionParser_mpfr</code></dt>
- <dd>
- <p>This parser uses <code>MpfrFloat</code> as its numerical type.
- <p>The <code>FP_SUPPORT_MPFR_FLOAT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that to use this version of the parser,
- <code>"fparser_mpfr.hh"</code> needs to be included.
- <p><code>MpfrFloat</code> is an auxiliary class which uses the MPFR
- library for multiple-precision floating point numbers. The class
- behaves largely like a floating point type, and is declared in the
- <code>mpfr/MpfrFloat.hh</code> file (see that file for info about
- the public interface of the class).
- <p>If this class is enabled, <code>mpfr/MpfrFloat.cc</code>
- needs to be compiled into the project, as well as the GMP and MPFR
- libraries. (With the gcc compiler this means using the linker options
- "<code>-lgmp -lmpfr</code>".)
- </dd>
-
- <dt><p><code>FunctionParser_gmpint</code></dt>
- <dd>
- <p>This parser uses <code>GmpInt</code> as its numerical type.
- <p>The <code>FP_SUPPORT_GMP_INT_TYPE</code> preprocessor macro needs
- to be defined for this class to be enabled.
- <p>Note that to use this version of the parser,
- <code>"fparser_gmpint.hh"</code> needs to be included.
- <p><code>GmpInt</code> is an auxiliary class which uses the GMP
- library for arbitrary-precision integer numbers. The class
- behaves largely like an integer type, and is declared in the
- <code>mpfr/GmpInt.hh</code> file (see that file for info about
- the public interface of the class).
- <p>If this class is enabled, <code>mpfr/GmpInt.cc</code>
- needs to be compiled into the project, as well as the GMP library.
- <p>This version of the class also uses a reduced version of the syntax,
- like the <code>long int</code> version.
- <p><b>Note:</b> Since there's no upper limit to the size of GMP
- integers, this version of the class should be used with care in
- situations where malicious users might be able to exploit it to
- make the program run out of memory. An example of this would be
- a server-side application usable through the WWW.
- </dd>
-</dl>
-
-<p>Note that these different classes are completely independent and
- instances of different classes cannot be given to each other using the
- <code>AddFunction()</code> method. Only objects of the same type can
- be given to that method.
-
-<p>The rest of the documentation assumes that <code>FunctionParser</code>
- (which uses the <code>double</code> type) is used. The usage of the other
- classes is identical except that <code>double</code> is replaced with the
- correspondent type used by that class. (In other words, whenever the
- rest of this documentation uses the type keyword '<code>double</code>',
- the correspondent type should be used instead, when using another version
- of the class.)
-
-<!-- -------------------------------------------------------------------- -->
-<a name="configuring"></a>
-<h3>Configuring the compilation</h3>
-
-<p>There is a set of precompiler options in the <code>fpconfig.hh</code> file
-which can be used for setting certain features on or off. All of these options
-can also be specified from the outside, using precompiler settings (eg. the
-<code>-D</code> option in gcc), and thus it's not necessary to modify this
-file.
-
-<dl>
- <dt><p><code>FP_USE_STRTOLD</code> : (Default off)</dt>
- <dd><p>If <code>FunctionParser_ld</code> or <code>FunctionParser_cld</code>
- are used, this preprocessor macro should be defined if the compiler
- supports the (C99) function <code>strtold()</code>. If not, then numeric
- literals will be parsed with double precision only, which in most
- systems is less accurate than long double precision, which will cause
- small rounding errors. (This setting has no effect on the other parser
- types.) Note that <code>strtold()</code> will also be automatically used
- if <code>__cplusplus</code> indicates that C++11 is in use.
- </dd>
-
- <dt><p><code>FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS</code> : (Default off)</dt>
- <dd><p>Use C++11 math functions where applicable. (These are ostensibly
- faster than the equivalent formulas using C++98 math functions.) Note
- that not all compilers support these functions (even if they otherwise
- support C++11.)
-
- <dt><p><code>FP_SUPPORT_OPTIMIZER</code> : (Default on)</dt>
- <dd><p>If you are not going to use the <code>Optimize()</code> method, you
- can comment this line out to speed-up the compilation a bit, as
- well as making the binary a bit smaller. (<code>Optimize()</code> can
- still be called, but it will not do anything.)
-
- <p>You can also disable the optimizer by specifying the
- <code>FP_NO_SUPPORT_OPTIMIZER</code> precompiler constant in your
- compiler settings.
- </dd>
-
- <dt><p><code>FP_USE_THREAD_SAFE_EVAL</code> : (Default off)</dt>
- <dd><p>Define this precompiler constant to make <code>Eval()</code>
- thread-safe. Refer to the <a href="#threadsafety">thread safety
- section</a> later in this document for more information.
- Note that defining this may make <code>Eval()</code> slightly slower.
- <p>Also note that the MPFR and GMP versions of the library cannot be
- made thread-safe, and thus this setting has no effect on them.
- </dd>
-
- <dt><p><code>FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA</code> : (Default off)</dt>
- <dd><p>This is like the previous, but makes <code>Eval()</code> use the
- <code>alloca()</code> function (instead of <code>std::vector</code>).
- This will make it faster, but the <code>alloca()</code>
- function is not standard and thus not supported by all compilers.
- </dd>
-</dl>
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="copyassignment"></a>
-<h3>Copying and assignment</h3>
-
-<p>The class implements a safe copy constructor and assignment operator.
-
-<p>It uses the copy-on-write technique for efficiency. This means that
- when copying or assigning a FunctionParser instance, the internal data
- (which in some cases can be quite lengthy) is not immediately copied
- but only when the contents of the copy (or the original) are changed.
-
-<p>This means that copying/assigning is a very fast operation, and if
- the copies are never modified then actual data copying never happens
- either.
-
-<p>The <code>Eval()</code> and <code>EvalError()</code> methods of the
-copy can be called without the internal data being copied.
-
-<p>Calling <code>Parse()</code>, <code>Optimize()</code> or the user-defined
-constant/function adding methods will cause a deep-copy.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="shortdesc"></a>
-<h3>Short descriptions of FunctionParser methods</h3>
-
-<pre>
-int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
-int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
-</pre>
-
-<p>Parses the given function and compiles it to internal format.
- Return value is -1 if successful, else the index value to the location
- of the error.
-
-<hr>
-<pre>
-void setDelimiterChar(char);
-</pre>
-
-<p>Sets an ending delimiter character for the function string. (See the
- long description for more details.)
-
-<hr>
-<pre>
-static double epsilon();
-static void setEpsilon(double);
-</pre>
-
-<p>Setter and getter for the epsilon value used with comparison operators.
-
-<hr>
-<pre>
-const char* ErrorMsg(void) const;
-</pre>
-
-<p>Returns an error message corresponding to the error in
-<code>Parse()</code>, or an empty string if no such error occurred.
-
-<hr>
-<pre>
-ParseErrorType GetParseErrorType() const;
-</pre>
-
-<p>Returns the type of parsing error which occurred. Possible return types
- are described in the long description.
-
-<hr>
-<pre>
-double Eval(const double* Vars);
-</pre>
-
-<p>Evaluates the function given to <code>Parse()</code>.
-
-<hr>
-<pre>
-int EvalError(void) const;
-</pre>
-
-<p>Returns <code>0</code> if no error happened in the previous call to
-<code>Eval()</code>, else an error code <code>>0</code>.
-
-<hr>
-<pre>
-void Optimize();
-</pre>
-
-<p>Tries to optimize the bytecode for faster evaluation.
-
-<hr>
-<pre>
-bool AddConstant(const std::string& name, double value);
-</pre>
-
-<p>Add a constant to the parser. Returns <code>false</code> if the name of
-the constant is invalid, else <code>true</code>.
-
-<hr>
-<pre>
-bool AddUnit(const std::string& name, double value);
-</pre>
-
-<p>Add a new unit to the parser. Returns <code>false</code> if the name of
-the unit is invalid, else <code>true</code>.
-
-<hr>
-<pre>
-bool AddFunction(const std::string& name,
- double (*functionPtr)(const double*),
- unsigned paramsAmount);
-</pre>
-
-<p>Add a user-defined function to the parser (as a function pointer).
-Returns <code>false</code> if the name of the function is invalid, else
-<code>true</code>.
-
-<hr>
-<pre>
-bool AddFunction(const std::string& name, FunctionParser&);
-</pre>
-
-<p>Add a user-defined function to the parser (as a <code>FunctionParser</code>
-instance). Returns <code>false</code> if the name of the function is invalid,
-else <code>true</code>.
-
-<hr>
-<pre>
-bool RemoveIdentifier(const std::string& name);
-</pre>
-
-<p>Removes the constant, unit or user-defined function with the specified
-name from the parser.
-
-<hr>
-<pre>
-int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-</pre>
-
-<p>Like <code>Parse()</code>, but the variables in the function are deduced
-automatically. The amount of found variables and the variable names themselves
-are returned by the different versions of the function.
-
-<!-- -------------------------------------------------------------------- -->
-<a name="longdesc"></a>
-<h3>Long descriptions of FunctionParser methods</h3>
-
-<hr>
-<a name="longdesc_Parse"></a>
-<pre>
-int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
-int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
-</pre>
-
-<p>Parses the given function (and compiles it to internal format).
-Destroys previous function. Following calls to <code>Eval()</code> will evaluate
-the given function.
-
-<p>The strings given as parameters are not needed anymore after parsing.
-
-<p>Parameters:
-
-<table border=2>
- <tr>
- <td><code>Function</code></td>
- <td>String containing the function to parse.</td>
- </tr><tr>
- <td><code>Vars</code></td>
- <td>String containing the variable names, separated by commas.<br>
- Eg. <code>"x,y"</code>, <code>"VarX,VarY,VarZ,n"</code> or
- <code>"x1,x2,x3,x4,__VAR__"</code>.
- </tr><tr>
- <td><code>useDegrees</code></td>
- <td>(Optional.) Whether to use degrees or radians in
- trigonometric functions. (Default: radians)</td>
- </tr>
-</table>
-
-<p>If a <code>char*</code> is given as the <code>Function</code> parameter,
-it must be a null-terminated string.
-
-<p>Variables can have any size and they are case sensitive (ie.
-<code>"var"</code>, <code>"VAR"</code> and <code>"Var"</code> are
-<em>different</em> variable names). Letters, digits, underscores and
-UTF8-encoded characters can be used in variable names, but the name of
-a variable can't begin with a digit. Each variable name can appear only
-once in the '<code>Vars</code>' string. Function names are not legal
-variable names.
-
-<p>Using longer variable names causes no overhead whatsoever to the
-<code>Eval()</code> method, so it's completely safe to use variable names
-of any size.
-
-<p>The third, optional parameter specifies whether angles should be
- interpreted as radians or degrees in trigonometrical functions.
- If not specified, the default value is radians.
-
-<p>Return values:
-
-<ul>
- <li>On success the function returns <code>-1</code>.
- <li>On error the function returns an index to where the error was found
- (<code>0</code> is the first character, <code>1</code> the second, etc).
- If the error was not a parsing error returns an index to the end of the
- string.
-</ul>
-
-<p>Example: <code>parser.Parse("3*x+y", "x,y");</code>
-
-
-<hr>
-<a name="longdesc_setDelimiterChar"></a>
-<pre>
-void setDelimiterChar(char);
-</pre>
-
-<p>By default the parser expects the entire function string to be valid
-(ie. the entire contents of the given <code>std::string</code>, or a C string
-ending in the null character <code>'\0'</code>).
-
-<p>If a delimiter character is specified with this function, then if it's
-encountered at the outermost parsing level by the <code>Parse()</code>
-function, and the input function has been valid so far, <code>Parse()</code>
-will return an index to this character inside the input string, but rather
-than set an error code, <code>FP_NO_ERROR</code> will be set.
-
-<p>The idea is that this can be used to more easily parse functions which
-are embedded inside larger strings, containing surrounding data, without
-having to explicitly extract the function to a separate string.
-
-<p>For example, suppose you are writing an interpreter for a scripting
- language, which can have commands like this:
-
-<p><code>let MyFunction(x,y) = { sin(x*x+y*y) } // A 2-dimensional function</code>
-
-<p>Normally when parsing such a line you would have to extract the part
-inside the curly brackets into a separate string and parse it that way.
-With this feature what you can do instead is to set <code>'}'</code> as
-the delimiter character and then simply give a pointer to the character
-which comes after the <code>'{'</code>. If all goes well, the
-<code>Parse()</code> function will return an index to the <code>'}'</code>
-character (from the given starting point) and <code>GetParseErrorType()</code>
-will return <code>FP_NO_ERROR</code>. You can use the return
-value (if it's not <code>-1</code>) to jump forward in the string to the
-delimiter character.
-
-<p>Note that a null character (<code>'\0'</code>) or the end of the
-<code>std::string</code> (if one was given) will still be a valid end of
-the function string even if a delimiter character was specified. (In this
-case <code>Parse()</code> will return <code>-1</code> if there was no error,
-as usual.)
-
-<p>Also note that the delimiter character cannot be any valid operator
-or alphanumeric (including the underscore) character, nor the other
-characters defined in the function syntax. It must be a character not
-supported by the function parser (such as <code>'}'</code>,
-<code>'"'</code>, <code>']'</code>, etc).
-
-
-<hr>
-<a name="longdesc_Epsilon"></a>
-<pre>
-static double epsilon();
-static void setEpsilon(double);
-</pre>
-
-<p>Comparison operators (for the non-integral versions of the parser) use an
-epsilon value to account for floating point calculation rounding errors.
-This epsilon value can be set and read with these functions. (Note that the
-specified value will be used by all instances of FunctionParser.) If not
-specified, the default values are:
-
-<ul>
- <li>double: 1e-12
- <li>float: 1e-5
- <li>long double: 1e-14
- <li>MpfrFloat: The value of MpfrFloat::someEpsilon()
-</ul>
-
-
-<hr>
-<a name="longdesc_ErrorMsg"></a>
-<pre>
-const char* ErrorMsg(void) const;
-</pre>
-
-<p>Returns a pointer to an error message string corresponding to the error
-caused by <code>Parse()</code> (you can use this to print the proper error
-message to the user). If no such error has occurred, returns an empty string.
-
-
-<hr>
-<a name="longdesc_GetParseErrorType"></a>
-<pre>
-ParseErrorType GetParseErrorType() const;
-</pre>
-
-<p>Returns the type of parse error which occurred.
-
-<p>This method can be used to get the error type if <code>ErrorMsg()</code>
-is not enough for printing the error message. In other words, this can be
-used for printing customized error messages (eg. in another language).
-If the default error messages suffice, then this method doesn't need
-to be called.
-
-<code>FunctionParser::ParseErrorType</code> is an enumerated type inside
-the class (ie. its values are accessed like
-"<code>FunctionParser::SYNTAX_ERROR</code>").
-
-<p>The possible values for FunctionParser::ParseErrorType are listed below,
-along with their equivalent error message returned by the
-<code>ErrorMsg()</code> method:
-
-<p><table border=2>
-<tr>
- <td><code>FP_NO_ERROR</code></td>
- <td>If no error occurred in the previous call to <code>Parse()</code>.</td>
-</tr><tr>
- <td><code>SYNTAX_ERROR</code></td>
- <td>"Syntax error"</td>
-</tr><tr>
- <td><code>MISM_PARENTH</code></td>
- <td>"Mismatched parenthesis"</td>
-</tr><tr>
- <td><code>MISSING_PARENTH</code></td>
- <td>"Missing ')'"</td>
-</tr><tr>
- <td><code>EMPTY_PARENTH</code></td>
- <td>"Empty parentheses"</td>
-</tr><tr>
- <td><code>EXPECT_OPERATOR</code></td>
- <td>"Syntax error: Operator expected"</td>
-</tr><tr>
- <td><code>OUT_OF_MEMORY</code></td>
- <td>"Not enough memory"</td>
-</tr><tr>
- <td><code>UNEXPECTED_ERROR</code></td>
- <td>"An unexpected error occurred. Please make a full bug report to the
- author"</td>
-</tr><tr>
- <td><code>INVALID_VARS</code></td>
- <td>"Syntax error in parameter 'Vars' given to FunctionParser::Parse()"</td>
-</tr><tr>
- <td><code>ILL_PARAMS_AMOUNT</code></td>
- <td>"Illegal number of parameters to function"</td>
-</tr><tr>
- <td><code>PREMATURE_EOS</code></td>
- <td>"Syntax error: Premature end of string"</td>
-</tr><tr>
- <td><code>EXPECT_PARENTH_FUNC</code></td>
- <td>"Syntax error: Expecting ( after function"</td>
-</tr><tr>
- <td><code>UNKNOWN_IDENTIFIER</code></td>
- <td>"Syntax error: Unknown identifier"</td>
-</tr><tr>
- <td><code>NO_FUNCTION_PARSED_YET</code></td>
- <td>"(No function has been parsed yet)"</td>
-</tr>
-</table>
-
-
-<hr>
-<a name="longdesc_Eval"></a>
-<pre>
-double Eval(const double* Vars);
-</pre>
-
-<p>Evaluates the function given to <code>Parse()</code>.
-The array given as parameter must contain the same amount of values as
-the amount of variables given to <code>Parse()</code>. Each value corresponds
-to each variable, in the same order.
-
-<p>Return values:
-<ul>
- <li>On success returns the evaluated value of the function given to
- <code>Parse()</code>.
- <li>On error (such as division by 0) the return value is unspecified,
- probably 0.
-</ul>
-
-<p>Example:
-
-<p><code>double Vars[] = {1, -2.5};</code><br>
-<code>double result = parser.Eval(Vars);</code>
-
-
-<hr>
-<a name="longdesc_EvalError"></a>
-<pre>
-int EvalError(void) const;
-</pre>
-
-<p>Used to test if the call to <code>Eval()</code> succeeded.
-
-<p>Return values:
-
-<p>If there was no error in the previous call to <code>Eval()</code>,
-returns <code>0</code>, else returns a positive value as follows:
-<ul>
- <li>1: division by zero
- <li>2: sqrt error (sqrt of a negative value)
- <li>3: log error (logarithm of a negative value)
- <li>4: trigonometric error (asin or acos of illegal value)
- <li>5: maximum recursion level in <code>eval()</code> reached
-</ul>
-
-
-<hr>
-<a name="longdesc_Optimize"></a>
-<pre>
-void Optimize();
-</pre>
-
-<p>This method can be called after calling the <code>Parse()</code> method.
-It will try to simplify the internal bytecode so that it will evaluate faster
-(it tries to reduce the amount of opcodes in the bytecode).
-
-<p>For example, the bytecode for the function <code>"5+x*y-25*4/8"</code> will
-be reduced to a bytecode equivalent to the function <code>"x*y-7.5"</code> (the
-original 11 opcodes will be reduced to 5). Besides calculating constant
-expressions (like in the example), it also performs other types of
-simplifications with variable and function expressions.
-
-<p>This method is quite slow and the decision of whether to use it or
-not should depend on the type of application. If a function is parsed
-once and evaluated millions of times, then calling <code>Optimize()</code>
-may speed-up noticeably. However, if there are tons of functions to parse
-and each one is evaluated once or just a few times, then calling
-<code>Optimize()</code> will only slow down the program.
-
-<p>Also, if the original function is expected to be optimal, then calling
-<code>Optimize()</code> would be useless.
-
-<p>Note: Currently this method does not make any checks (like
-<code>Eval()</code> does) and thus things like <code>"1/0"</code> will cause
-undefined behaviour. (On the other hand, if such expression is given to the
-parser, <code>Eval()</code> will always give an error code, no matter what
-the parameters.) If caching this type of errors is important, a work-around
-is to call <code>Eval()</code> once before calling <code>Optimize()</code>
-and checking <code>EvalError()</code>.
-
-<p>If the destination application is not going to use this method,
-the compiler constant <code>FP_SUPPORT_OPTIMIZER</code> can be undefined in
-<code>fpconfig.hh</code> to make the library smaller (<code>Optimize()</code>
-can still be called, but it will not do anything).
-
-<p>(If you are interested in seeing how this method optimizes the opcode,
-you can call the <code>PrintByteCode()</code> method before and after the
-call to <code>Optimize()</code> to see the difference.)
-
-
-<hr>
-<a name="longdesc_AddConstant"></a>
-<pre>
-bool AddConstant(const std::string& name, double value);
-</pre>
-
-<p>This method can be used to add constants to the parser. Syntactically
- constants are identical to variables (ie. they follow the same naming
- rules and they can be used in the function string in the same way as
- variables), but internally constants are directly replaced with their
- value at parse time.
-
-<p>Constants used by a function must be added before calling
-<code>Parse()</code> for that function. Constants are preserved between
-<code>Parse()</code> calls in the current FunctionParser instance, so
-they don't need to be added but once. (If you use the same constant in
-several instances of FunctionParser, you will need to add it to all the
-instances separately.)
-
-<p>Constants can be added at any time and the value of old constants can
-be changed, but new additions and changes will only have effect the next
-time <code>Parse()</code> is called. (That is, changing the value of a constant
-after calling <code>Parse()</code> and before calling <code>Eval()</code>
-will have no effect.)
-
-<p>The return value will be <code>false</code> if the '<code>name</code>' of
-the constant was illegal, else <code>true</code>. If the name was illegal,
-the method does nothing.
-
-<p>Example: <code>parser.AddConstant("pi", 3.1415926535897932);</code>
-
-<p>Now for example <code>parser.Parse("x*pi", "x");</code> will be identical
-to the call <code>parser.Parse("x*3.1415926535897932", "x");</code>
-
-
-<hr>
-<a name="longdesc_AddUnit"></a>
-<pre>
-bool AddUnit(const std::string& name, double value);
-</pre>
-
-<p>In some applications it is desirable to have units of measurement.
-A typical example is an application which creates a page layout to be
-printed. When printing, distances are usually measured in points
-(defined by the resolution of the printer). However, it is often more
-useful for the user to be able to specify measurements in other units
-such as centimeters or inches.
-
-<p>A unit is simply a value by which the preceding element is multiplied.
-For example, if the printing has been set up to 300 DPI, one inch is
-then 300 points (dots). Thus saying eg. <code>"5in"</code> is the same as saying
-<code>"5*300"</code> or <code>"1500"</code> (assuming <code>"in"</code> has
-been added as a unit with the value 300).
-
-<p>Note that units are slightly different from a multiplication in
-that they have a higher precedence than any other operator (except
-parentheses). Thus for example <code>"5/2in"</code> is parsed as
-<code>"5/(2*300)"</code>.
-(If 5/2 inches is what one wants, it has to be written <code>"(5/2)in"</code>.)
-
-<p>You can use the <code>AddUnit()</code> method to add a new unit. The
-unit can then be used after any element in the function (and will work as
-a multiplier for that element). An element is a float literal, a constant,
-a variable, a function or any expression in parentheses. When the element
-is not a float literal nor an expression in parentheses, there has to naturally
-be at least one whitespace between the element and the unit (eg.
-<code>"x in"</code>). To change the value of a unit, call
-<code>AddUnit()</code> again with the same unit name and the new value.
-
-<p>Unit names share the same namespace as constants, functions and
- variables, and thus should be distinct from those.
-
-<p>Example: <code>parser.AddUnit("in", 300);</code>
-
-<p>Now for example the function <code>"5in"</code> will be identical to
-<code>"(5*300)"</code>. Other usage examples include <code>"x in"</code>,
-<code>"3in+2"</code>, <code>"pow(x,2)in"</code>, <code>"(x+2)in"</code>.
-
-
-<hr>
-<a name="longdesc_AddFunction1"></a>
-<pre>
-bool AddFunction(const std::string& name,
- double (*functionPtr)(const double*),
- unsigned paramsAmount);
-</pre>
-
-This method can be used to add new functions to the parser. For example,
-if you would like to add a function "<code>sqr(A)</code>" which squares the
-value of <code>A</code>, you can do it with this method (so that you don't
-need to touch the source code of the parser).
-
-<p>The method takes three parameters:
-
-<ul>
- <li>The name of the function. The name follows the same naming conventions
- as variable names.
-
- <li>A C++ function, which will be called when evaluating the function
- string (if the user-given function is called there). The C++ function
- must have the form:
- <p><code>double functionName(const double* params);</code>
-
- <li>The number of parameters the function takes. 0 is a valid value
- in which case the function takes no parameters (such function
- should simply ignore the <code>double*</code> it gets as a parameter).
-</ul>
-
-<p>The return value will be <code>false</code> if the given name was invalid
-(either it did not follow the variable naming conventions, or the name was
-already reserved), else <code>true</code>. If the return value is
-<code>false</code>, nothing is added.
-
-<p>Example: Suppose we have a C++ function like this:
-
-<p><code>double Square(const double* p)</code><br>
-<code>{</code><br>
-<code> return p[0]*p[0];</code><br>
-<code>}</code>
-
-<p>Now we can add this function to the parser like this:
-
-<p><code>parser.AddFunction("sqr", Square, 1);</code><br>
-<code>parser.Parse("2*sqr(x)", "x");</code>
-
-<p>An example of a useful function taking no parameters is a function
- returning a random value. For example:
-
-<p><code>double Rand(const double*)</code><br>
-<code>{</code><br>
-<code> return drand48();</code><br
-<code>}</code>
-
-<p><code>parser.AddFunction("rand", Rand, 0);</code>
-
-<p><em>Important note</em>: If you use the <code>Optimize()</code> method,
-it will assume that the user-given function has no side-effects, that is,
-it always returns the same value for the same parameters. The optimizer will
-optimize the function call away in some cases, making this assumption.
-(The <code>Rand()</code> function given as example above is one such
-problematic case.)
-
-
-<hr>
-<a name="longdesc_AddFunction2"></a>
-<pre>
-bool AddFunction(const std::string& name, FunctionParser&);
-</pre>
-
-<p>This method is almost identical to the previous <code>AddFunction()</code>,
-but instead of taking a C++ function, it takes another FunctionParser
-instance.
-
-<p>There are some important restrictions on making a FunctionParser instance
- call another:
-
-<ul>
- <li>The FunctionParser instance given as parameter must be initialized
- with a <code>Parse()</code> call before giving it as parameter. That
- is, if you want to use the parser <code>A</code> in the parser
- <code>B</code>, you must call <code>A.Parse()</code> before you can
- call <code>B.AddFunction("name", A)</code>.
-
- <li>The amount of variables in the FunctionParser instance given as
- parameter must not change after it has been given to the
- <code>AddFunction()</code>
- of another instance. Changing the number of variables will result in
- malfunction.
-
- <li><code>AddFunction()</code> will fail (ie. return <code>false</code>)
- if a recursive loop is
- formed. The method specifically checks that no such loop is built.
-
- <li>The FunctionParser instance given as parameter will <em>not</em> be
- copied internally, only referenced. Thus the FunctionParser instance
- given as parameter must exist for as long as the other FunctionParser
- instance uses it.
-</ul>
-
-<p>Example:
-
-<p><code>FunctionParser f1, f2;</code><br>
-<p><code>f1.Parse("x*x", "x");</code><br>
-<p><code>f2.AddFunction("sqr", f1);</code>
-
-<p>This version of the <code>AddFunction()</code> method can be useful to
-eg. chain user-given functions. For example, ask the user for a function F1,
- and then ask the user another function F2, but now the user can
- call F1 in this second function if he wants (and so on with a third
- function F3, where he can call F1 and F2, etc).
-
-<hr>
-<a name="longdesc_AddFunction3"></a>
-<pre>
-template<typename DerivedWrapper>
-bool AddFunctionWrapper(const std::string& name, const DerivedWrapper&,
- unsigned paramsAmount);
-</pre>
-
-<p>See section on <a href="#functionobjects">specialized function objects</a>.
-
-<hr>
-<a name="longdesc_RemoveIdentifier"></a>
-<pre>
-bool RemoveIdentifier(const std::string& name);
-</pre>
-
-<p>If a constant, unit or user-defined function with the specified name
-exists in the parser, it will be removed and the return value will be
-<code>true</code>, else nothing will be done and the return value will be
-<code>false</code>.
-
-<p>(Note: If you want to remove <em>everything</em> from an existing
-FunctionParser instance, simply assign a fresh instance to it, ie. like
-"<code>parser = FunctionParser();</code>")
-
-<hr>
-<a name="longdesc_ParseAndDeduceVariables"></a>
-<pre>
-int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
-int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-</pre>
-
-<p>These functions work in the same way as the <code>Parse()</code> function,
-but the variables in the input function string are deduced automatically. The
-parameters are:
-
-<ul>
- <li><code>function</code>: The input function string, as with
- <code>Parse()</code>.
- <li><code>amountOfVariablesFound</code>: If non-null, the amount of found
- variables will be assigned here.
- <li><code>resultVarString</code>: The found variables will be written to
- this string, in the same format as accepted by the <code>Parse()</code>
- function. The variable names will be sorted using the <code><</code>
- operator of <code>std::string</code>.
- <li><code>resultVars</code>: The found variables will be written to this
- vector, each element being one variable name. They will be sorted using
- the <code><</code> operator of <code>std::string</code>. (The amount
- of found variables can be retrieved, rather obviously, with the
- <code>size()</code> method of the vector.)
- <li><code>useDegrees</code>: As with <code>Parse()</code>.
-</ul>
-
-<p>As with <code>Parse()</code>, the return value will be <code>-1</code> if
-the parsing succeeded, else an index to the location of the error. None of
-the specified return values will be modified in case of error.
-
-<!-- -------------------------------------------------------------------- -->
-<a name="functionobjects"></a>
-<h3>Specialized function objects</h3>
-
-<p>The <code>AddFunction()</code> method can be used to add a new user-defined
-function to the parser, its implementation being called through a C++ function
-pointer. Sometimes this might not be enough, though. For example, one might
-want to use <code>boost::function</code> or other similar specialized stateful
-function objects instead of raw function pointers. This library provides a
-mechanism to achieve this.
-
-<h4>Creating and adding a specialized function object</h4>
-
-<p>In order to create a specialized function object, create a class derived
-from the <code>FunctionParser::FunctionWrapper</code> class. This class
-declares a virtual function named <code>callFunction</code> that the derived
-class must implement. For example:
-
-<pre>
-class MyFunctionWrapper:
- public FunctionParser::FunctionWrapper
-{
- public:
- virtual double callFunction(const double* values)
- {
- // Perform the actual function call here, like:
- return someFunctionSomewhere(values);
-
- // In principle the result could also be
- // calculated here, like for example:
- return values[0] * values[0];
- }
-};
-</pre>
-
-<p>You can then add an instance of this class to <code>FunctionParser</code>
-using the <code>AddFunctionWrapper()</code> method, which works like
-<code>AddFunction()</code>, but takes a wrapper object instead of a function
-pointer as parameter. For example:
-
-<pre>
-MyFunctionWrapper wrapper;
-parser.AddFunctionWrapper("funcName", wrapper, 1);
-</pre>
-
-<p>Note that <code>FunctionParser</code> will internally create a copy of
-the wrapper object, managing the lifetime of this copy, and thus the object
-given as parameter does not need to exist for as long as the
-<code>FunctionParser</code> instance. Hence the above could also be written as:
-
-<pre>
-parser.AddFunctionWrapper("funcName", MyFunctionWrapper(), 1);
-</pre>
-
-<p>Note that this also means that the wrapper class must have a working
-copy constructor.
-
-<p>Also note that if the <code>FunctionParser</code> instance is copied, all
-the copies will share the same function wrapper objects given to the original.
-
-<h4>Retrieving specialized function objects</h4>
-
-<p>As noted, the library will internally make a copy of the wrapper object,
-and thus it will be separate from the one which was given as parameter to
-<code>AddFunctionWrapper()</code>. In some cases it may be necessary to
-retrieve this wrapper object (for example to read or change its state).
-This can be done with the <code>GetFunctionWrapper()</code> method, which
-takes the name of the function and returns a pointer to the wrapper object,
-or null if no such object exists with that name.
-
-<p>Note that the returned pointer will be of type
-<code>FunctionParser::FunctionWrapper</code>. In order to get a pointer to
-the actual derived type, the calling code should perform a
-<code>dynamic_cast</code>, for example like this:
-
-<pre>
-MyFunctionWrapper* wrapper =
- dynamic_cast<MyFunctionWrapper*>
- (parser.GetFunctionWrapper("funcName"));
-
-if(!wrapper) { /* oops, the retrieval failed */ }
-else ...
-</pre>
-
-<p>(Using dynamic cast rather than a static cast adds safety because if you
-accidentally try to downcast to the wrong type, the pointer will become null.)
-
-<p>The calling code is free to modify the object in any way it wants, but it
-must not delete it (because <code>FunctionParser</code> itself handles this).
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="base"></a>
-<h3>FunctionParserBase</h3>
-
-<p>All the different parser types are derived from a templated base class
-named <code>FunctionParserBase</code>. In normal use it's not necessary to
-directly refer to this base class in the calling code. However, if the calling
-code also needs to be templated (with respect to the numerical type), then
-using <code>FunctionParserBase</code> directly is the easiest way to achieve
-this.
-
-<p>For example, if you want to make a function that handles more than one
-type of parser, it can be done like this:
-
-<pre>
-template<typename Value_t>
-void someFunction(FunctionParserBase<Value_t>& parser)
-{
- // do something with 'parser' here
-}
-</pre>
-
-<p>Now it's convenient to call that function with more than one type of
-parser, for example:
-
-<pre>
-FunctionParser realParser;
-FunctionParser_cd complexParser;
-
-someFunction(realParser);
-someFunction(complexParser);
-</pre>
-
-<p>Another example is a class that inherits from <code>FunctionParser</code>
-which also wants to support different numerical types. Such class can be
-declared as:
-
-<pre>
-template<typename Value_t>
-class SpecializedParser: public FunctionParserBase<Value_t>
-{
- ...
-};
-</pre>
-
-
-<!-- -------------------------------------------------------------------- -->
-<h2>Syntax</h2>
-
-<a name="literals"></a>
-<h3>Numeric literals</h3>
-
-<p>A numeric literal is a fixed numerical value in the input function string
- (either a floating point value or an integer value, depending on the parser
- type).
-
-<p>An integer literal can consist solely of numerical digits (possibly with
- a preceding unary minus). For example, "<code>12345</code>".
-
-<p>If the literal is preceded by the characters "<code>0x</code>", it
- will be interpreted as a hexadecimal literal, where digits can also include
- the letters from '<code>A</code>' to '<code>F</code>' (in either uppercase
- or lowercase). For example, "<code>0x89ABC</code>" (which corresponds to the
- value 563900).
-
-<p>A floating point literal (only supported by the floating point type parsers)
- may additionally include a decimal point followed by the decimal part of the
- value, such as for example "<code>12.34</code>", optionally followed by a
- decimal exponent.
-
-<p>A decimal exponent consists of an '<code>E</code>' or '<code>e</code>',
- followed by an optional plus or minus sign, followed by decimal digits, and
- indicates multiplication by a power of 10. For example, "<code>1.2e5</code>"
- (which is equivalent to the value 120000).
-
-<p>If a floating point literal is preceded by the characters "<code>0x</code>"
- it will be interpreted in hexadecimal. A hexadecimal floating point
- literal consists of a hexadecimal value, with an optional decimal point,
- followed optionally by a binary exponent in base 10 (in other words, the
- exponent is not in hexadecimal).
-
-<p>A binary exponent has the same format as a decimal exponent, except that
- '<code>P</code>' or '<code>p</code>' is used. A binary exponent indicates
- multiplication by a power of 2. For example, "<code>0xA.Bp10</code>"
- (which is equivalent to the value 10944).
-
-<p>With the complex versions of the library, the imaginary part of a numeric
- literal is written as a regular numeric literal with an '<code>i</code>'
- appended, for example "<code>5i</code>". Note that when also specifying
- the real part of a complex literal, parentheses should be used to avoid
- precedence problems. (For example, "<code>(2+5i) * x</code>"
- is not the same thing as "<code>2+5i * x</code>". The latter
- would be equivalent to "<code>2 + (5i * x)</code>".)
-
-<a name="identifiers"></a>
-<h3>Identifier names</h3>
-
-<p>An identifier is the name of a function (internal or user-defined),
- variable, constant or unit. New identifiers can be specified with the
- functions described in the earlier subsections in this document.
-
-<p>The name of an identifier can use any alphanumeric characters, the
- underscore character and any UTF8-encoded unicode character, excluding
- those denoting whitespace.
- The first character of the name cannot be a numeric digit, though.
-
-<p>All functions, variables, constants and units must use unique names.
- It's not possible to add two different identifiers with the same name.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="functionsyntax"></a>
-<h3>The function string syntax</h3>
-
-<p>The function string understood by the class is very similar (but not
-completely identical in all aspects) to mathematical expressions in the
-C/C++ languages.
-Arithmetic float expressions can be created from float literals, variables
-or functions using the following operators in this order of precedence:
-
-<p><table border=2>
- <tr>
- <td><code>()</code></td>
- <td>expressions in parentheses first</td>
- </tr><tr>
- <td><code>A unit</code></td>
- <td>a unit multiplier (if one has been added)</td>
- </tr><tr>
- <td><code>A^B</code></td>
- <td>exponentiation (A raised to the power B)</td>
- </tr><tr>
- <td><code>-A</code></td>
- <td>unary minus</td>
- </tr><tr>
- <td><code>!A</code></td>
- <td>unary logical not (result is 1 if <code>int(A)</code> is 0, else 0)</td>
- </tr><tr>
- <td><code>A*B A/B A%B</code></td>
- <td>multiplication, division and modulo</td>
- </tr><tr>
- <td><code>A+B A-B</code></td>
- <td>addition and subtraction</td>
- </tr><tr>
- <td><code>A=B A<B A<=B<br>A!=B A>B A>=B</code></td>
- <td>comparison between A and B (result is either 0 or 1)</td>
- </tr><tr>
- <td><code>A&B</code></td>
- <td>result is 1 if <code>int(A)</code> and <code>int(B)</code> differ from
- 0, else 0.<br>
- Note: Regardless of the values, both operands are always
- evaluated. However, if the expression is optimized, it may
- be changed such that only one of the operands is evaluated,
- according to standard shortcut logical operation semantics.</td>
- </tr><tr>
- <td><code>A|B</code></td>
- <td>result is 1 if <code>int(A)</code> or <code>int(B)</code> differ from 0,
- else 0.<br>
- Note: Regardless of the values, both operands are always
- evaluated. However, if the expression is optimized, it may
- be changed such that only one of the operands is evaluated,
- according to standard shortcut logical operation semantics.</td>
- </tr>
-</table>
-
-<p>(Note that currently the exponentiation operator is not supported for
- <code>FunctionParser_li</code> nor <code>FunctionParser_gmpint</code>.
- With the former the result would very easily overflow, making its
- usefulness questionable. With the latter it could be easily abused to
- make the program run out of memory; think of a function like
- "10^10^10^100000".)
-
-<p>Since the unary minus has higher precedence than any other operator, for
- example the following expression is valid: <code>x*-y</code>
-
-<p>The comparison operators use an epsilon value, so expressions which may
-differ in very least-significant digits should work correctly. For example,
-<code>"0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = 1"</code> should always
-return 1, and the same comparison done with "<code>></code>" or
-"<code><</code>" should always return 0. (The epsilon value can be
-configured in the <code>fpconfig.hh</code> file.)
-Without epsilon this comparison probably returns the wrong value.
-
-<p>The class supports these functions:
-
-<p><table border=2>
-<tr>
- <td><code>abs(A)</code></td>
- <td>Absolute value (magnitude) of A.
- With real numbers, if A is negative, returns -A otherwise returns A.
- With complex numbers, equivalent to <code>hypot(real(x),imag(x))</code>.</td>
-</tr><tr>
- <td><code>acos(A)</code></td>
- <td>Arc-cosine of A. Returns the angle, measured in radians, whose cosine is A.</td>
-</tr><tr>
- <td><code>acosh(A)</code></td>
- <td>Same as acos() but for hyperbolic cosine.</td>
-</tr><tr>
- <td><code>arg(A)</code></td>
- <td>Phase angle of complex number A. Equivalent to <code>atan2(imag(x),real(x))</code>.</td>
-</tr><tr>
- <td><code>asin(A)</code></td>
- <td>Arc-sine of A. Returns the angle, measured in radians, whose sine is A.</td>
-</tr><tr>
- <td><code>asinh(A)</code></td>
- <td>Same as asin() but for hyperbolic sine.</td>
-</tr><tr>
- <td><code>atan(A)</code></td>
- <td>Arc-tangent of (A). Returns the angle, measured in radians,
- whose tangent is A.</td>
-</tr><tr>
- <td><code>atan2(A,B)</code></td>
- <td>Principal arc-tangent of A/B, using the signs of the
- two arguments to determine the quadrant of the result.
- Returns the solution to the two expressions
- hypot(A,B)*sin(x)=A, hypot(A,B)*cos(x)=B.
- The return value is in range -pi to pi, inclusive.</td>
-</tr><tr>
- <td><code>atanh(A)</code></td>
- <td>Same as atan() but for hyperbolic tangent.</td>
-</tr><tr>
- <td><code>cbrt(A)</code></td>
- <td>Cube root of A. Returns a solution to expression pow(x,3)=A.</td>
-</tr><tr>
- <td><code>conj(A)</code></td>
- <td>Complex conjugate of A. Equivalent to <code>real(x) - 1i*imag(x)</code> or <code>polar(abs(x),-arg(x))</code>.</td>
-</tr><tr>
- <td><code>ceil(A)</code></td>
- <td>Ceiling of A. Returns the smallest integer not smaller than A.
- Rounds up to the next higher integer. E.g. -2.9, -2.5 and -2.1 are
- rounded to -2.0, and 2.9, 2.5 and 2.1 are rounded to 3.0.</td>
-</tr><tr>
- <td><code>cos(A)</code></td>
- <td>Cosine of A. Returns the cosine of the angle A, where A is
- measured in radians.</td>
-</tr><tr>
- <td><code>cosh(A)</code></td>
- <td>Same as cos() but for hyperbolic cosine.</td>
-</tr><tr>
- <td><code>cot(A)</code></td>
- <td>Cotangent of A. Equivalent to <code>1/tan(A)</code>.</td>
-</tr><tr>
- <td><code>csc(A)</code></td>
- <td>Cosecant of A. Equivalent to <code>1/sin(A)</code>.</td>
-</tr><tr>
- <td><code>eval(...)</code></td>
- <td>This a recursive call to the function to be evaluated. The
- number of parameters must be the same as the number of parameters
- taken by the function. Must be called inside <code>if()</code> to avoid
- infinite recursion.</td>
-</tr><tr>
- <td><code>exp(A)</code></td>
- <td>Exponential of A. Returns the value of e raised to the power
- A where e is the base of the natural logarithm, i.e. the
- non-repeating value approximately equal to 2.71828182846.</td>
-</tr><tr>
- <td><code>exp2(A)</code></td>
- <td>Base 2 exponential of A. Equivalent to <code>pow(2,A)</code>.</td>
-</tr><tr>
- <td><code>floor(A)</code></td>
- <td>Floor of A. Returns the largest integer not greater than A. Rounds
- down to the next lower integer.
- E.g. -2.9, -2.5 and -2.1 are rounded to -3.0,
- and 2.9, 2.5 and 2.1 are rounded to 2.0.</td>
-</tr><tr>
- <td><code>hypot(A,B)</code></td>
- <td>Euclidean distance function. Equivalent to <code>sqrt(A^2+B^2)</code>.</td>
-</tr><tr>
- <td><code>if(A,B,C)</code></td>
- <td>If int(A) differs from 0, the return value of this function is B,
- else C. Only the parameter which needs to be evaluated is
- evaluated, the other parameter is skipped; this makes it safe to
- use <code>eval()</code> in them.</td>
-</tr><tr>
- <td><code>imag(A)</code></td>
- <td>Return the imaginary part of complex number A. Equivalent to <code>abs(A)*sin(arg(A))</code>.</td>
-</tr><tr>
- <td><code>int(A)</code></td>
- <td>Rounds A to the closest integer. Equidistant values are rounded away from
- zero. E.g. -2.9 and -2.5 are rounded to -3.0; -2.1 is rounded to -2.0,
- and 2.9 and 2.5 are rounded to 3.0; 2.1 is rounded to 2.0.</td>
-</tr><tr>
- <td><code>log(A)</code></td>
- <td>Natural (base e) logarithm of A. Returns the solution to expression exp(x)=A.</td>
-</tr><tr>
- <td><code>log2(A)</code></td>
- <td>Base 2 logarithm of A. Equivalent to <code>log(A)/log(2)</code>.</td>
-</tr><tr>
- <td><code>log10(A)</code></td>
- <td>Base 10 logarithm of A.</td>
-</tr><tr>
- <td><code>max(A,B)</code></td>
- <td>If A>B, the result is A, else B.</td>
-</tr><tr>
- <td><code>min(A,B)</code></td>
- <td>If A<B, the result is A, else B.</td>
-</tr><tr>
- <td><code>polar(A,B)</code></td>
- <td>Returns a complex number from magnitude A, phase angle B (in radians).
- Equivalent to <code>real(A)*(cos(real(B))+1i*sin(real(B)))</code>.</td>
-</tr><tr>
- <td><code>pow(A,B)</code></td>
- <td>Exponentiation (A raised to the power B).</td>
-</tr><tr>
- <td><code>real(A)</code></td>
- <td>Return the real part of complex number A. Equivalent to <code>abs(A)*cos(arg(A))</code>.</td>
-</tr><tr>
- <td><code>sec(A)</code></td>
- <td>Secant of A. Equivalent to <code>1/cos(A)</code>.</td>
-</tr><tr>
- <td><code>sin(A)</code></td>
- <td>Sine of A. Returns the sine of the angle A, where A is
- measured in radians.</td>
-</tr><tr>
- <td><code>sinh(A)</code></td>
- <td>Same as sin() but for hyperbolic sine.</td>
-</tr><tr>
- <td><code>sqrt(A)</code></td>
- <td>Square root of A. Returns a solution to expression pow(x,2)=A.</td>
-</tr><tr>
- <td><code>tan(A)</code></td>
- <td>Tangent of A. Returns the tangent of the angle A, where A
- is measured in radians.</td>
-</tr><tr>
- <td><code>tanh(A)</code></td>
- <td>Same as tan() but for hyperbolic tangent.</td>
-</tr><tr>
- <td><code>trunc(A)</code></td>
- <td>Truncated value of A. Returns an integer corresponding to the value
- of A without its fractional part.
- E.g. -2.9, -2.5 and -2.1 are rounded to -2.0,
- and 2.9, 2.5 and 2.1 are rounded to 2.0.</td>
-</tr>
-</table>
-
-<p>(Note that for <code>FunctionParser_li</code> and
- <code>FunctionParser_gmpint</code> only the functions
- <code>abs()</code>, <code>eval()</code>, <code>if()</code>,
- <code>min()</code> and <code>max()</code> are supported.)
-
-<p>Examples of function string understood by the class:
-
-<p><code>"1+2"</code><br>
-<code>"x-1"</code><br>
-<code>"-sin(sqrt(x^2+y^2))"</code><br>
-<code>"sqrt(XCoord*XCoord + YCoord*YCoord)"</code><br>
-
-<p>An example of a recursive function is the factorial function:
-
-<code>"if(n>1, n*eval(n-1), 1)"</code>
-
-<p>Note that a recursive call has some overhead, which makes it a bit slower
- than any other operation. It may be a good idea to avoid recursive functions
- in very time-critical applications. Recursion also takes some memory, so
- extremely deep recursions should be avoided (eg. millions of nested recursive
- calls).
-
-<p>Also note that even though the maximum recursion level of
-<code>eval()</code> is limited, it is possible to write functions which
-never reach that level but still take enormous amounts of time to evaluate.
-This can sometimes be undesirable because it is prone to exploitation,
-which is why <code>eval()</code> is disabled by default. It can be enabled
-in the <code>fpconfig.hh</code> file.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="inlinevars"></a>
-<h3>Inline variables</h3>
-
-<p>The function syntax supports defining new variables inside the function
-string itself. This can be done with the following syntax:
-
-<p><code>"<variable name> := <expression>; <function>"</code>
-
-<p>For example:
-
-<p><code>"length := sqrt(x*x+y*y); 2*length*sin(length)"</code>
-
-<p>(Spaces around the '<code>:=</code>' operator are optional.)
-
-<p>The obvious benefit of this is that if a long expression needs to be
-used in the function several times, this allows writing it only once and
-using a named variable from that point forward.
-
-<p>The variable name must be an unused identifier (in other words, not an
-existing function, variable or unit name).
-
-<p>The <code><function></code> part can have further inline variable
-definitions, and thus it's possible to have any amount of them, for example:
-
-<p><code>"A := x^2; B := y^2; C := z^2; sqrt(A+B+C)"</code>
-
-<p>The expressions in subsequent inline variable definitions can use any
-of the previous inline variables. It is also possible to redefine an inline
-variable. For example:
-
-<p><code>"A := x^2; A := 2*A; sqrt(A)"</code>
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="whitespace"></a>
-<h3>Whitespace</h3>
-
-<p>Arbitrary amounts of whitespace can optionally be included between
- elements in the function string.
- The following unicode characters are interpreted as whitespace:
-<table>
- <tr>
- <th>Character number</th>
- <th>Character name</th>
- <th>UTF-8 byte sequence</th>
- </tr>
- <tr><td>U+0009</td><td>HORIZONTAL TABULATION </td><td>09</td></tr>
- <tr><td>U+000A</td><td>LINE FEED </td><td>0A</td></tr>
- <tr><td>U+000B</td><td>VERTICAL TABULATION </td><td>0B</td></tr>
- <tr><td>U+000D</td><td>CARRIAGE RETURN </td><td>0D</td></tr>
- <tr><td>U+0020</td><td>SPACE </td><td>20</td></tr>
- <tr><td>U+00A0</td><td>NO-BREAK SPACE </td><td>C2 A0</td></tr>
- <tr><td>U+2000</td><td>EN QUAD </td><td>E2 80 80</td></tr>
- <tr><td>U+2001</td><td>EM QUAD </td><td>E2 80 81</td></tr>
- <tr><td>U+2002</td><td>EN SPACE </td><td>E2 80 82</td></tr>
- <tr><td>U+2003</td><td>EM SPACE </td><td>E2 80 83</td></tr>
- <tr><td>U+2004</td><td>THREE-PER-EM SPACE </td><td>E2 80 84</td></tr>
- <tr><td>U+2005</td><td>FOUR-PER-EM SPACE </td><td>E2 80 85</td></tr>
- <tr><td>U+2006</td><td>SIX-PER-EM SPACE </td><td>E2 80 86</td></tr>
- <tr><td>U+2007</td><td>FIGURE SPACE </td><td>E2 80 87</td></tr>
- <tr><td>U+2008</td><td>PUNCTUATION SPACE </td><td>E2 80 88</td></tr>
- <tr><td>U+2009</td><td>THIN SPACE </td><td>E2 80 89</td></tr>
- <tr><td>U+200A</td><td>HAIR SPACE </td><td>E2 80 8A</td></tr>
- <tr><td>U+200B</td><td>ZERO WIDTH SPACE </td><td>E2 80 8B</td></tr>
- <tr><td>U+202F</td><td>NARROW NO-BREAK SPACE </td><td>E2 80 AF</td></tr>
- <tr><td>U+205F</td><td>MEDIUM MATHEMATICAL SPACE</td><td>E2 81 9F</td></tr>
- <tr><td>U+3000</td><td>IDEOGRAPHIC SPACE </td><td>E3 80 80</td></tr>
-</table>
-
-<!-- -------------------------------------------------------------------- -->
-<h2>Miscellaneous</h2>
-
-<a name="fpaccuracy"></a>
-<h3>About floating point accuracy</h3>
-
-<p>Note that if you are using <code>FunctionParser_ld</code> or
-<code>FunctionParser_cld</code> and you want calculations to be as accurate
-as the <code>long double</code> type allows, you should pay special attention
-to floating point literals in your own code. For example, this is a very
-typical mistake:
-
-<pre>FunctionParser_ld parser;
-parser.AddConstant("pi", 3.14159265358979323846);</pre>
-
-<p>The mistake might not be immediately apparent. The mistake is that a
-literal of type <code>double</code> is passed to the <code>AddConstant()</code>
-function even though it expects a value of type <code>long double</code>.
-In most systems the latter has more bits of precision than the former, which
-means that the value will have its least-significant bits clipped,
-introducing a rounding error. The proper way of making the above calls is:
-
-<pre>FunctionParser_ld parser;
-parser.AddConstant("pi", 3.14159265358979323846L);</pre>
-
-<p>The same principle should be used everywhere in your own code, if you are
-using the <code>long double</code> type.
-
-<p>This is especially important if you are using the <code>MpfrFloat</code>
-type (in which case its string-parsing constructor or its
-<code>ParseValue()</code> or <code>parseString()</code> member functions
-should be used instead of using numerical literals).
-
-<a name="evaluationchecks"></a>
-<h3>About evaluation-time checks</h3>
-
-<p><code>FunctionParser::Eval()</code> will perform certain sanity
-checks before performing certain operations. For example, before calling the
-<code>sqrt</code> function, it will check if the parameter is negative, and
-if so, it will set the proper error code instead of calling the function.
-These checks include:
-
-<ul>
- <li>Division by (the exact value of) zero.
- <li>Square root of a negative value.
- <li>Logarithm of a non-positive value.
- <li>Arcsine or arccosine of a value not in the range [-1, 1]. (This includes
- hyperbolic versions of the functions.)
-</ul>
-
-<p>However, the library <em>can not</em> guarantee that it will catch all
-possible floating point errors before performing them, because this is
-impossible to do with standard C++. For example, dividing a very large
-value by a value which is very close to zero, or calculating the logarithm
-of a very small value may overflow the result, as well as multiplying two
-very large values. Raising a negative number to a non-integral power may
-cause a <em>NaN</em> result, etc.
-
-<p>As a rule of thumb, the library will (by default) detect invalid operations
-if they are invalid for a range of values. For example, square root is undefined
-for all negative values, and arc sine is undefined only values outside the range
-[-1, 1]. In general, operations which are invalid for only one single value
-(rather than a contiguous range of values) will not be detected (division by
-the exact value of zero is an exception to this rule) nor will
-overflow/underflow situations.
-
-<p>The library cannot guarantee that floating point
-errors will never happen during evaluation. This can make the library to
-return the floating point values <em>inf</em> and <em>NaN</em>. Moreover,
-if floating point errors cause an interrupt in the target computer
-architecture and/or when using certain compiler settings, this library
-cannot guarantee that it will never happen.
-
-<p>Note that the optimizer never performs any sanity checks.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="threadsafety"></a>
-<h3>About thread safety</h3>
-
-<p>None of the member functions of the FunctionParser class are thread-safe.
-Most prominently, the <code>Eval()</code> function is not thread-safe.
-(In other words, the <code>Eval()</code> function of a single FunctionParser
-instance cannot be safely called simultaneously by two threads.)
-
-<p>There are ways to use this library in a thread-safe way, though. If each
-thread uses its own FunctionParser instance, no problems will obviously
-happen. Note, however, that if these instances need to be a copy of a given
-FunctionParser instance (eg. one where the user has entered a function),
-a deep copy of this instance has to be performed for each thread. By
-default FunctionParser uses shallow-copying (copy-on-write), which means
-that a simple assignment of copy construction will not copy the data itself.
-To force a deep copy you can all the <code>ForceDeepCopy()</code> function on
-each of the instances of each thread after the assignment or copying has been
-done.
-
-<p>Another possibility is to compile the FunctionParser library so that
-its <code>Eval()</code> function will be thread-safe. (This can be done by
-defining the <code>FP_USE_THREAD_SAFE_EVAL</code> or the
-<code>FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA</code>
-precompiler constant.) As long as only one thread calls the other functions
-of FunctionParser, the other threads can safely call the <code>Eval()</code>
-of this one instance.
-
-<p>Note, however, that compiling the library like this can make
-<code>Eval()</code> slightly slower. (The <code>alloca</code> version, if
-supported by the compiler, will not be as slow.)
-
-<p>Also note that the MPFR and GMP versions of the library cannot be
- made thread-safe, and thus this setting has no effect on them.
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="tipsandtricks"></a>
-<h3>Tips and tricks</h3>
-
-<h4>Add constants automatically to all parser objects</h4>
-
-<p>Often the same constants (such as <em>pi</em> and <em>e</em>) and other
-user-defined identifiers (such as units) are always used in all the
-<code>FunctionParser</code> objects throughout the program. It would be
-troublesome to always have to manually add these constants every time a
-new parser object is created.
-
-<p>There is, however, a simple way to always add these user-defined identifiers
-to all instances. Write a class like this:
-
-<pre>
- class ParserWithConsts: public FunctionParser
- {
- public:
- ParserWithConsts()
- {
- AddConstant("pi", 3.14159265358979323846);
- AddConstant("e", 2.71828182845904523536);
- }
- };
-</pre>
-
-<p>Now instead of using <code>FunctionParser</code>, always use
-<code>ParserWithConsts</code>. It will behave identically except that the
-constants (and possibly other user-defined identifiers) will always be
-automatically defined. (Objects of this type even survive
-<a href="http://en.wikipedia.org/wiki/Object_slicing">slicing</a>, so
-they are completely safe to use anywhere.)
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="contact"></a>
-<h3>Contacting the author</h3>
-
-<p>Any comments, bug reports, etc. should be sent to warp@iki.fi
-
-
-<!-- -------------------------------------------------------------------- -->
-<!--
-<a name="algorithm"></a>
-<h2>The algorithm used in the library</h2>
-
-<p>The whole idea behind the algorithm is to convert the regular infix
-format (the regular syntax for mathematical operations in most languages,
-like C and the input of the library) to postfix format. The postfix format
-is also called stack arithmetic since an expression in postfix format
-can be evaluated using a stack and operating with the top of the stack.
-
-<p>For example:
-
-<p><table border=2>
-<tr><th>infix</th> <th>postfix</th></tr>
-<tr><td><code>2+3</code></td><td><code>2 3 +</code></td></tr>
-<tr><td><code>1+2+3</code></td><td><code>1 2 + 3 +</code></td></tr>
-<tr><td><code>5*2+8/2</code></td><td><code>5 2 * 8 2 / +</code></td></tr>
-<tr><td><code>(5+9)*3</code></td><td><code>5 9 + 3 *</code></td></tr>
-</table>
-
-<p>The postfix notation should be read in this way:
-
-<p>Let's take for example the expression: <code>5 2 * 8 2 / +</code>
-<ul>
- <li>Put 5 on the stack
- <li>Put 2 on the stack
- <li>Multiply the two values on the top of the stack and put the result on
- the stack (removing the two old values)
- <li>Put 8 on the stack
- <li>Put 2 on the stack
- <li>Divide the two values on the top of the stack
- <li>Add the two values on the top of the stack (which are in this case
- the result of 5*2 and 8/2, that is, 10 and 4).
-</ul>
-
-<p>At the end there's only one value in the stack, and that value is the
-result of the expression.
-
-<p>Why stack arithmetic?
-
-<p>The last example above can give you a hint.
- In infix format operators have precedence and we have to use parentheses to
-group operations with lower precedence to be calculated before operations
-with higher precedence.
- This causes a problem when evaluating an infix expression, specially
-when converting it to byte code. For example in this kind of expression:
- <code>(x+1)/(y+2)</code>
-we have to calculate first the two additions before we can calculate the
-division. We have to also keep counting parentheses, since there can be
-a countless amount of nested parentheses. This usually means that you
-have to do some type of recursion.
-
-<p>The simplest and mostefficient way of calculating this is to convert it
-to postfix notation.
- The postfix notation has the advantage that you can make all operations
-in a straightforward way. You just evaluate the expression from left to
-right, applying each operation directly and that's it. There are no
-parentheses to worry about. You don't need recursion anywhere.
- You have to keep a stack, of course, but that's extremely easily done.
-Also you just operate with the top of the stack, which makes it very easy.
-You never have to go deeper than 2 items in the stack.
- And even better: Evaluating an expression in postfix format is never
-slower than in infix format. All the contrary, in many cases it's a lot
-faster (eg. because all parentheses are optimized away).
- The above example could be expressed in postfix format:
- <code>x 1 + y 2 + /</code>
-
-<p>The good thing about the postfix notation is also the fact that it can
-be extremely easily expressed in bytecode form.
- You only need a byte value for each operation, for each variable and
-to push a constant to the stack.
- Then you can interpret this bytecode straightforwardly. You just interpret
-it byte by byte, from the beginning to the end. You never have to go back,
-make loops or anything.
-
-<p>This is what makes byte-coded stack arithmetic so fast.
--->
-
-
-<!-- -------------------------------------------------------------------- -->
-<a name="license"></a>
-<h2>Usage license</h2>
-
-<p>Copyright © 2003-2011 Juha Nieminen, Joel Yliluoma
-
-<p>This Library is distributed under the
- <a href="http://www.gnu.org/copyleft/lesser.html">Lesser General Public
- License</a> (LGPL) version 3.
-
-</body>
-</html>
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+++ /dev/null
-html
-{
- background-color: #E0E0E0;
-}
-
-body
-{
- background-color: white;
- margin-left: 7%;
- margin-top: 16px;
- margin-right: 7%;
- padding-top: 2em;
- padding-left: 7%;
- padding-right: 7%;
- padding-bottom: 2%;
- border-color: black;
- border: solid;
- border-width: 1px;
-}
-
-h1
-{
- text-align: center;
- background-color: #FFEEBB;
- padding-bottom: 0.2em;
- padding-top: 0.1em;
-}
-
-h2
-{
- background-color: #FFFFCC;
- padding-left: 0.5em;
-}
-
-h3
-{
- background-color: #FFFFEE;
-}
-
-blockquote
-{
- padding-left: 2em;
- padding-right: 2em;
- font-style: italic;
- background-color: #FFFAF0;
-}
-
-li
-{
- padding-top: 0.3em;
-}
-
-pre
-{
- background-color: #E8E8E8;
- padding-left: 1em;
- padding-top: 0.5em;
- padding-bottom: 0.5em;
-}
-
-code
-{
- font-family: monospace;
- color: #900040;
-}
-
-.small
-{
- font-size: 80%;
-}
-
-.codecomment
-{
- color: green;
-}
-
-.highlight
-{
- background: #C0D0FF;
-}
+++ /dev/null
-// Simple example file for the function parser\r
-// ===========================================\r
-\r
-/* When running the program, try for example with these values:\r
-\r
-f(x) = x^2\r
-min x: -5\r
-max x: 5\r
-step: 1\r
-\r
-*/\r
-\r
-#include "../fparser.hh"\r
-\r
-#include <iostream>\r
-#include <string>\r
-\r
-int main()\r
-{\r
- std::string function;\r
- double minx, maxx, step;\r
- FunctionParser fparser;\r
-\r
- fparser.AddConstant("pi", 3.1415926535897932);\r
-\r
- while(true)\r
- {\r
- std::cout << "f(x) = ";\r
- std::getline(std::cin, function);\r
- if(std::cin.fail()) return 0;\r
-\r
- int res = fparser.Parse(function, "x");\r
- if(res < 0) break;\r
-\r
- std::cout << std::string(res+7, ' ') << "^\n"\r
- << fparser.ErrorMsg() << "\n\n";\r
- }\r
-\r
- std::cout << "min x: ";\r
- std::cin >> minx;\r
- std::cout << "max x: ";\r
- std::cin >> maxx;\r
- std::cout << "step: ";\r
- std::cin >> step;\r
- if(std::cin.fail()) return 0;\r
-\r
- double vals[] = { 0 };\r
- for(vals[0] = minx; vals[0] <= maxx; vals[0] += step)\r
- {\r
- std::cout << "f(" << vals[0] << ") = " << fparser.Eval(vals)\r
- << std::endl;\r
- }\r
-\r
- return 0;\r
-}\r
+++ /dev/null
-// Simple example file for the function parser
-// ===========================================
-/* Note that the library has to be compiled with
- FP_SUPPORT_FLOAT_TYPE, FP_SUPPORT_LONG_DOUBLE_TYPE and
- FP_SUPPORT_LONG_INT_TYPE
- preprocessor macros defined for this example to work.
-
- Try with these input values with the different floating point parser
- types to see the difference in accuracy:
-
-f(x) = x + 1.234567890123456789
-min x: 0
-max x: 2
-step: 1
-*/
-
-#include "../fparser.hh"
-
-#include <iostream>
-#include <iomanip>
-#include <string>
-
-template<typename Parser>
-void runExample(const char* valueTypeName)
-{
- typedef typename Parser::value_type Value_t;
-
- std::cout << "Using " << valueTypeName << " parser." << std::endl;
-
- Parser fparser;
- std::string function;
- Value_t minx, maxx, step;
-
- fparser.AddConstant("pi", Value_t(3.1415926535897932));
-
- std::cin.ignore();
- while(true)
- {
- std::cout << "f(x) = ";
- std::getline(std::cin, function);
- if(std::cin.fail()) return;
-
- int res = fparser.Parse(function, "x");
- if(res < 0) break;
-
- std::cout << std::string(res+7, ' ') << "^\n"
- << fparser.ErrorMsg() << "\n\n";
- }
-
- std::cout << "min x: ";
- std::cin >> minx;
- std::cout << "max x: ";
- std::cin >> maxx;
- std::cout << "step: ";
- std::cin >> step;
- if(std::cin.fail()) return;
-
- Value_t vals[] = { 0 };
- for(vals[0] = minx; vals[0] <= maxx; vals[0] += step)
- {
- std::cout << std::setprecision(20);
- std::cout << "f(" << vals[0] << ") = " << fparser.Eval(vals)
- << std::endl;
- }
-}
-
-int main()
-{
- int choice = 0;
- do
- {
- std::cout << "1 = double, 2 = float, 3 = long double, 4 = long int: ";
- std::cin >> choice;
- } while(choice < 1 || choice > 4);
-
- switch(choice)
- {
- case 1: runExample<FunctionParser>("double"); break;
- case 2: runExample<FunctionParser_f>("float"); break;
- case 3: runExample<FunctionParser_ld>("long double"); break;
- case 4: runExample<FunctionParser_li>("long int"); break;
- }
-
- return 0;
-}
+++ /dev/null
-/* NOTE:
- Do not include this file in your project. The fparser.cc file #includes
-this file internally and thus you don't need to do anything (other than keep
-this file in the same directory as fparser.cc).
-
- Part of this file is generated code (by using the make_function_name_parser
-utility, found in the development version of this library). It's not intended
-to be modified by hand.
-*/
-
- unsigned nameLength = 0;
- const unsigned maximumNameLength = 0x80000000U-8;
- /*
- Due to the manner the identifier lengths are returned from
- the readOpcode() function, the maximum supported length for
- identifiers is 0x7FFFFFFF bytes. We minus 8 here to add some
- buffer, because of the multibyteness of UTF-8.
- Function names are limited to 0xFFFF bytes instead, but because
- function names that long just are not defined, the point is moot.
- */
- const unsigned char* const uptr = (const unsigned char*) input;
- typedef signed char schar;
- while(likely(nameLength < maximumNameLength))
- {
- unsigned char byte = uptr[nameLength+0];
- /* Handle the common case of A-Za-z first */
- if(byte >= 0x40)
- {
- if(byte < 0x80) // 0x40..0x7F - most common case
- {
- // Valid characters in 40..7F: A-Za-z_
- // Valid bitmask for 40..5F: 01111111111111111111111111100001
- // Valid bitmask for 60..7F: 01111111111111111111111111100000
- if(sizeof(unsigned long) == 8)
- {
- const unsigned n = sizeof(unsigned long)*8-32;
- // ^ avoids compiler warning when not 64-bit
- unsigned long masklow6bits = 1UL << (byte & 0x3F);
- if(masklow6bits & ~((1UL << 0) | (0x0FUL << (0x1B ))
- | (1UL << n) | (0x1FUL << (0x1B+n))))
- { ++nameLength; continue; }
- }
- else
- {
- unsigned masklow5bits = 1 << (byte & 0x1F);
- if((masklow5bits & ~(1 | (0x1F << 0x1B))) || byte == '_')
- { ++nameLength; continue; }
- }
- break;
- }
- if(byte < 0xF0)
- {
- if(byte < 0xE0)
- {
- if(byte < 0xC2) break; // 0x80..0xC1
- if(byte == 0xC2 && uptr[nameLength+1]==0xA0) break; // skip nbsp
- // C2-DF - next common case when >= 0x40
- // Valid sequence: C2-DF 80-BF
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- nameLength += 2;
- continue;
- }
- if(byte == 0xE0) // E0
- {
- // Valid sequence: E0 A0-BF 80-BF
- if((unsigned char)(uptr[nameLength+1] - 0xA0) > (0xBF-0xA0)) break;
- }
- else
- {
- if(byte == 0xED) break; // ED is invalid
- // Valid sequence: E1-EC 80-BF 80-BF
- // And: EE-EF 80-BF 80-BF
- if(byte == 0xE2)
- {
- // break on various space characters
- if(uptr[nameLength+1] == 0x80
- && (schar(uptr[nameLength+2]) <= schar(0x8B)
- || (uptr[nameLength+2] == 0xAF))) break;
- if(uptr[nameLength+1] == 0x81
- && uptr[nameLength+2] == 0x9F) break;
- } else
- if(byte == 0xE3 && uptr[nameLength+1] == 0x80
- && uptr[nameLength+2] == 0x80) break; // this too
-
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- }
- if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
- nameLength += 3;
- continue;
- }
- if(byte == 0xF0) // F0
- {
- // Valid sequence: F0 90-BF 80-BF 80-BF
- if((unsigned char)(uptr[nameLength+1] - 0x90) > (0xBF-0x90)) break;
- }
- else
- {
- if(byte > 0xF4) break; // F5-FF are invalid
- if(byte == 0xF4) // F4
- {
- // Valid sequence: F4 80-8F
- if(schar(uptr[nameLength+1]) > schar(0x8F)) break;
- }
- else
- {
- // F1-F3
- // Valid sequence: F1-F3 80-BF 80-BF 80-BF
- if(schar(uptr[nameLength+1]) > schar(0xBF)) break;
- }
- }
- if(schar(uptr[nameLength+2]) > schar(0xBF)) break;
- if(schar(uptr[nameLength+3]) > schar(0xBF)) break;
- nameLength += 4;
- continue;
- }
- if(nameLength > 0)
- {
- if(sizeof(unsigned long) == 8)
- {
- // Valid bitmask for 00..1F: 00000000000000000000000000000000
- // Valid bitmask for 20..3F: 00000000000000001111111111000000
- const unsigned n = sizeof(unsigned long)*8-32;
- // ^ avoids compiler warning when not 64-bit
- unsigned long masklow6bits = 1UL << byte;
- if(masklow6bits & (((1UL << 10)-1UL) << (16+n)))
- { ++nameLength; continue; }
- }
- else
- {
- if(byte >= '0' && byte <= '9')
- { ++nameLength; continue; }
- }
- }
- break;
- }
-
- /* This function generated with make_function_name_parser.cc */
-#define lO l3 lH
-#define lN switch(
-#define lM l4 lH
-#define lL if('i' l5
-#define lK 'n' l5
-#define lJ 0x80000003U;
-#define lI l1 3]={
-#define lH case
-#define lG 0x80000005U;
-#define lF )==0)l0(
-#define lE l8 3;}lH
-#define lD std::memcmp(uptr+
-#define lC l2 3 lF
-#define lB lA 1]){lH
-#define lA :lN uptr[
-#define l9 'a' lB
-#define l8 default:l0
-#define l7 lG l0 5;}lH
-#define l6 <<16)|
-#define l5 ==uptr[
-#define l4 lJ l0 3;
-#define l3 0x80000004U;l0 4;
-#define l2 lD 1,tmp,
-#define l1 static const char tmp[
-#define l0 return
-lN
-nameLength){lH
-2:lL
-0]&&'f' l5
-1])l0(cIf
-l6
-0x80000002U;l0
-2;lH
-3
-lA
-0]){lH
-l9'b':if('s' l5
-2])l0(cAbs
-l6
-lM'r':if('g' l5
-2])l0(cArg
-l6
-l4
-lE'c' lB'o' lA
-2]){lH's':l0(cCos
-l6
-lJ
-lH't':l0(cCot
-l6
-lJ
-lE's':if('c' l5
-2])l0(cCsc
-l6
-l4
-lE'e':if('x' l5
-1]&&'p' l5
-2])l0(cExp
-l6
-lM'i':if(lK
-1]&&'t' l5
-2])l0(cInt
-l6
-lM'l':if('o' l5
-1]&&'g' l5
-2])l0(cLog
-l6
-lM'm' lB'a':if('x' l5
-2])l0(cMax
-l6
-lM'i':if(lK
-2])l0(cMin
-l6
-l4
-lE'p':if('o' l5
-1]&&'w' l5
-2])l0(cPow
-l6
-lM's' lB'e':if('c' l5
-2])l0(cSec
-l6
-lM'i':if(lK
-2])l0(cSin
-l6
-l4
-lE't':if('a' l5
-1]&&lK
-2])l0(cTan
-l6
-l4
-lE
-4
-lA
-0]){lH
-l9'c':if('o' l5
-2]&&'s' l5
-3])l0(cAcos
-l6
-lO's':lL
-2]&&lK
-3])l0(cAsin
-l6
-lO't':if('a' l5
-2]&&lK
-3])l0(cAtan
-l6
-l3
-l8
-4;}
-lH'c' lB'b':if('r' l5
-2]&&'t' l5
-3])l0(cCbrt
-l6
-lO'e':lL
-2]&&'l' l5
-3])l0(cCeil
-l6
-lO'o' lA
-2]){lH'n':if('j' l5
-3])l0(cConj
-l6
-lO's':if('h' l5
-3])l0(cCosh
-l6
-l3
-l8
-4;}
-l8
-4;}
-lH'e':{lI'x','p','2'}
-;if(lC
-cExp2
-l6
-l3}
-lH'i':{lI'm','a','g'}
-;if(lC
-cImag
-l6
-l3}
-lH'l':{lI'o','g','2'}
-;if(lC
-cLog2
-l6
-l3}
-lH'r':{lI'e','a','l'}
-;if(lC
-cReal
-l6
-l3}
-lH's' lB'i':if(lK
-2]&&'h' l5
-3])l0(cSinh
-l6
-lO'q':if('r' l5
-2]&&'t' l5
-3])l0(cSqrt
-l6
-l3
-l8
-4;}
-lH't':{lI'a','n','h'}
-;if(lC
-cTanh
-l6
-l3}
-l8
-4;}
-lH
-5
-lA
-0]){lH
-l9'c':{lI'o','s','h'}
-;if(lD
-2,tmp,3
-lF
-cAcosh
-l6
-l7's':{lI'i','n','h'}
-;if(lD
-2,tmp,3
-lF
-cAsinh
-l6
-l7't':if('a' l5
-2]){if(lK
-3]){lN
-uptr[4]){lH'2':l0(cAtan2
-l6
-lG
-lH'h':l0(cAtanh
-l6
-lG
-l8
-5;}
-}
-l0
-5;}
-l0
-5;l8
-5;}
-lH'f':{l1
-4]={'l','o','o','r'}
-;if(l2
-4
-lF
-cFloor
-l6
-l7'h':{l1
-4]={'y','p','o','t'}
-;if(l2
-4
-lF
-cHypot
-l6
-l7'l':{l1
-4]={'o','g','1','0'}
-;if(l2
-4
-lF
-cLog10
-l6
-l7'p':{l1
-4]={'o','l','a','r'}
-;if(l2
-4
-lF
-cPolar
-l6
-l7't':{l1
-4]={'r','u','n','c'}
-;if(l2
-4
-lF
-cTrunc
-l6
-lG
-l0
-5;}
-l8
-5;}
-default:break;}
-l0
-nameLength;
+++ /dev/null
-/* Function Parser for C++ v4.5.1
-
- NOTE:
- Do not include this file in your project. The fparser.cc file #includes
-this file internally and thus you don't need to do anything (other than keep
-this file in the same directory as fparser.cc).
-
- This file contains generated code and is thus not intended to be to
-be modified by hand. It was generated by util/bytecoderules_parser, which
-is available in the development package.
-*/
-#define HasInvalidRangesOpcode HasInvalidRangesOpcode<IsComplexType<Value_t>::result>
-#define FP_TRACE_BYTECODE_OPTIMIZATION(srcline,from,to,with) \
- /*std::cout << "Changing \"" from "\"\t(line " #srcline ")\n" \
- " into \"" to "\"\n" with << std::flush*/
-#define FP_TRACE_OPCODENAME(op) \
- (op < VarBegin \
- ? FP_GetOpcodeName(OPCODE(op)) \
- : findName(mData->mNamePtrs,op,NameData<Value_t>::VARIABLE))
-#define FP_TRACE_BYTECODE_ADD(opcode) \
- /*std::cout << "Adding opcode: " << FP_TRACE_OPCODENAME(opcode) \
- << ", bytecode length " << data->ByteCode.size() \
- << ", pointer is " << (void*)ByteCodePtr \
- << ", code is " << (data->ByteCode.empty() \
- ? (void*)0 \
- : (void*)&data->ByteCode[0]) \
- << std::endl*/
-#define qH1 " B" mF
-#define qG1 gT y*x;
-#define qF1 hV 2;qI
-#define qE1 <<"," aD
-#define qD1 <<"," aB
-#define qC1 "cNeg"
-#define qB1 wA"," aD
-#define qA1 "x[x!=Value_t(0)] "
-#define q91 <<"," a8
-#define q81 wA"," a1
-#define q71 );qW q6
-#define q61 "cPow "
-#define q51 "cSqrt"
-#define q41 "cSqr "
-#define q31 " cExp2"
-#define q21 "cExp "
-#define q11 ){hD wB
-#define q01 "cCeil"
-#define mZ "cImag"
-#define mY "cConj"
-#define mX "cDup "
-#define mW hO wB
-#define mV "cAbs"
-#define mU wQ wH" "
-#define mT qS w2 wB
-#define mS "cFloor"
-#define mR "cTan"
-#define mQ " cDup"
-#define mP "cSin"
-#define mO (y hX;
-#define mN "[ y+x]"
-#define mM hV 2 gC
-#define mL " cExp"
-#define mK "A " wX
-#define mJ "cLess"
-#define mI "[-x]" wH
-#define mH "cDiv" a7
-#define mG "cLog"
-#define mF " cDiv"
-#define mE " " a6
-#define mD " " aF
-#define mC "cMin"
-#define mB "cMax"
-#define mA aY"x "
-#define m9 gN wB
-#define m8 "x cPow"
-#define m7 g1 oG wB
-#define m6 (x);gJ
-#define m5 "B cSqr"
-#define m4 oH dE wB
-#define m3 "[y*x]" wH
-#define m2 "cGreater"
-#define m1 mV" " wL
-#define m0 "cNeg "
-#define aZ " cAdd"
-#define aY "y "
-#define aX "B[IsVarOpcode(B)] "
-#define aW " cSub"
-#define aV gY if(dO wB
-#define aU "cInv"
-#define aT mX aU
-#define aS "cAbsNot"
-#define aR "cLessOrEq"
-#define aQ "cAdd " q51
-#define aP "[y*x] cPow"
-#define aO "cCos"
-#define aN "cLog2"
-#define aM "cCosh"
-#define aL "cLog10"
-#define aK "B[B==A]"
-#define aJ "cNotNot"
-#define aI " " a2
-#define aH "cDup" aZ
-#define aG "cGreaterOrEq"
-#define aF "x" aZ
-#define aE "cEqual"
-#define aD " " aC
-#define aC "A" wY
-#define aB " " wU
-#define aA " cNeg"
-#define a9 " cRDiv"
-#define a8 " B" wY
-#define a7 " x" wH
-#define a6 "cRSub"
-#define a5 "A[IsVarOpcode(A)]"
-#define a4 "x[x!=Value_t()] "
-#define a3 " " a5" "
-#define a2 " with" aD
-#define a1 " " wG
-#define a0 " cNot"
-#define wZ "x[x==Value_t()]" wH
-#define wY " " wC
-#define wX "[x]" wH
-#define wW "cNEqual"
-#define wV a5 mF
-#define wU "x = "<<x
-#define wT "x[isInteger(x)] cPow"
-#define wS a5 wH
-#define wR "x[x!=Value_t(0)]" mF
-#define wQ "x[x>Value_t(0)]"
-#define wP "B[IsNeverNegativeValueOpcode(B)] "
-#define wO "x[x==Value_t(1)] "
-#define wN wA"\n"
-#define wM <<"\n"
-#define wL "x[x==Value_t(0)] "
-#define wK "B[IsBinaryOpcode(B)&&!HasInvalidRangesOpcode(B)] " wD
-#define wJ "A[IsNeverNegativeValueOpcode(A)] "
-#define wI "A[IsVarOpcode(A)&&mData->mByteCode.size()>2] "
-#define wH " cMul"
-#define wG aY"= "<<y wM
-#define wF " x A[IsComparisonOpcode(A)]"
-#define wE FP_TRACE_BYTECODE_ADD
-#define wD "A[IsBinaryOpcode(A)&&!HasInvalidRangesOpcode(A)] " wZ
-#define wC "= "<<FP_TRACE_OPCODENAME
-#define wB FP_TRACE_BYTECODE_OPTIMIZATION
-#define wA " with" aB<<
-#define w9 qT q6:
-#define w8 cEqual
-#define w7 Lbd gY
-#define w6 Lcb gY
-#define w5 opcode
-#define w4 B==A){
-#define w3 q5 q4
-#define w2 cExp:
-#define w1 qO A qP
-#define w0 qO h2
-#define oZ qF g1
-#define oY if dC
-#define oX fp_pow(
-#define oW fp_log(
-#define oV 3 gC A
-#define oU x==g1 oG
-#define oT gX Lml;
-#define oS q4 Lbo
-#define oR 3 gH
-#define oQ cSinh:
-#define oP g1 0)
-#define oO 0.5)){
-#define oN Ldn;qT
-#define oM ]==h3){
-#define oL qY g8 0
-#define oK .size()
-#define oJ );qE
-#define oI A oJ dU
-#define oH g7 A=
-#define oG 1)){
-#define oF qU hI
-#define oE Lbo oF
-#define oD qT hM hB
-#define oC qL 3]
-#define oB :hC qQ oC
-#define oA cSub oB d3 hJ
-#define o9 q7=-x
-#define o8 gX Loi;
-#define o7 );qF
-#define o6 qE A o7
-#define o5 h3 d4 qL
-#define o4 fp_log2(
-#define o3 ==cSqr){
-#define o2 qT cSqr:
-#define o1 cGreater
-#define o0 Default6
-#define dZ Default5
-#define dY Default2
-#define dX Default1
-#define dW ImmedPtr
-#define dV gA qZ qC
-#define dU h3);
-#define dT gC dU
-#define dS cNotNot
-#define dR fp_log10(
-#define dQ cAbs);
-#define dP fp_abs(x)
-#define dO x>oP){
-#define dN mImmed
-#define dM qE h3 gX
-#define dL qK dJ w3
-#define dK cGreaterOrEq
-#define dJ =q6;
-#define dI qK dJ g6
-#define dH Value_t
-#define dG q8 2 gH q4
-#define dF q0[0]
-#define dE qK qR qX
-#define dD qK qR IsLogicalOpcode(h2
-#define dC (qK==
-#define dB hB oY
-#define dA qY g8 oG
-#define d9 pop_back()
-#define d8 q6;q1 h3 gI
-#define d7 q8 2 gC
-#define d6 hR Lba;
-#define d5 Default4 qU
-#define d4 :if(
-#define d3 qV hS d4 qL
-#define d2 h3 gM if
-#define d1 IsVarOpcode(
-#define d0 mData->
-#define hZ ]qR w4
-#define hY gX Llq
-#define hX ,x gX Lap
-#define hW gT y+x;q8
-#define hV for qA
-#define hU gQ cAbs:
-#define hT unsigned
-#define hS cAdd
-#define hR ,y gX
-#define hQ qL 3 hZ
-#define hP y=q3-1]qR
-#define hO y gO
-#define hN qY if(dP
-#define hM q6:qC
-#define hL :if gF
-#define hK qQ h9 hS hL
-#define hJ 4 qZ mW(292,aY"cAdd B[IsVarOpcode(B)]" aW mD,mN aZ" B" aW,wA"," a8(B)<<"," a1);q4
-#define hI cNeg:
-#define hH :qS cDup:
-#define hG hS hH hK h1 wB(310,aH" " aH,"[Value_t(4)]" wH,);q4
-#define hF (x!=g1
-#define hE qL 2]
-#define hD B g4 w4
-#define hC B=hE qO B)){
-#define hB if hF 0)){
-#define hA gX Lng;
-#define h9 qK qV
-#define h8 }break;
-#define h7 <dH>()){
-#define h6 hR Lap;
-#define h5 isEvenInteger(
-#define h4 DegreesToRadians(x
-#define h3 cMul
-#define h2 A)){
-#define h1 ]==cDup){
-#define h0 hI wB(201,m0 mV,mV,);q4 Lab qU qB
-#define gZ 3 h1 wB(311,aH wH" " aH,"cMul [Value_t(4)]" wH,);q4
-#define gY qU hM
-#define gX );q4
-#define gW y,x gX Lba;
-#define gV IsUnaryOpcode(
-#define gU g6 w5=
-#define gT q3-1]=
-#define gS gR qR IsAlwaysIntegerOpcode(h2
-#define gR ;oH dF
-#define gQ )){qQ h9
-#define gP break gR qO A gQ
-#define gO =q3-1];
-#define gN qJ hO
-#define gM :qJ qC
-#define gL d2(dO
-#define gK ]=q6 q9 2 gH
-#define gJ return;
-#define gI );w5=
-#define gH ;qI q5
-#define gG qL 2 gK q0-=2;
-#define gF (qL 2
-#define gE y;hT B;hT
-#define gD d0 mByteCode
-#define gC ;qI q1
-#define gB q9 2 gC h3 gI
-#define gA ){if gF
-#define g9 oY h3 dV
-#define g8 if(x==g1
-#define g7 default:
-#define g6 q5 q0-=1;
-#define g5 if(!q0){q2
-#define g4 =hE qR
-#define g3 B g4 IsNeverNegativeValueOpcode(B)){
-#define g2 &&!HasInvalidRangesOpcode(
-#define g1 dH(
-#define g0 FP_ReDefinePointers();
-#define qZ ]==q6){
-#define qY if(q0[0 qZ qC
-#define qX IsNeverNegativeValueOpcode(h2
-#define qW gD qD
-#define qV ){case
-#define qU ;case
-#define qT }break qU
-#define qS qQ dF qV
-#define qR ;if(
-#define qQ switch(
-#define qP )&&gD oK>
-#define qO qR d1
-#define qN dF w1 2){
-#define qM d0 dN.d9;
-#define qL q0[-
-#define qK qL 1]
-#define qJ oY q6){
-#define qI tmp-->0;)
-#define qH q4 Default0;
-#define qG }}qH
-#define qF d0 dN qD
-#define qE AddFunctionOpcode(
-#define qD .push_back(
-#define qC x=q7;
-#define qB hM wB(132,"x " mV,"[fp_abs(x)]",wN);q4 Lac;
-#define qA (hT tmp=
-#define q9 ;hV
-#define q8 d0 dN.d9 q9
-#define q7 q3 0]
-#define q6 cImmed
-#define q5 gD.d9;
-#define q4 goto
-#define q3 dW[
-#define q2 q4 Laa;}case
-#define q1 q5 qE
-#define q0 ByteCodePtr
-hT*q0;dH*dW;
-#define FP_ReDefinePointers() q0=!gD.empty()?&gD[0]+gD oK-1:0;dW=!d0 dN.empty()?&d0 dN[0]+d0 dN oK-1:0;
-g0
-wE(opcode);
-#if(!(FP_COMPLEX_VERSION) && !(FP_FLOAT_VERSION))
-dH
-x;hT
-A;dH
-gE
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0
-oH
-dF
-qR
-qX
-wB(393,wJ
-mV,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cAdd:g5
-hG
-Lad;qT
-h3
-hL]==hS){if(qL
-gZ
-Lae;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Laf;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lag
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Lah;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lai;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Laj
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lak;qT
-oA
-Lal;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lam
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lan;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Lao;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lap;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Laq;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lba;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-Lbb
-gY
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbc;h8}
-qH
-TailCall_cDiv:g5
-cDiv
-hH
-wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-w7
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lbe
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Lbf;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lap;h8}
-qH
-TailCall_cEqual:g5
-w8:dA
-A=dD
-wB(421,"A[IsLogicalOpcode(A)] "
-wO
-aE,"A"
-,qB1(A)wM);q4
-Lap;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Lbg;}
-g8
-0
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Lbh
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Lbh;}
-wB(411,wL
-aE,"cNot"
-,wN);q4
-Lbi;qG
-TailCall_cGreater:g5
-o1:oL
-hU
-wB(413,m1
-m2,aJ,wN);q4
-Lbj;m4(417,wJ
-wL
-m2,"A "
-aJ,qB1(A)wM);q4
-Lbk;}
-}
-}
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lbl;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-g8
-1
-hU
-wB(414,mV" "
-wO
-aG,aJ,wN);q4
-Lbj;m4(418,wJ
-wO
-aG,"A "
-aJ,qB1(A)wM);q4
-Lbk;}
-}
-}
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Lbm;qG
-TailCall_cInv:g5
-cInv:qY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lbn;qG
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);oS;}
-}
-g8
-1
-hU
-wB(415,mV" "
-wO
-mJ,"cNot"
-,wN);q4
-Lbp;m4(419,wJ
-wO
-mJ,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lbq;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:oL
-hU
-wB(416,m1
-aR,"cNot"
-,wN);q4
-Lbp;m4(420,wJ
-wL
-aR,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-}
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lca;qG
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-w6
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lcc;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-Lcb;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Lcb;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-w6
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lcd;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-Lcb;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Lcb;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lce;}
-qG
-TailCall_cMul:g5
-h3
-hH
-wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lcf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lcg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lci;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lcj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lck;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lcl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lcj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lco;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lcp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lcq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup:wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lda
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldb;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Ldc;qT
-h3:qQ
-hE
-d3
-3
-h1
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Ldd;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Ldf;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Ldg
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldh;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Ldi;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lap;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Ldj;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Ldk;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-q4
-Default4;g7
-Default4:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Ldl;}
-}
-q4
-dZ
-oF
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lcg;}
-q4
-dZ;g7
-dZ:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lcf;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Ldm;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:dA
-A=dD
-wB(422,"A[IsLogicalOpcode(A)] "
-wO
-wW,"A"
-a0,qB1(A)wM);q4
-Lbi;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Ldn;}
-g8
-0
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Ldo
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Ldo;}
-wB(412,wL
-wW,aJ,wN);q4
-Lbk;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Ldp;qT
-hI
-wB(61,qC1
-aA,,);q4
-w6
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Ldq;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbs:wB(227,mV
-a0,"cNot"
-,);q4
-Lea
-qU
-cAbsNot:A=dD
-wB(389,"A[IsLogicalOpcode(A)] "
-aS
-a0,"A"
-,aI(A)wM);q4
-Lcb;}
-if(A!=q6){wB(390,"A[A!=cImmed] "
-aS
-a0,"A cAbsNotNot"
-,aI(A)wM);q4
-Leb;}
-q4
-o0
-qU
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lec
-qU
-hS
-gM
-wB(424,aF
-a0,"[-x] "
-aE,wN);q4
-Led;}
-q4
-o0
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Lee
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Lef
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Leg
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Leh
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Lei
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Lej
-oF
-wB(226,qC1
-a0,"cNot"
-,);q4
-Lea
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbb
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lea
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Lek;g7
-o0:;A=dF
-qR
-qX
-wB(391,wJ"cNot"
-,"A "
-aS,aI(A)wM);q4
-Lel;qG
-TailCall_cNotNot:g5
-dS:qS
-hS
-gM
-wB(423,aF" "
-aJ,"[-x] "
-wW,wN);q4
-Lem;qT
-cNot:wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-Lbb
-gY
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Len;h8}
-qH
-TailCall_cRDiv:g5
-cRDiv:dA
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Leo;qG
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lep;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Leq
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Leq;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lep
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Lfa
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lap;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Lfb;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lfc
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lfd;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lfe;}
-qG
-g7
-Default0:;A=w5
-qR
-IsComparisonOpcode(h2
-qY
-hK
-qZ
-mW(364,aY"cAdd"
-wF,"[x-y] A"
-,aI(A)qD1<<","
-a1);q4
-Lff;qT
-hI
-wB(365,qC1
-wF,"[-x] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1
-wM);q4
-Lfg;}
-}
-}
-if(d1
-A
-qP
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lfh;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lfi;}
-}
-}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:oZ
-4));gG
-Lfj:w5=h3;Lfk:g0
-Lfl:wE(cMul);q4
-TailCall_cMul;Lae:hV
-4
-dT
-oZ
-4)q71
-gX
-Lfj;Laf:q7=x+g1
-1);gG
-Lbo:w5=h3;q4
-Lfl;Lag:gU
-cSub;Lfm:wE(cSub);q4
-TailCall_cSub;Lah:hW
-2
-gH
-Lfn:g0
-Lfo:wE(cAdd);q4
-TailCall_cAdd;Lai:hW
-oR
-Lfp:qE
-hS);Lfq:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Laj:o9;qL
-2
-gK
-q4
-Lfp;Lak:hW
-2
-gH
-q4
-Lfq;Lal:hW
-4
-gH
-Lga:qE
-hS);Lgb:qE
-B);Lgc:w5=cSub;g0
-q4
-Lfm;Lam:o9;oC=q6
-q9
-oR
-q4
-Lga;Lan:hW
-oR
-q4
-Lgb;Lao:gT
-y+x;Lap:qM
-Lcb:q5
-gJ
-Laq:q8
-oV
-o7
-x
-q71
-gX
-Lfp;Lba:mM
-A
-gX
-Lfp;Lbb:gU
-dS;Lgd:wE(cNotNot);q4
-TailCall_cNotNot;Lbc:gT
-fp_and(x
-h6
-Lbd:oZ));dF
-dJ
-qE
-dU
-oZ
-1));Lge:qW
-q6);Lgf:w5=hS;q4
-Lfn;Lbe:o9;dI
-wE(cDiv);q4
-TailCall_cDiv;Lbf:gT
-y/x;q4
-Lap;Lbg:gT
-fp_equal
-mO
-Lbh:dI
-Lgg:wE(cEqual);q4
-TailCall_cEqual;Lbi:qM
-q5
-Lgh:w5=cNot;g0
-Lgi:wE(cNot);q4
-TailCall_cNot;Lbj:q8
-2
-gH
-Lgj:w5=dS;g0
-q4
-Lgd;Lbk:qM
-w3
-Lgj;Lbl:gT
-fp_less(x
-h6
-Lbm:gT
-fp_lessOrEq(x
-h6
-Lbn:q7=g1
-1)/x;gJ
-Lbp:dG
-Lgh;Lbq:gT
-fp_less
-mO
-Lca:gT
-fp_lessOrEq
-mO
-Lcc:gT
-fp_max(x
-h6
-Lcd:gT
-fp_min(x
-h6
-Lce:gT
-fp_mod
-mO
-Lcf:gU
-cSqr;Lgk:wE(cSqr);q4
-TailCall_cSqr;Lcg:mM
-cSqr);Lgl:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lch:hV
-3
-gC
-cSqr);dM
-Lgl;Lci:q7=x+g1
-1);hE=q6
-q9
-2
-gC
-cPow);gJ
-Lcj:gG
-q4
-Lfl;Lck:gT
-x;Lgm:dG
-Lfk;Lcl:qF1
-qM
-Lgn:hV
-4
-gH
-Lgo:o6
-x);Lgp:qW
-q6
-gX
-Lfk;Lcm:qM
-q4
-Lgn;Lcn:q8
-4
-gC
-B
-gX
-Lgo;Lco:q8
-oR
-q4
-Lgo;Lcp:qK
-dJ
-q4
-Lcb;Lcq:dI
-q4
-Lfl;Lda:q7=x+x;q4
-Lcj;Ldb:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgf;Ldc:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lge;Ldd:q8
-4
-dT
-qF
-x+x
-gX
-Lgp;Lde:qF1
-q8
-oR
-gJ
-Ldf:qG1
-q4
-Lgm;Ldg:o9;q4
-Lcq;Ldh:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgc;Ldi:qG1
-q4
-Lap;Ldj:qM
-w3
-Lgl;Ldk:dF=cDup;dW-=1;qM
-Lgq:w5=hS;q4
-Lfo;Ldl:hV
-2
-gH
-Lha:qE
-cSqr
-gX
-Lfk;Ldm:hV
-oR
-q4
-Lha;Ldn:gT
-fp_nequal
-mO
-Ldo:dI
-Lhb:wE(cNEqual);q4
-TailCall_cNEqual;Ldp:o9;g6
-oS;Ldq:o9;gJ
-Lea:g6
-q4
-Lgi;Leb:q1
-cAbsNotNot);gJ
-Lec:q5
-Lel:qE
-cAbsNot);gJ
-Led:o9;Lej:gU
-w8;q4
-Lgg;Lee:gU
-cNEqual;q4
-Lhb;Lef:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Leg:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Leh:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Lei:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Lek:q7=fp_not
-m6
-Lem:o9;q4
-Lee;Len:gT
-fp_or(x
-h6
-Leo:qM
-q5
-w5=cInv;g0
-wE(cInv);q4
-TailCall_cInv;Lep:oZ));dF
-dJ
-q4
-Lfj;Leq:g6
-q4
-Lgk;Lfa:g6
-q4
-Lgq;Lfb:gT
-y-x;q4
-Lap;Lfc:o9;q4
-Lgq;Lfd:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lfq;Lfe:mM
-A
-oJ
-cSub
-gX
-Lfq;Lff:gT
-x-y;d7
-A);gJ
-Lfg:o9;qK
-dJ
-q1
-OppositeComparisonOpcode(A));gJ
-Lfh:qW
-cDup);gJ
-Lfi:dF=cDup;gJ
-gJ
-q4
-TailCall_cAnd;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cNeg;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cSub;
-#endif
-#if((FP_COMPLEX_VERSION) && !(FP_FLOAT_VERSION))
-dH
-x;dH
-gE
-A;hT
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0}
-qH
-TailCall_cAdd:g5
-hG
-Lad;qT
-h3
-hL]==hS){if(qL
-gZ
-Lae;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Laf;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lag
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Lah;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lai;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Laj
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lak;qT
-oA
-Lal;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lam
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lan;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Lao;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lap;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Laq;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lba;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-Lbb
-gY
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbc;h8}
-qH
-TailCall_cConj:g5
-cConj:qS
-cConj:wB(63,mY" "
-mY,,);q4
-w7
-wB(193,"x "
-mY,"[fp_conj(x)]"
-,wN);q4
-Lbe;}
-qH
-TailCall_cDiv:g5
-cDiv
-hH
-wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lbf
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lbg
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Lbh;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lap;h8}
-qH
-TailCall_cEqual:g5
-w8:dA
-A=dD
-wB(421,"A[IsLogicalOpcode(A)] "
-wO
-aE,"A"
-,qB1(A)wM);q4
-Lap;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Lbi;}
-g8
-0
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Lbj
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Lbj;}
-wB(411,wL
-aE,"cNot"
-,wN);q4
-Lbk;qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lbl;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Lbm;qG
-TailCall_cImag:g5
-cImag:qS
-cAbs:wB(81,mV" "
-mZ,"[Value_t()]"
-wH,);q4
-Lbn
-qU
-cReal:wB(80,"cReal "
-mZ,"[Value_t()]"
-wH,);q4
-Lbn
-gY
-wB(192,"x "
-mZ,"[fp_imag(x)]"
-,wN);oS;}
-qH
-TailCall_cInv:g5
-cInv:qY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lbp;qG
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lbq;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lca;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lcb;qG
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-w7
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lcc;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-Lbd;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Lbd;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-w7
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lcd;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-Lbd;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Lbd;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lce;}
-qG
-TailCall_cMul:g5
-h3
-hH
-wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lcf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lcg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lci;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lcj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lck;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lcl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lcn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lcj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lco;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lcp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lcq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup:wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lda
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldb;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Ldc;qT
-h3:qQ
-hE
-d3
-3
-h1
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Ldd;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Ldf;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Ldg
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Ldh;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Ldi;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lap;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Ldj;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Ldk;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lch;}
-q4
-Default4;g7
-Default4:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Ldl;}
-}
-q4
-dZ
-oF
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lcg;}
-q4
-dZ;g7
-dZ:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lcf;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Ldm;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:dA
-A=dD
-wB(422,"A[IsLogicalOpcode(A)] "
-wO
-wW,"A"
-a0,qB1(A)wM);q4
-Lbk;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Ldn;}
-g8
-0
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Ldo
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Ldo;}
-wB(412,wL
-wW,aJ,wN);q4
-Ldp;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Ldq;qT
-hI
-wB(61,qC1
-aA,,);q4
-w7
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Lea;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Leb
-qU
-hS
-gM
-wB(424,aF
-a0,"[-x] "
-aE,wN);q4
-Lec;qT
-w8:wB(220,aE
-a0,wW,);q4
-Led
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Lee
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Lef
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Leg
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Leh
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Lei
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbb
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lej
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Lek;}
-qH
-TailCall_cNotNot:g5
-dS:qS
-hS
-gM
-wB(423,aF" "
-aJ,"[-x] "
-wW,wN);q4
-Lel;qT
-cNot:wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-Lbb
-gY
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Lem;h8}
-qH
-TailCall_cRDiv:g5
-cRDiv:dA
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Len;qG
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lbn;}
-qH
-TailCall_cReal:g5
-cReal:qY
-wB(191,"x cReal"
-,"[fp_real(x)]"
-,wN);q4
-Leo;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Lep
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Lep;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lbn
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Leq
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lap;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Lfa;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lfb
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lfc;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lfd;}
-qG
-g7
-Default0:;A=w5
-w1
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lfe;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lff;}
-}
-}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:oZ
-4));gG
-Lfg:w5=h3;Lfh:g0
-Lfi:wE(cMul);q4
-TailCall_cMul;Lae:hV
-4
-dT
-oZ
-4)q71
-gX
-Lfg;Laf:q7=x+g1
-1);gG
-Lbq:w5=h3;q4
-Lfi;Lag:gU
-cSub;Lfj:wE(cSub);q4
-TailCall_cSub;Lah:hW
-2
-gH
-Lfk:g0
-Lfl:wE(cAdd);q4
-TailCall_cAdd;Lai:hW
-oR
-Lfm:qE
-hS);Lfn:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Laj:o9;qL
-2
-gK
-q4
-Lfm;Lak:hW
-2
-gH
-q4
-Lfn;Lal:hW
-4
-gH
-Lfo:qE
-hS);Lfp:qE
-B);Lfq:w5=cSub;g0
-q4
-Lfj;Lam:o9;oC=q6
-q9
-oR
-q4
-Lfo;Lan:hW
-oR
-q4
-Lfp;Lao:gT
-y+x;Lap:qM
-Lbd:q5
-gJ
-Laq:q8
-oV
-o7
-x
-q71
-gX
-Lfm;Lba:mM
-A
-gX
-Lfm;Lbb:gU
-dS;Lga:wE(cNotNot);q4
-TailCall_cNotNot;Lbc:gT
-fp_and(x
-h6
-Lbe:q7=fp_conj
-m6
-Lbf:oZ));dF
-dJ
-qE
-dU
-oZ
-1));Lgb:qW
-q6);Lgc:w5=hS;q4
-Lfk;Lbg:o9;dI
-wE(cDiv);q4
-TailCall_cDiv;Lbh:gT
-y/x;q4
-Lap;Lbi:gT
-fp_equal
-mO
-Lbj:dI
-Lgd:wE(cEqual);q4
-TailCall_cEqual;Lbk:qM
-q5
-w5=cNot;g0
-Lge:wE(cNot);q4
-TailCall_cNot;Lbl:gT
-fp_less(x
-h6
-Lbm:gT
-fp_lessOrEq(x
-h6
-Lbn:oZ));dF
-dJ
-q4
-Lfg;Lbo:q7=fp_imag
-m6
-Lbp:q7=g1
-1)/x;gJ
-Lca:gT
-fp_less
-mO
-Lcb:gT
-fp_lessOrEq
-mO
-Lcc:gT
-fp_max(x
-h6
-Lcd:gT
-fp_min(x
-h6
-Lce:gT
-fp_mod
-mO
-Lcf:gU
-cSqr;Lgf:wE(cSqr);q4
-TailCall_cSqr;Lcg:mM
-cSqr);Lgg:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lch:hV
-3
-gC
-cSqr);dM
-Lgg;Lci:q7=x+g1
-1);hE=q6
-q9
-2
-gC
-cPow);gJ
-Lcj:gG
-q4
-Lfi;Lck:gT
-x;Lgh:dG
-Lfh;Lcl:qF1
-qM
-Lgi:hV
-4
-gH
-Lgj:o6
-x);Lgk:qW
-q6
-gX
-Lfh;Lcm:qM
-q4
-Lgi;Lcn:q8
-4
-gC
-B
-gX
-Lgj;Lco:q8
-oR
-q4
-Lgj;Lcp:qK
-dJ
-q4
-Lbd;Lcq:dI
-q4
-Lfi;Lda:q7=x+x;q4
-Lcj;Ldb:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lgc;Ldc:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lgb;Ldd:q8
-4
-dT
-qF
-x+x
-gX
-Lgk;Lde:qF1
-q8
-oR
-gJ
-Ldf:qG1
-q4
-Lgh;Ldg:o9;q4
-Lcq;Ldh:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lfq;Ldi:qG1
-q4
-Lap;Ldj:qM
-w3
-Lgg;Ldk:dF=cDup;dW-=1;qM
-Lgl:w5=hS;q4
-Lfl;Ldl:hV
-2
-gH
-Lgm:qE
-cSqr
-gX
-Lfh;Ldm:hV
-oR
-q4
-Lgm;Ldn:gT
-fp_nequal
-mO
-Ldo:dI
-Lgn:wE(cNEqual);q4
-TailCall_cNEqual;Ldp:qM
-q5
-w5=dS;g0
-q4
-Lga;Ldq:o9;g6
-q4
-Lbq;Lea:o9;gJ
-Leb:q1
-cAbsNot);gJ
-Lec:o9;Lei:gU
-w8;q4
-Lgd;Led:gU
-cNEqual;q4
-Lgn;Lee:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Lef:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Leg:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Leh:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Lej:g6
-q4
-Lge;Lek:q7=fp_not
-m6
-Lel:o9;q4
-Led;Lem:gT
-fp_or(x
-h6
-Len:qM
-q5
-w5=cInv;g0
-wE(cInv);q4
-TailCall_cInv;Leo:q7=fp_real
-m6
-Lep:g6
-q4
-Lgf;Leq:g6
-q4
-Lgl;Lfa:gT
-y-x;q4
-Lap;Lfb:o9;q4
-Lgl;Lfc:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lfn;Lfd:mM
-A
-oJ
-cSub
-gX
-Lfn;Lfe:qW
-cDup);gJ
-Lff:dF=cDup;gJ
-gJ
-q4
-TailCall_cAnd;q4
-TailCall_cConj;q4
-TailCall_cImag;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cNeg;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cReal;q4
-TailCall_cSub;
-#endif
-#if((FP_FLOAT_VERSION) && !(FP_COMPLEX_VERSION))
-dH
-x;hT
-A;dH
-gE
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0
-oH
-dF
-qR
-qX
-wB(393,wJ
-mV,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cAcos:g5
-cAcos:hN<=m7(148,"x[fp_abs(x)<=Value_t(1)] cAcos"
-,"[fp_acos(x)]"
-,wN);q4
-Lad;qG
-TailCall_cAcosh:g5
-cAcosh:qY
-if(x>=m7(145,"x[x>=Value_t(1)] cAcosh"
-,"[fp_acosh(x)]"
-,wN);q4
-Lae;qG
-TailCall_cAdd:g5
-hG
-Laf;qT
-h3
-hL]==hS){if(qL
-gZ
-Lag;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Lah;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lai
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Laj;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lak;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Lal
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lam;qT
-oA
-Lan;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lao
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lap;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Laq;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lba;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lbb;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lbc;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-w7
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbe;h8}
-qH
-TailCall_cAsin:g5
-cAsin:hN<=m7(149,"x[fp_abs(x)<=Value_t(1)] cAsin"
-,"[fp_asin(x)]"
-,wN);q4
-Lbf;qG
-TailCall_cAsinh:g5
-cAsinh:qY
-wB(146,"x cAsinh"
-,"[fp_asinh(x)]"
-,wN);q4
-Lbg;}
-qH
-TailCall_cAtan:g5
-cAtan:qY
-wB(150,"x cAtan"
-,"[fp_atan(x)]"
-,wN);q4
-Lbh;}
-qH
-TailCall_cAtan2:g5
-cAtan2:qY
-m9(139,mA"cAtan2"
-,"[fp_atan2(y,x)]"
-,q81);q4
-Lbi;qG
-TailCall_cAtanh:g5
-cAtanh:hN<m7(147,"x[fp_abs(x)<Value_t(1)] cAtanh"
-,"[fp_atanh(x)]"
-,wN);q4
-Lbj;qG
-TailCall_cCbrt:g5
-cCbrt:qY
-wB(151,"x cCbrt"
-,"[fp_cbrt(x)]"
-,wN);q4
-Lbk;}
-qH
-TailCall_cCeil:g5
-cCeil:qS
-hI
-wB(402,m0
-q01,mS
-aA,);q4
-Lbl
-gY
-wB(135,"x "
-q01,"[fp_ceil(x)]"
-,wN);q4
-Lbm
-gS
-wB(396,"A[IsAlwaysIntegerOpcode(A)] "
-q01,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cCos:g5
-cCos:qS
-cAbs:wB(235,mV" "
-aO,aO,);q4
-Lbn
-oF
-wB(238,m0
-aO,aO,);q4
-Lbn
-gY
-wB(152,"x "
-aO,"[fp_cos(x)]"
-,wN);oS;oH
-qN
-qQ
-h9
-cSec:hD
-wB(500,aK" cSec "
-wI
-aO,"B cSec "
-aT,aI(A)q91(B)wM);q4
-Lbp;qT
-cSin:hD
-wB(494,aK" "
-mP" "
-wI
-aO,"B cSinCos"
-,aI(A)q91(B)wM);q4
-Lbq;h8}
-qG
-TailCall_cCosh:g5
-cCosh:qS
-cAbs:wB(236,mV" "
-aM,aM,);q4
-Lca
-qU
-cAsinh:wB(450,"cAsinh "
-aM,"[DO_STACKPLUS1] "
-q41"[Value_t(1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lcb
-oF
-wB(239,m0
-aM,aM,);q4
-Lca
-gY
-wB(153,"x "
-aM,"[fp_cosh(x)]"
-,wN);q4
-Lcc;oH
-qN
-oY
-cSinh
-q11(507,aK" cSinh "
-wI
-aM,"B cSinhCosh"
-,aI(A)q91(B)wM);q4
-Lcd;}
-}
-qG
-TailCall_cCot:g5
-cCot:A=qN
-oY
-cTan
-q11(498,aK" "
-mR" "
-wI"cCot"
-,"B "
-mR" "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-qG
-TailCall_cCsc:g5
-cCsc:A=qN
-oY
-cSin
-q11(496,aK" "
-mP" "
-wI"cCsc"
-,"B "
-mP" "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-qG
-TailCall_cDeg:g5
-cDeg:qY
-wB(133,"x cDeg"
-,"[RadiansToDegrees(x)]"
-,wN);q4
-Lce;}
-qH
-TailCall_cDiv:g5
-cDiv:qS
-cCos:wB(250,aO
-mF,"cSec"
-wH,);q4
-Lcf
-qU
-cCot:wB(254,"cCot"
-mF,mR
-wH,);q4
-Lcg
-qU
-cCsc:wB(252,"cCsc"
-mF,mP
-wH,);q4
-Lch
-qU
-cDup:wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lci
-qU
-w2
-wB(408,"cExp"
-mF,m0"cExp"
-wH,);q4
-Lcj
-qU
-cExp2:wB(409,"cExp2"
-mF,m0"cExp2"
-wH,);q4
-Lck
-qU
-cInv:wB(213,aU
-mF,"cMul"
-,);q4
-Lcl
-qU
-cPow:wB(407,"cPow"
-mF,m0"cPow"
-wH,);q4
-Lcm
-qU
-cSec:wB(253,"cSec"
-mF,aO
-wH,);q4
-Lcn
-qU
-cSin:wB(249,mP
-mF,"cCsc"
-wH,);q4
-Lco
-qU
-cSinCos:wB(502,"cSinCos"
-mF,mR,);q4
-Lcp
-qU
-cSinhCosh:wB(509,"cSinhCosh"
-mF,"cTanh"
-,);q4
-Lcq
-qU
-cTan:wB(251,mR
-mF,"cCot"
-wH,);q4
-Lda
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Ldb
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Ldc;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lba;}
-dB
-h3
-gA
-qZ
-hP(y/x)==fp_const_rad_to_deg
-h7
-wB(321,"y[(y/x)==fp_const_rad_to_deg<Value_t>()]"
-wH" "
-wR,"cDeg"
-,q81);q4
-Ldd;}
-if((y/x)==fp_const_deg_to_rad
-h7
-wB(322,"y[(y/x)==fp_const_deg_to_rad<Value_t>()]"
-wH" "
-wR,"cRad"
-,q81);q4
-Lde;}
-wB(323,"y"
-wH" "
-wR,"[y/x]"
-wH,q81);q4
-Ldf;}
-}
-wB(325,wR,"[Value_t(1)/x]"
-wH,wN);q4
-Ldg;}
-gP
-cDiv:hC
-wB(271,aX"cDiv "
-wV,"[DO_STACKPLUS1] B A"
-wH
-mF,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Ldh;qT
-cRDiv:qQ
-hE
-qV
-hM
-wB(266,"x"
-a9" "
-wV,"A"
-wH" [x]"
-a9,aI(A)qD1
-wM);q4
-Ldi;g7
-hC
-wB(265,"B[IsVarOpcode(B)]"
-a9" "
-wV,"A"
-wH" B"
-a9,aI(A)q91(B)wM);q4
-Ldj;}
-h8}
-qG
-TailCall_cEqual:g5
-w8:oL
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Ldk
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Ldk;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Ldl;qG
-TailCall_cExp:g5
-w2
-qS
-hS
-gM
-wB(404,aF
-mL,q21"[fp_exp(x)]"
-wH,wN);q4
-Ldm;qT
-cLog:A=dE
-wB(340,wJ
-mG
-mL,"A"
-,aI(A)wM);q4
-oN
-hM
-wB(154,"x"
-mL,"[fp_exp(x)]"
-,wN);q4
-Ldo;}
-qH
-TailCall_cExp2:g5
-cExp2:qS
-hS
-gM
-wB(405,aF
-q31,"cExp2 [fp_exp2(x)]"
-wH,wN);q4
-Ldp;qT
-cLog2:A=dE
-wB(341,wJ
-aN
-q31,"A"
-,aI(A)wM);q4
-oN
-hM
-wB(155,"x"
-q31,"[fp_exp2(x)]"
-,wN);q4
-Ldq;}
-wB(479,"cExp2"
-,"[DO_STACKPLUS1] [fp_log(Value_t(2))]"
-wH
-mL,);incStackPtr();--mStackPtr;q4
-Lea;TailCall_cFloor:g5
-cFloor:qS
-hI
-wB(401,m0
-mS,q01
-aA,);q4
-Leb
-gY
-wB(136,"x "
-mS,"[fp_floor(x)]"
-,wN);q4
-Lec
-gS
-wB(395,"A[IsAlwaysIntegerOpcode(A)] "
-mS,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Led;}
-g8-oO
-wB(431,"x[x==Value_t(-0.5)] "
-m2,m0
-aS,wN);q4
-Lee;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-dB
-cAbs){wB(427,mV" x[x!=Value_t(0)] "
-aG,"[Value_t(0.5)/x]"
-wH" "
-aJ,wN);q4
-Lef;}
-}
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Leg;}
-g8
-oO
-wB(430,"x[x==Value_t(0.5)] "
-aG,"cAbsNotNot"
-,wN);q4
-Leh;qG
-TailCall_cHypot:g5
-cHypot
-d4
-dF==cSinCos){wB(84,"cSinCos cHypot"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lci;}
-qH
-TailCall_cInt:g5
-cInt:qS
-hM
-wB(137,"x cInt"
-,"[fp_int(x)]"
-,wN);q4
-Lei
-gS
-wB(397,"A[IsAlwaysIntegerOpcode(A)] cInt"
-,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cInv:g5
-cInv:qS
-cCos:wB(256,aO" "
-aU,"cSec"
-,);q4
-Lej
-qU
-cCot:wB(260,"cCot "
-aU,mR,);q4
-Lcp
-qU
-cCsc:wB(258,"cCsc "
-aU,mP,);q4
-Lek
-qU
-cInv:wB(62,aU" "
-aU,,);q4
-Ldn
-qU
-cPow:wB(355,q61
-aU,m0"cPow"
-,);q4
-Lel
-qU
-cSec:wB(259,"cSec "
-aU,aO,);q4
-Lem
-qU
-cSin:wB(255,mP" "
-aU,"cCsc"
-,);q4
-Len
-qU
-cSqrt:wB(206,q51" "
-aU,"cRSqrt"
-,);q4
-Leo
-qU
-cTan:wB(257,mR" "
-aU,"cCot"
-,);q4
-Lep
-gY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Leq;h8}
-qH
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lfa;}
-}
-dB
-cAbs){wB(426,mV" x[x!=Value_t(0)] "
-mJ,"[Value_t(0.5)/x]"
-wH
-a0,wN);q4
-Lfb;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lfc;}
-g8
-oO
-wB(429,"x[x==Value_t(0.5)] "
-mJ,aS,wN);q4
-Lfd;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lfe;}
-g8-oO
-wB(432,"x[x==Value_t(-0.5)] "
-aR,m0"cAbsNotNot"
-,wN);q4
-Lff;qG
-TailCall_cLog:g5
-cLog:mT(343,q21
-mG,,);q4
-Ldn
-qU
-gL
-wB(491,mU
-mG,mG" [fp_log(x)]"
-aZ,wN);q4
-Lfg;}
-o2
-wB(303,q41
-mG,mV" "
-mG" "
-aH,);q4
-Lfh
-aV(156,wQ" "
-mG,"[fp_log(x)]"
-,wN);q4
-Lfi;h8}
-qH
-TailCall_cLog10:g5
-cLog10:mT(481,q21
-aL,"[DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfj
-qU
-gL
-wB(492,mU
-aL,aL" [fp_log10(x)]"
-aZ,wN);q4
-Lfk;}
-o2
-wB(305,q41
-aL,mV" "
-aL" "
-aH,);q4
-Lfl
-aV(157,wQ" "
-aL,"[fp_log10(x)]"
-,wN);q4
-Lfm;h8}
-qH
-TailCall_cLog2:g5
-cLog2:mT(480,q21
-aN,"[DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfn
-qU
-cExp2:wB(344,"cExp2 "
-aN,,);q4
-Ldn
-qU
-gL
-wB(490,mU
-aN,aN" [fp_log2(x)]"
-aZ,wN);q4
-Lfo;}
-o2
-wB(304,q41
-aN,mV" "
-aN" "
-aH,);q4
-Lfp
-aV(158,wQ" "
-aN,"[fp_log2(x)]"
-,wN);q4
-Lfq;h8}
-qH
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);q4
-Ldn
-gY
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lga;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);q4
-oN
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);q4
-Ldn;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);q4
-Ldn
-gY
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lgb;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);q4
-oN
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);q4
-Ldn;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lgc;}
-qG
-TailCall_cMul:g5
-h3:qS
-cCsc:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(508,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cCsc"
-wH,"B cCot"
-,aI(A)q91(B)wM);q4
-Lgd;}
-}
-}
-q4
-dY
-qU
-cDup:wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lge
-qU
-cInv:wB(214,aU
-wH,"cDiv"
-,);q4
-Lgf
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lgg;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgh;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lgi;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lgj;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lgk;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lgl;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgm;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgn;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lgj;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lgo;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lgp;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lgq;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup
-d4
-x+oU
-wB(316,"cDup[x+x==Value_t(1)]"
-aZ
-a7,,wN);q4
-Lha;}
-wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lhb
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lhc;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Lhd;qT
-cDeg:wB(209,"cDeg"
-a7,"[RadiansToDegrees(x)]"
-wH,wN);q4
-Lhe
-qU
-cDiv
-oB
-qV
-o5
-4
-qZ
-mW(278,"y"
-wH" "
-aX
-mH,m3
-qH1,wA","
-a8(B)<<","
-a1);q4
-Lhf;qT
-hI
-wB(279,m0
-aX
-mH,mI
-qH1,wA","
-a8(B)wM);q4
-Lhg
-qU
-q6:mW(277,aY
-aX
-mH,"[y*x] B"
-mF,wA","
-a8(B)<<","
-a1);q4
-Lhh;}
-qT
-h3:qQ
-hE
-d3
-3
-h1
-if(x+oU
-wB(318,"cDup[x+x==Value_t(1)]"
-aZ
-wH
-a7,"cMul"
-,wN);q4
-Lhi;}
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Lhj;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lhk;}
-if((y*x)==fp_const_rad_to_deg
-h7
-wB(307,"y[(y*x)==fp_const_rad_to_deg<Value_t>()]"
-wH
-a7,"cDeg"
-,q81);q4
-Ldd;}
-if((y*x)==fp_const_deg_to_rad
-h7
-wB(308,"y[(y*x)==fp_const_deg_to_rad<Value_t>()]"
-wH
-a7,"cRad"
-,q81);q4
-Lde;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Lhl;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Lhm
-qU
-cRDiv:qQ
-hE
-qV
-o5
-3
-qZ
-mW(285,"y"
-wH
-a9
-a7,m3
-a9,q81);q4
-Lhn;qT
-hI
-wB(286,qC1
-a9
-a7,mI
-a9,wN);q4
-Lho
-qU
-q6:mW(284,"y"
-a9
-a7,"[y*x]"
-a9,q81);q4
-Lhp;qT
-cRad:wB(210,"cRad"
-a7,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lhq
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lia;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Lib;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lba;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Lic;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Lid;}
-if(x==fp_const_rad_to_deg
-h7
-wB(207,"x[x==fp_const_rad_to_deg<Value_t>()]"
-wH,"cDeg"
-,wN);q4
-Lie;}
-if(x==fp_const_deg_to_rad
-h7
-wB(208,"x[x==fp_const_deg_to_rad<Value_t>()]"
-wH,"cRad"
-,wN);q4
-Lif;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-cDiv:hC
-wB(274,aX"cDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-qH1,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Lig;}
-q4
-d5
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgh;}
-q4
-dZ;g7
-dZ:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Lih;}
-}
-q4
-d5
-hI
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lgg;}
-q4
-d5
-cRDiv
-hL
-qZ
-qC
-wB(267,"x"
-a9" "
-wS,"[DO_STACKPLUS1] "
-mK
-a9,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lii;}
-wB(281,"cRDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-a9,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lij;g7
-Default4:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lge;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lik;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:oL
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Lil
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Lil;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Lim;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Lin;qT
-hI
-wB(61,qC1
-aA,,);q4
-Ldn
-qU
-cSin:g9
-wB(244,"x"
-wH" "
-mP
-aA,mI" "
-mP,wN);q4
-Lio;}
-qT
-oQ
-g9
-wB(245,"x"
-wH" cSinh"
-aA,mI" cSinh"
-,wN);q4
-Lip;}
-qT
-cTan:g9
-wB(246,"x"
-wH" "
-mR
-aA,mI" "
-mR,wN);q4
-Liq;}
-qT
-cTanh:g9
-wB(247,"x"
-wH" cTanh"
-aA,mI" cTanh"
-,wN);q4
-Lja;}
-qT
-hM
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Ljb;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbs:wB(227,mV
-a0,"cNot"
-,);q4
-Ljc
-qU
-cAbsNot:A=dD
-wB(389,"A[IsLogicalOpcode(A)] "
-aS
-a0,"A"
-,aI(A)wM);q4
-Ldn;}
-if(A!=q6){wB(390,"A[A!=cImmed] "
-aS
-a0,"A cAbsNotNot"
-,aI(A)wM);q4
-Ljd;}
-q4
-o0
-qU
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lje
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Ljf
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Ljg
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Ljh
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Lji
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Ljj
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Ljk
-oF
-wB(226,qC1
-a0,"cNot"
-,);q4
-Ljc
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbd
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Ljc
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Ljl;g7
-o0:;A=dF
-qR
-qX
-wB(391,wJ"cNot"
-,"A "
-aS,aI(A)wM);q4
-Ljm;qG
-TailCall_cNotNot:g5
-dS
-d4
-dF==cNot){wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-w7
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Ljn;h8}
-qH
-TailCall_cPow:g5
-cPow:qY
-if(!h5
-x+x)){oY
-cSqr){wB(22,q41"x[!isEvenInteger(x+x)] cPow"
-,mV" [x+x] cPow"
-,wN);q4
-Ljo;}
-}
-if(isInteger(x
-gQ
-w2
-wB(43,q21
-wT,wX
-mL,wN);q4
-Ljp
-qU
-cExp2:wB(44,"cExp2 "
-wT,wX
-q31,wN);q4
-Ljq
-qU
-cPow
-hL
-qZ
-hP!isInteger(y)){wB(42,"y[!isInteger(y)] "
-q61
-wT,aP,q81);q4
-Lka;}
-}
-wB(45,q61
-wT,wX" cPow"
-,wN);q4
-Lkb;}
-}
-if(h5
-x
-hU
-wB(434,mV" x[isEvenInteger(x)] cPow"
-,"[x] cPow"
-,wN);q4
-Lkc
-qU
-h3
-hL]==cAbs){wB(435,mV
-wH" x[isEvenInteger(x)] cPow"
-,"cMul [x] cPow"
-,wN);q4
-Lkd;h8}
-}
-g8)){wB(83,"x[x==Value_t()] cPow"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,wN);q4
-Lke;}
-g8
-oO
-wB(332,"x[x==Value_t(0.5)] cPow"
-,q51,wN);q4
-Lkf;}
-g8
-1)/g1
-3)){wB(333,"x[x==Value_t(1)/Value_t(3)] cPow"
-,"cCbrt"
-,wN);q4
-Lkg;}
-g8
-1)/g1-3)){wB(334,"x[x==Value_t(1)/Value_t(-3)] cPow"
-,"cCbrt "
-aU,wN);q4
-Lkh;}
-g8-oO
-wB(335,"x[x==Value_t(-0.5)] cPow"
-,"cRSqrt"
-,wN);q4
-Lki;}
-g8-oG
-wB(336,"x[x==Value_t(-1)] cPow"
-,aU,wN);q4
-Lkj;}
-qQ
-h9
-cPow
-hL
-qZ
-hP
-h5
-y)&&!h5
-x*y)){wB(21,"y[isEvenInteger(y)&&!isEvenInteger(x*y)] "
-q61
-m8,mV" "
-aP,q81);q4
-Lkk;}
-wB(330,aY
-q61
-m8,aP,q81);q4
-Lka;o2
-wB(46,q41
-m8,"[x+x] cPow"
-,wN);q4
-Lkl
-qU
-q6:hP
-y!=oP||x>=oP){wB(165,"y[y!=Value_t(0)||x>=Value_t(0)] "
-m8,"[fp_pow(y,x)]"
-,q81);q4
-Lkm;h8}
-wB(455,m8,"[DO_POWI]"
-,wN)qR
-TryCompilePowi(x))gJ}
-qH
-TailCall_cRDiv:g5
-cRDiv:qS
-cSinCos:wB(503,"cSinCos"
-a9,"cCot"
-,);q4
-Lep
-qU
-cSinhCosh:wB(510,"cSinhCosh"
-a9,"cTanh "
-aU,);q4
-Lkn
-gY
-g8
-oG
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Lkj;h8}
-qH
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Lko;}
-qH
-TailCall_cRad:g5
-cRad:qS
-h3
-gM
-wB(211,"x"
-wH" cRad"
-,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lkp;qT
-hM
-wB(134,"x cRad"
-,"[DegreesToRadians(x)]"
-,wN);q4
-Lkq;}
-qH
-TailCall_cSec:g5
-cSec:A=qN
-qQ
-h9
-cCos:hD
-wB(497,aK" "
-aO" "
-wI"cSec"
-,"B "
-aO" "
-aT,aI(A)q91(B)wM);q4
-Lbp;qT
-cSin:hD
-wB(495,aK" "
-mP" "
-wI"cSec"
-,"B cSinCos "
-aU,aI(A)q91(B)wM);q4
-Lla;h8
-qG
-TailCall_cSin:g5
-cSin:qS
-hI
-wB(240,m0
-mP,mP
-aA,);q4
-Llb
-gY
-wB(159,"x "
-mP,"[fp_sin(x)]"
-,wN);q4
-Llc;oH
-qN
-oY
-cCsc
-q11(499,aK" cCsc "
-wI
-mP,"B cCsc "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-}
-qG
-TailCall_cSinh:g5
-oQ
-qS
-cAcosh:wB(437,"cAcosh cSinh"
-,"[DO_STACKPLUS1] "
-q41"[Value_t(-1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lld
-qU
-cAsinh:wB(349,"cAsinh cSinh"
-,,);q4
-Ldn
-oF
-wB(241,m0"cSinh"
-,"cSinh"
-aA,);q4
-Lle
-gY
-wB(160,"x cSinh"
-,"[fp_sinh(x)]"
-,wN);q4
-Llf;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Llg
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Llg
-qU
-cSqrt:A=dE
-wB(338,wJ
-q51" cSqr"
-,"A"
-,aI(A)wM);q4
-Ldn;h8}
-qH
-TailCall_cSqrt:g5
-cSqrt:qS
-hS
-d4
-qK
-o3
-A=hE
-w0
-if(oC
-o3
-wB(512,"cSqr"
-a3
-q41
-aQ,"A cHypot"
-,aI(A)wM);q4
-Llh;}
-}
-B
-g4
-gV
-B)){A=oC
-w0
-if(qL
-4]o3
-wB(513,"cSqr"
-a3"B[IsUnaryOpcode(B)] "
-q41
-aQ,"A B cHypot"
-," with"
-a8(B)qE1(A)wM);q4
-Lli;}
-}
-}
-o2
-wB(23,q41
-q51,mV,);q4
-Llj
-gY
-if(x>=oP){wB(161,"x[x>=Value_t(0)] "
-q51,"[fp_sqrt(x)]"
-,wN);q4
-Llk;h8}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Lko
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Lll
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lba;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Llm;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lln
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Llo;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Llp;}
-qG
-TailCall_cTan:g5
-cTan:qS
-cAtan2:wB(354,"cAtan2 "
-mR,"cDiv"
-,);q4
-Lgf
-oF
-wB(242,m0
-mR,mR
-aA,);q4
-Llq
-gY
-wB(163,"x "
-mR,"[fp_tan(x)]"
-,wN);q4
-Lma;oH
-qN
-oY
-cCot
-q11(501,aK" cCot "
-wI
-mR,"B cCot "
-aT,aI(A)q91(B)wM);q4
-Lbp;}
-}
-qG
-TailCall_cTanh:g5
-cTanh:qS
-hI
-wB(243,m0"cTanh"
-,"cTanh"
-aA,);q4
-Lmb
-gY
-wB(164,"x cTanh"
-,"[fp_tanh(x)]"
-,wN);q4
-Lmc;}
-qH
-TailCall_cTrunc:g5
-cTrunc:qS
-hM
-wB(138,"x cTrunc"
-,"[fp_trunc(x)]"
-,wN);q4
-Lmd
-gS
-wB(394,"A[IsAlwaysIntegerOpcode(A)] cTrunc"
-,"A"
-,aI(A)wM);gJ
-qG
-g7
-Default0:;A=w5
-qR
-IsComparisonOpcode(h2
-qY
-hK
-qZ
-mW(364,aY"cAdd"
-wF,"[x-y] A"
-,aI(A)qD1<<","
-a1);q4
-Lme;qT
-cAtan
-d4
-dP<fp_const_pi<dH>()*g1
-oO
-wB(380,"cAtan[fp_abs(x)<fp_const_pi<Value_t>()*Value_t(0.5)]"
-wF,"[fp_tan(x)] A"
-,aI(A)qD1
-wM);q4
-Lmf;qT
-cExp
-d4
-dO
-wB(370,"cExp[x>Value_t(0)]"
-wF,"[fp_log(x)] A"
-,aI(A)qD1
-wM);q4
-Lmg;qT
-cExp2
-d4
-dO
-wB(371,"cExp2[x>Value_t(0)]"
-wF,"[fp_log2(x)] A"
-,aI(A)qD1
-wM);q4
-Lmh;qT
-cLog:g3
-wB(373,wP
-mG
-wF,"B [fp_exp(x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmi;qT
-cLog10:g3
-wB(375,wP
-aL
-wF,"B [fp_pow(Value_t(10),x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmj;qT
-cLog2:g3
-wB(374,wP
-aN
-wF,"B [fp_exp2(x)] A"
-,aI(A)qD1
-q91(B)wM);q4
-Lmk;qT
-h3
-hL
-qZ
-hP
-y>oP){wB(366,"y[y>Value_t(0)]"
-wH
-wF,"[x/y] A"
-,aI(A)qD1<<","
-a1);q4
-Lml;}
-if(y<oP){wB(367,"y[y<Value_t(0)]"
-wH
-wF,"[x/y] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1<<","
-a1);q4
-Lmm;}
-qT
-hI
-wB(365,qC1
-wF,"[-x] {OppositeComparisonOpcode(A)}"
-,aI(A)qD1
-wM);q4
-Lmn
-qU
-cPow
-d4
-x>oP
-gA
-qZ
-hP
-y>oP){wB(368,"y[y>Value_t(0)] cPow[x>Value_t(0)]"
-wF,"[fp_pow(x,Value_t(1)/y)] A"
-,aI(A)qD1<<","
-a1);q4
-Lmo;}
-}
-qT
-oQ
-wB(381,"cSinh"
-wF,"[fp_asinh(x)] A"
-,aI(A)qD1
-wM);q4
-Lmp
-qU
-cSqr
-d4
-dO
-wB(369,"cSqr[x>Value_t(0)]"
-wF,mV" [fp_sqrt(x)] A"
-,aI(A)qD1
-wM);q4
-Lmq;qT
-cTanh
-d4
-dP<m7(382,"cTanh[fp_abs(x)<Value_t(1)]"
-wF,"[fp_atanh(x)] A"
-,aI(A)qD1
-wM);q4
-Lna;h8}
-}
-}
-if(d1
-A
-qP
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lnb;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lnc;}
-}
-}
-}
-C=w5
-qR
-IsCommutativeOrParamSwappableBinaryOpcode(C)){qS
-cSin:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(505,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] "
-mP" C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinCos {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lnd;}
-}
-qT
-oQ
-A=qK
-w1
-3
-gA]==cCosh){B=hQ
-wB(506,aK" "
-aM" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cSinh C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinhCosh {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lne;}
-}
-h8}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-Lnf:wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:q7=fp_acos
-m6
-Lae:q7=fp_acosh
-m6
-Laf:oZ
-4));gG
-Lng:w5=h3;Lnh:g0
-Lni:wE(cMul);q4
-TailCall_cMul;Lag:hV
-4
-dT
-oZ
-4));Lnj:qW
-q6
-hA
-Lah:q7=x+g1
-1);gG
-Lfa:w5=h3;q4
-Lni;Lai:gU
-cSub;Lnk:wE(cSub);q4
-TailCall_cSub;Laj:hW
-2
-gH
-Lnl:g0
-Lnm:wE(cAdd);q4
-TailCall_cAdd;Lak:hW
-oR
-Lnn:qE
-hS);Lno:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Lal:o9;qL
-2
-gK
-q4
-Lnn;Lam:hW
-2
-gH
-q4
-Lno;Lan:hW
-4
-gH
-Lnp:qE
-hS);Lnq:qE
-B);Loa:w5=cSub;g0
-q4
-Lnk;Lao:o9;oC=q6
-q9
-oR
-q4
-Lnp;Lap:hW
-oR
-q4
-Lnq;Laq:gT
-y+x;Lba:qM
-Ldn:q5
-gJ
-Lbb:q8
-oV
-o7
-x
-q71
-gX
-Lnn;Lbc:mM
-A
-gX
-Lnn;Lbd:gU
-dS;Lob:wE(cNotNot);q4
-TailCall_cNotNot;Lbe:gT
-fp_and(x
-d6
-Lbf:q7=fp_asin
-m6
-Lbg:q7=fp_asinh
-m6
-Lbh:q7=fp_atan
-m6
-Lbi:gT
-fp_atan2(gW
-Lbj:q7=fp_atanh
-m6
-Lbk:q7=fp_cbrt
-m6
-Lbl:q1
-cFloor);Loc:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lbm:q7=fp_ceil
-m6
-Lbn:g6
-Lod:wE(cCos);q4
-TailCall_cCos;Lbo:q7=fp_cos
-m6
-Lbp:dF=cDup;w5=cInv;Loe:wE(cInv);q4
-TailCall_cInv;Lbq:mM
-cSinCos);gJ
-Lca:g6
-wE(cCosh);q4
-TailCall_cCosh;Lcb:q1
-cSqr
-o7
-g1
-1));Lof:qW
-q6
-oJ
-hS);Log:w5=cSqrt;g0
-wE(cSqrt);q4
-TailCall_cSqrt;Lcc:q7=fp_cosh
-m6
-Lcd:mM
-cSinhCosh);gJ
-Lce:q7=RadiansToDegrees
-m6
-Lcf:q1
-cSec
-hA
-Lcg:q1
-cTan
-hA
-Lch:q1
-cSin
-hA
-Lci:oZ));dF
-dJ
-Loh:qE
-dU
-oZ
-1));Loi:qW
-q6);Loj:w5=hS;q4
-Lnl;Lcj:q1
-cNeg
-oJ
-cExp
-hA
-Lck:q1
-cNeg
-oJ
-cExp2
-hA
-Lcl:g6
-q4
-Lfa;Lcm:q1
-cNeg
-oJ
-cPow
-hA
-Lcn:q1
-cCos
-hA
-Lco:q1
-cCsc
-hA
-Lcp:gU
-cTan;Lok:wE(cTan);q4
-TailCall_cTan;Lcq:gU
-cTanh;Lol:wE(cTanh);q4
-TailCall_cTanh;Lda:q1
-cCot
-hA
-Ldb:o9;dI
-Lom:wE(cDiv);q4
-TailCall_cDiv;Ldc:gT
-y/x;q4
-Lba;Ldd:qF1
-q8
-oR
-Lon:w5=cDeg;g0
-wE(cDeg);q4
-TailCall_cDeg;Lde:qF1
-q8
-oR
-Loo:w5=cRad;g0
-wE(cRad);q4
-TailCall_cRad;Ldf:gT
-y/x;dG
-Lng;Ldg:q7=g1
-1)/x;q4
-Lfa;Ldh:mM
-oI
-Lop:g0
-q4
-Lom;Ldi:q8
-3
-gC
-oI
-qF
-x
-q71);Loq:w5=cRDiv;g0
-wE(cRDiv);q4
-TailCall_cRDiv;Ldj:hV
-3
-gC
-oI
-qE
-B
-gX
-Loq;Ldk:dI
-Lpa:wE(cEqual);q4
-TailCall_cEqual;Ldl:gT
-fp_equal(gW
-Ldm:d7
-cExp
-o7
-fp_exp(x)gX
-Lnj;Ldo:q7=fp_exp
-m6
-Ldp:d7
-cExp2
-o7
-fp_exp2(x)gX
-Lnj;Ldq:q7=fp_exp2
-m6
-Lea:qF
-oW
-g1
-2))q71);Lpb:qE
-h3
-gI
-cExp;g0
-wE(cExp);q4
-TailCall_cExp;Leb:q1
-cCeil
-gX
-Loc;Lec:q7=fp_floor
-m6
-Led:gT
-fp_less(x
-d6
-Lee:qM
-q1
-cNeg);Ljm:qE
-cAbsNot);gJ
-Lef:q7=g1
-0.5)/x;qK=d8
-dS;g0
-q4
-Lob;Leg:gT
-fp_lessOrEq(x
-d6
-Leh:qM
-Ljd:q5
-Lpc:qE
-cAbsNotNot);gJ
-Lei:q7=fp_int
-m6
-Lej:gU
-cSec;wE(cSec);q4
-TailCall_cSec;Lek:gU
-cSin;Lpd:wE(cSin);q4
-TailCall_cSin;Lel:q1
-cNeg
-gI
-cPow;Lpe:g0
-Lpf:wE(cPow);q4
-TailCall_cPow;Lem:gU
-cCos;q4
-Lod;Len:gU
-cCsc;wE(cCsc);q4
-TailCall_cCsc;Leo:q1
-cRSqrt);gJ
-Lep:g6
-Lpg:w5=cCot;wE(cCot);q4
-TailCall_cCot;Leq:q7=g1
-1)/x;gJ
-Lfb:q7=g1
-0.5)/x;qK=d8
-cNot;g0
-Lph:wE(cNot);q4
-TailCall_cNot;Lfc:gT
-fp_less(gW
-Lfd:qM
-Lje:w3
-Ljm;Lfe:gT
-fp_lessOrEq(gW
-Lff:qM
-q1
-cNeg
-gX
-Lpc;Lfg:d7
-cLog
-o7
-oW
-x)o8
-Lfh:q1
-dQ
-qE
-cLog);Lpi:qW
-cDup
-gX
-Loj;Lfi:q7=oW
-x);gJ
-Lfj:qF
-dR
-fp_const_e<dH>()));Lpj:dF
-dJ
-q4
-Lng;Lfk:d7
-cLog10
-o7
-dR
-x)o8
-Lfl:q1
-dQ
-qE
-cLog10
-gX
-Lpi;Lfm:q7=dR
-x);gJ
-Lfn:qF
-o4
-fp_const_e<dH>())gX
-Lpj;Lfo:d7
-cLog2
-o7
-o4
-x)o8
-Lfp:q1
-dQ
-qE
-cLog2
-gX
-Lpi;Lfq:q7=o4
-x);gJ
-Lga:gT
-fp_max(x
-d6
-Lgb:gT
-fp_min(x
-d6
-Lgc:gT
-fp_mod(gW
-Lgd:hV
-oR
-q0-=3;q4
-Lpg;Lge:gU
-cSqr;Lpk:wE(cSqr);q4
-TailCall_cSqr;Lgf:gU
-cDiv;q4
-Lom;Lgg:mM
-cSqr
-gX
-Loc;Lgh:hV
-3
-gC
-cSqr);dM
-Loc;Lgi:q7=x+g1
-1);gG
-w5=cPow;q4
-Lpf;Lgj:gG
-q4
-Lni;Lgk:gT
-x;Lpl:dG
-Lnh;Lgl:qF1
-qM
-Lpm:hV
-4
-gH
-Lpn:o6
-x);Lpo:qW
-q6
-gX
-Lnh;Lgm:qM
-q4
-Lpm;Lgn:q8
-4
-gC
-B
-gX
-Lpn;Lgo:q8
-oR
-q4
-Lpn;Lgp:qK
-dJ
-q4
-Ldn;Lgq:dI
-q4
-Lni;Lha:qM
-Lpp:hV
-oR
-gJ
-Lhb:q7=x+x;q4
-Lgj;Lhc:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Loj;Lhd:gT
-x;d7
-dU
-qF
-y*x
-o8
-Lhe:q7=RadiansToDegrees(x
-gX
-Lgq;Lhf:qG1
-q8
-4
-gH
-Lpq:qE
-dU
-Lqa:qE
-B
-gI
-cDiv;q4
-Lop;Lhg:o9;oC=q6
-q9
-oR
-q4
-Lpq;Lhh:qG1
-q8
-oR
-q4
-Lqa;Lhi:q8
-4
-gH
-q4
-Lnh;Lhj:q8
-4
-dT
-qF
-x+x
-gX
-Lpo;Lhk:qF1
-qM
-q4
-Lpp;Lhl:qG1
-q4
-Lpl;Lhm:o9;q4
-Lgq;Lhn:qG1
-q8
-oR
-Lqb:dM
-Loq;Lho:o9;qL
-2
-gK
-q4
-Lqb;Lhp:qG1
-dG
-Loq;Lhq:q7=h4
-gX
-Lgq;Lia:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Loa;Lib:qG1
-q4
-Lba;Lic:qM
-w3
-Loc;Lid:dF=cDup;dW-=1;qM
-Lqc:w5=hS;q4
-Lnm;Lie:qM
-w3
-Lon;Lif:qM
-w3
-Loo;Lig:hV
-oV
-gX
-Lpq;Lih:hV
-2
-gH
-Lqd:qE
-cSqr
-gX
-Lnh;Lii:q8
-oV
-o7
-x
-q71
-gX
-Lqb;Lij:mM
-A
-gX
-Lqb;Lik:hV
-oR
-q4
-Lqd;Lil:dI
-Lqe:wE(cNEqual);q4
-TailCall_cNEqual;Lim:gT
-fp_nequal(gW
-Lin:o9;q4
-Lcl;Lio:o9
-gB
-cSin;g0
-q4
-Lpd;Lip:o9
-gB
-cSinh;g0
-wE(cSinh);q4
-TailCall_cSinh;Liq:o9
-gB
-cTan;g0
-q4
-Lok;Lja:o9
-gB
-cTanh;g0
-q4
-Lol;Ljb:o9;gJ
-Ljc:g6
-q4
-Lph;Ljf:gU
-cNEqual;q4
-Lqe;Ljg:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Ljh:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Lji:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Ljj:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Ljk:gU
-w8;q4
-Lpa;Ljl:q7=fp_not
-m6
-Ljn:gT
-fp_or(x
-d6
-Ljo:d7
-dQ
-qF
-x+x);Lqf:qW
-q6
-gX
-Lpe;Ljp:dL
-Lpb;Ljq:qK=d8
-cExp2;g0
-wE(cExp2);q4
-TailCall_cExp2;Lka:qG1
-dG
-Lpe;Lkb:qK
-dJ
-q1
-h3
-gX
-Lpe;Lkc:dI
-q4
-Lpf;Lkd:q8
-3
-dT
-qF
-x
-gX
-Lqf;Lke:q7=g1
-gX
-Loh;Lkf:qM
-w3
-Log;Lkg:qM
-q5
-w5=cCbrt;g0
-wE(cCbrt);q4
-TailCall_cCbrt;Lkh:qM
-q1
-cCbrt);Lqg:w5=cInv;g0
-q4
-Loe;Lki:qM
-q4
-Leo;Lkj:qM
-w3
-Lqg;Lkk:qF1
-q8
-3
-gC
-dQ
-qF
-y*x
-gX
-Lqf;Lkl:q7=x+x;q4
-Lkc;Lkm:gT
-oX
-gW
-Lkn:q1
-cTanh
-gX
-Lqg;Lko:oZ)gX
-Lpj;Lkp:q7=h4
-gX
-Lcl;Lkq:q7=h4);gJ
-Lla:mM
-cSinCos
-gX
-Lqg;Llb:q1
-cSin
-gX
-Loc;Llc:q7=fp_sin
-m6
-Lld:q1
-cSqr
-o7
-g1-1)gX
-Lof;Lle:q1
-cSinh
-gX
-Loc;Llf:q7=fp_sinh
-m6
-Llg:g6
-q4
-Lpk;Llh:hV
-4
-gC
-A);Lqh:w5=cHypot;g0
-wE(cHypot);q4
-TailCall_cHypot;Lli:hV
-5
-gC
-A
-oJ
-B
-gX
-Lqh;Llj:gU
-cAbs;q4
-Lnf;Llk:q7=fp_sqrt
-m6
-Lll:g6
-q4
-Lqc;Llm:gT
-y-x;q4
-Lba;Lln:o9;q4
-Lqc;Llo:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lno;Llp:mM
-A
-oJ
-cSub
-gX
-Lno;Llq:q1
-cTan
-gX
-Loc;Lma:q7=fp_tan
-m6
-Lmb:q1
-cTanh
-gX
-Loc;Lmc:q7=fp_tanh
-m6
-Lmd:q7=fp_trunc
-m6
-Lme:gT
-x-y;Lqi:q8
-2
-gH
-Lqj:qE
-A);gJ
-Lmf:q7=fp_tan(x);Lqk:dL
-Lqj;Lmg:q7=oW
-x
-gX
-Lqk;Lmh:q7=o4
-x
-gX
-Lqk;Lmi:q7=fp_exp(x
-gX
-Lqk;Lmj:q7=oX
-g1
-10),x
-gX
-Lqk;Lmk:q7=fp_exp2(x
-gX
-Lqk;Lml:gT
-x/y;q4
-Lqi;Lmm:gT
-x/y;q8
-2
-gH
-Lql:qE
-OppositeComparisonOpcode(A));gJ
-Lmn:o9;dL
-Lql;Lmo:gT
-oX
-x,g1
-1)/y
-gX
-Lqi;Lmp:q7=fp_asinh(x
-gX
-Lqk;Lmq:d7
-dQ
-qF
-fp_sqrt(x)q71
-gX
-Lqj;Lna:q7=fp_atanh(x
-gX
-Lqk;Lnb:qW
-cDup);gJ
-Lnc:dF=cDup;gJ
-Lnd:hV
-3
-gC
-cSinCos);Lqm:qE
-GetParamSwappedBinaryOpcode(C));gJ
-Lne:hV
-3
-gC
-cSinhCosh
-gX
-Lqm;gJ
-q4
-TailCall_cAcos;q4
-TailCall_cAcosh;q4
-TailCall_cAnd;q4
-TailCall_cAsin;q4
-TailCall_cAsinh;q4
-TailCall_cAtan;q4
-TailCall_cAtan2;q4
-TailCall_cAtanh;q4
-TailCall_cCeil;q4
-TailCall_cFloor;q4
-TailCall_cInt;q4
-TailCall_cLog;q4
-TailCall_cLog10;q4
-TailCall_cLog2;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cOr;q4
-TailCall_cRDiv;q4
-TailCall_cRad;q4
-TailCall_cSec;q4
-TailCall_cSin;q4
-TailCall_cSinh;q4
-TailCall_cSqrt;q4
-TailCall_cSub;q4
-TailCall_cTan;q4
-TailCall_cTanh;q4
-TailCall_cTrunc;
-#endif
-#if((FP_COMPLEX_VERSION) && (FP_FLOAT_VERSION))
-dH
-x;dH
-gE
-A;hT
-C;hT
-D;qQ
-w5){TailCall_cAbs:g5
-cAbs:qS
-h0}
-qH
-TailCall_cAcos:g5
-cAcos:qY
-wB(172,"x cAcos"
-,"[fp_acos(x)]"
-,wN);q4
-Lad;}
-qH
-TailCall_cAcosh:g5
-cAcosh:qY
-wB(169,"x cAcosh"
-,"[fp_acosh(x)]"
-,wN);q4
-Lae;}
-qH
-TailCall_cAdd:g5
-hG
-Laf;qT
-h3
-hL]==hS){if(qL
-gZ
-Lag;}
-h8}
-q4
-dX
-qU
-d2
-gF
-h1
-wB(313,"cDup"
-a7
-aZ,"[x+Value_t(1)]"
-wH,wN);q4
-Lah;}
-}
-q4
-dX
-oF
-wB(199,qC1
-aZ,"cSub"
-,);q4
-Lai
-gY
-hK
-qZ
-mW(127,aY"cAdd"
-mD,"[y+x]"
-aZ,q81);q4
-Laj;qT
-cRSub:qQ
-hE
-d3
-3
-qZ
-mW(298,aY"cAdd"
-mE
-mD,mN
-aZ
-mE,q81);q4
-Lak;qT
-hI
-wB(299,m0
-a6
-mD,"[-x]"
-aZ
-mE,wN);q4
-Lal
-qU
-q6:mW(297,aY
-a6
-mD,mN
-mE,q81);q4
-Lam;qT
-oA
-Lan;qT
-hI
-wB(293,m0"B[IsVarOpcode(B)]"
-aW
-mD,"[-x]"
-aZ" B"
-aW,wA","
-a8(B)wM);q4
-Lao
-qU
-q6:mW(291,aY"B[IsVarOpcode(B)]"
-aW
-mD,mN" B"
-aW,wA","
-a8(B)<<","
-a1);q4
-Lap;}
-w9
-mW(105,aY
-aF,"[y+x]"
-,q81);q4
-Laq;}
-g8)){wB(57,"x[x==Value_t()]"
-aZ,,wN);q4
-Lba;h8
-g7
-dX:;A=dF
-w0
-oY
-cRSub
-dV
-wB(290,"x"
-mE
-a3"cAdd"
-,"[DO_STACKPLUS1] A [x]"
-aZ
-mE,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lbb;}
-wB(295,a6
-a3"cAdd"
-,"[DO_STACKPLUS1] A"
-aZ
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lbc;}
-qG
-TailCall_cAnd:g5
-cAnd
-hH
-wB(224,mX"cAnd"
-,aJ,);q4
-w7
-m9(117,mA"cAnd"
-,"[fp_and(x,y)]"
-,q81);q4
-Lbe;h8}
-qH
-TailCall_cArg:g5
-cArg:qY
-wB(190,"x cArg"
-,"[fp_arg(x)]"
-,wN);q4
-Lbf;}
-qH
-TailCall_cAsin:g5
-cAsin:qY
-wB(173,"x cAsin"
-,"[fp_asin(x)]"
-,wN);q4
-Lbg;}
-qH
-TailCall_cAsinh:g5
-cAsinh:qY
-wB(170,"x cAsinh"
-,"[fp_asinh(x)]"
-,wN);q4
-Lbh;}
-qH
-TailCall_cAtan:g5
-cAtan:qY
-if(g1
-x.real(),fp_abs(x.imag()))!=g1
-0,oG
-wB(174,"x[Value_t(x.real(),fp_abs(x.imag()))!=Value_t(0,1)] cAtan"
-,"[fp_atan(x)]"
-,wN);q4
-Lbi;qG
-TailCall_cAtan2:g5
-cAtan2:qY
-m9(139,mA"cAtan2"
-,"[fp_atan2(y,x)]"
-,q81);q4
-Lbj;qG
-TailCall_cAtanh:g5
-cAtanh:qY
-if(g1
-fp_abs(x.real()),x.imag())!=g1
-1,0)){wB(171,"x[Value_t(fp_abs(x.real()),x.imag())!=Value_t(1,0)] cAtanh"
-,"[fp_atanh(x)]"
-,wN);q4
-Lbk;qG
-TailCall_cCbrt:g5
-cCbrt:qY
-wB(175,"x cCbrt"
-,"[fp_cbrt(x)]"
-,wN);q4
-Lbl;}
-qH
-TailCall_cCeil:g5
-cCeil:qS
-hI
-wB(402,m0
-q01,mS
-aA,);q4
-Lbm
-gY
-wB(135,"x "
-q01,"[fp_ceil(x)]"
-,wN);q4
-Lbn
-gS
-wB(396,"A[IsAlwaysIntegerOpcode(A)] "
-q01,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cConj:g5
-cConj:qS
-cConj:wB(63,mY" "
-mY,,);oS
-gY
-wB(193,"x "
-mY,"[fp_conj(x)]"
-,wN);q4
-Lbp;}
-qH
-TailCall_cCos:g5
-cCos:qS
-cAcos:wB(346,"cAcos "
-aO,,);q4
-oE
-wB(238,m0
-aO,aO,);q4
-Lbq
-gY
-wB(176,"x "
-aO,"[fp_cos(x)]"
-,wN);q4
-Lca;oH
-qN
-qQ
-h9
-cSec:hD
-wB(500,aK" cSec "
-wI
-aO,"B cSec "
-aT,aI(A)q91(B)wM);q4
-Lcb;qT
-cSin:hD
-wB(494,aK" "
-mP" "
-wI
-aO,"B cSinCos"
-,aI(A)q91(B)wM);q4
-Lcc;h8}
-qG
-TailCall_cCosh:g5
-cCosh:qS
-cAsinh:wB(450,"cAsinh "
-aM,"[DO_STACKPLUS1] "
-q41"[Value_t(1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lcd
-oF
-wB(239,m0
-aM,aM,);q4
-Lce
-gY
-wB(177,"x "
-aM,"[fp_cosh(x)]"
-,wN);q4
-Lcf;oH
-qN
-oY
-cSinh
-q11(507,aK" cSinh "
-wI
-aM,"B cSinhCosh"
-,aI(A)q91(B)wM);q4
-Lcg;}
-}
-qG
-TailCall_cCot:g5
-cCot:A=qN
-oY
-cTan
-q11(498,aK" "
-mR" "
-wI"cCot"
-,"B "
-mR" "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-qG
-TailCall_cCsc:g5
-cCsc:A=qN
-oY
-cSin
-q11(496,aK" "
-mP" "
-wI"cCsc"
-,"B "
-mP" "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-qG
-TailCall_cDeg:g5
-cDeg:qY
-wB(133,"x cDeg"
-,"[RadiansToDegrees(x)]"
-,wN);q4
-Lch;}
-qH
-TailCall_cDiv:g5
-cDiv:qS
-cCos:wB(250,aO
-mF,"cSec"
-wH,);q4
-Lci
-qU
-cCot:wB(254,"cCot"
-mF,mR
-wH,);q4
-Lcj
-qU
-cCsc:wB(252,"cCsc"
-mF,mP
-wH,);q4
-Lck
-qU
-cDup:wB(78,"cDup"
-mF,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lcl
-qU
-w2
-wB(408,"cExp"
-mF,m0"cExp"
-wH,);q4
-Lcm
-qU
-cExp2:wB(409,"cExp2"
-mF,m0"cExp2"
-wH,);q4
-Lcn
-qU
-cInv:wB(213,aU
-mF,"cMul"
-,);q4
-Lco
-qU
-cPow:wB(407,"cPow"
-mF,m0"cPow"
-wH,);q4
-Lcp
-qU
-cSec:wB(253,"cSec"
-mF,aO
-wH,);q4
-Lcq
-qU
-cSin:wB(249,mP
-mF,"cCsc"
-wH,);q4
-Lda
-qU
-cSinCos:wB(502,"cSinCos"
-mF,mR,);q4
-Ldb
-qU
-cSinhCosh:wB(509,"cSinhCosh"
-mF,"cTanh"
-,);q4
-Ldc
-qU
-cTan:wB(251,mR
-mF,"cCot"
-wH,);q4
-Ldd
-gY
-if
-hF
-gQ
-hI
-wB(125,m0
-a4"cDiv"
-,"[-x]"
-mF,wN);q4
-Lde
-qU
-q6:mW(103,aY
-a4"cDiv"
-,"[y/x]"
-,q81);q4
-Ldf;}
-}
-g8
-oG
-wB(56,wO"cDiv"
-,,wN);q4
-Lba;}
-dB
-h3
-gA
-qZ
-hP(y/x)==fp_const_rad_to_deg
-h7
-wB(321,"y[(y/x)==fp_const_rad_to_deg<Value_t>()]"
-wH" "
-wR,"cDeg"
-,q81);q4
-Ldg;}
-if((y/x)==fp_const_deg_to_rad
-h7
-wB(322,"y[(y/x)==fp_const_deg_to_rad<Value_t>()]"
-wH" "
-wR,"cRad"
-,q81);q4
-Ldh;}
-wB(323,"y"
-wH" "
-wR,"[y/x]"
-wH,q81);q4
-Ldi;}
-}
-wB(325,wR,"[Value_t(1)/x]"
-wH,wN);q4
-Ldj;}
-gP
-cDiv:hC
-wB(271,aX"cDiv "
-wV,"[DO_STACKPLUS1] B A"
-wH
-mF,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Ldk;qT
-cRDiv:qQ
-hE
-qV
-hM
-wB(266,"x"
-a9" "
-wV,"A"
-wH" [x]"
-a9,aI(A)qD1
-wM);q4
-Ldl;g7
-hC
-wB(265,"B[IsVarOpcode(B)]"
-a9" "
-wV,"A"
-wH" B"
-a9,aI(A)q91(B)wM);q4
-Ldm;}
-h8}
-qG
-TailCall_cEqual:g5
-w8:oL
-hU
-wB(359,m1
-aE,"[x] "
-aE,wN);q4
-Ldn
-qU
-cSqr:wB(361,q41
-wL
-aE,"[x] "
-aE,wN);q4
-Ldn;}
-}
-m9(115,mA
-aE,"[fp_equal(y,x)]"
-,q81);q4
-Ldo;qG
-TailCall_cExp:g5
-w2
-qS
-hS
-gM
-wB(404,aF
-mL,q21"[fp_exp(x)]"
-wH,wN);q4
-Ldp;qT
-cLog:A=dE
-wB(340,wJ
-mG
-mL,"A"
-,aI(A)wM);oS;qT
-hM
-wB(178,"x"
-mL,"[fp_exp(x)]"
-,wN);q4
-Ldq;}
-qH
-TailCall_cExp2:g5
-cExp2:qS
-hS
-gM
-wB(405,aF
-q31,"cExp2 [fp_exp2(x)]"
-wH,wN);q4
-Lea;qT
-cLog2:A=dE
-wB(341,wJ
-aN
-q31,"A"
-,aI(A)wM);oS;qT
-hM
-wB(179,"x"
-q31,"[fp_exp2(x)]"
-,wN);q4
-Leb;}
-wB(479,"cExp2"
-,"[DO_STACKPLUS1] [fp_log(Value_t(2))]"
-wH
-mL,);incStackPtr();--mStackPtr;q4
-Lec;TailCall_cFloor:g5
-cFloor:qS
-hI
-wB(401,m0
-mS,q01
-aA,);q4
-Led
-gY
-wB(136,"x "
-mS,"[fp_floor(x)]"
-,wN);q4
-Lee
-gS
-wB(395,"A[IsAlwaysIntegerOpcode(A)] "
-mS,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cGreater:g5
-o1:qY
-m9(113,mA
-m2,"[fp_less(x,y)]"
-,q81);q4
-Lef;qG
-TailCall_cGreaterOrEq:g5
-dK:qY
-m9(114,mA
-aG,"[fp_lessOrEq(x,y)]"
-,q81);q4
-Leg;qG
-TailCall_cHypot:g5
-cHypot
-d4
-dF==cSinCos){wB(84,"cSinCos cHypot"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,);q4
-Lcl;}
-qH
-TailCall_cImag:g5
-cImag:qS
-cAbs:wB(81,mV" "
-mZ,"[Value_t()]"
-wH,);q4
-Leh
-qU
-cReal:wB(80,"cReal "
-mZ,"[Value_t()]"
-wH,);q4
-Leh
-gY
-wB(192,"x "
-mZ,"[fp_imag(x)]"
-,wN);q4
-Lei;}
-qH
-TailCall_cInt:g5
-cInt:qS
-hM
-wB(137,"x cInt"
-,"[fp_int(x)]"
-,wN);q4
-Lej
-gS
-wB(397,"A[IsAlwaysIntegerOpcode(A)] cInt"
-,"A"
-,aI(A)wM);gJ
-qG
-TailCall_cInv:g5
-cInv:qS
-cCos:wB(256,aO" "
-aU,"cSec"
-,);q4
-Lek
-qU
-cCot:wB(260,"cCot "
-aU,mR,);q4
-Ldb
-qU
-cCsc:wB(258,"cCsc "
-aU,mP,);q4
-Lel
-qU
-cInv:wB(62,aU" "
-aU,,);oS
-qU
-cPow:wB(355,q61
-aU,m0"cPow"
-,);q4
-Lem
-qU
-cSec:wB(259,"cSec "
-aU,aO,);q4
-Len
-qU
-cSin:wB(255,mP" "
-aU,"cCsc"
-,);q4
-Leo
-qU
-cSqrt:wB(206,q51" "
-aU,"cRSqrt"
-,);q4
-Lep
-qU
-cTan:wB(257,mR" "
-aU,"cCot"
-,);q4
-Leq
-gY
-if
-hF)){wB(101,a4
-aU,"[Value_t(1)/x]"
-,wN);q4
-Lfa;h8}
-qH
-TailCall_cLess:g5
-cLess:oL)){A=dE
-wB(301,wJ
-wL
-mJ,mK,qB1(A)wM);q4
-Lfb;}
-}
-m9(111,mA
-mJ,"[fp_less(y,x)]"
-,q81);q4
-Lfc;qG
-TailCall_cLessOrEq:g5
-cLessOrEq:qY
-m9(112,mA
-aR,"[fp_lessOrEq(y,x)]"
-,q81);q4
-Lfd;qG
-TailCall_cLog:g5
-cLog:mT(343,q21
-mG,,);oS
-qU
-gL
-wB(491,mU
-mG,mG" [fp_log(x)]"
-aZ,wN);q4
-Lfe;}
-oD
-wB(180,qA1
-mG,"[fp_log(x)]"
-,wN);q4
-Lff;h8}
-qH
-TailCall_cLog10:g5
-cLog10:mT(481,q21
-aL,"[DO_STACKPLUS1] [fp_log10(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfg
-qU
-gL
-wB(492,mU
-aL,aL" [fp_log10(x)]"
-aZ,wN);q4
-Lfh;}
-oD
-wB(181,qA1
-aL,"[fp_log10(x)]"
-,wN);q4
-Lfi;h8}
-qH
-TailCall_cLog2:g5
-cLog2:mT(480,q21
-aN,"[DO_STACKPLUS1] [fp_log2(fp_const_e<Value_t>())]"
-wH,);incStackPtr();--mStackPtr;q4
-Lfj
-qU
-cExp2:wB(344,"cExp2 "
-aN,,);oS
-qU
-gL
-wB(490,mU
-aN,aN" [fp_log2(x)]"
-aZ,wN);q4
-Lfk;}
-oD
-wB(182,qA1
-aN,"[fp_log2(x)]"
-,wN);q4
-Lfl;h8}
-qH
-TailCall_cMax:g5
-cMax
-hH
-wB(60,mX
-mB,,);oS
-gY
-m9(141,mA
-mB,"[fp_max(x,y)]"
-,q81);q4
-Lfm;}
-gP
-cDup:hD
-wB(66,aK
-mQ
-a3
-mB,"B"
-mQ,aI(A)q91(B)wM);oS;qT
-cMax:hD
-wB(68,aK" "
-mB
-a3
-mB,"B "
-mB,aI(A)q91(B)wM);oS;h8}
-qG
-TailCall_cMin:g5
-cMin
-hH
-wB(59,mX
-mC,,);oS
-gY
-m9(140,mA
-mC,"[fp_min(x,y)]"
-,q81);q4
-Lfn;}
-gP
-cDup:hD
-wB(65,aK
-mQ
-a3
-mC,"B"
-mQ,aI(A)q91(B)wM);oS;qT
-cMin:hD
-wB(67,aK" "
-mC
-a3
-mC,"B "
-mC,aI(A)q91(B)wM);oS;h8}
-qG
-TailCall_cMod:g5
-cMod:qY
-if
-hF)){m9(104,aY
-a4"cMod"
-,"[fp_mod(y,x)]"
-,q81);q4
-Lfo;}
-qG
-TailCall_cMul:g5
-h3:qS
-cCsc:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(508,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cCsc"
-wH,"B cCot"
-,aI(A)q91(B)wM);q4
-Lfp;}
-}
-}
-q4
-dY
-qU
-cDup:wB(202,"cDup"
-wH,"cSqr"
-,);q4
-Lfq
-qU
-cInv:wB(214,aU
-wH,"cDiv"
-,);q4
-Lga
-oF
-qQ
-h9
-cDup:wB(467,"cDup"
-aA
-wH,"cSqr"
-aA,);q4
-Lgb;oH
-qK
-qO
-A)gA
-oM
-B=hQ
-wB(473,aK
-wH
-a3
-qC1
-wH,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgc;}
-}
-}
-}
-q4
-dY
-qU
-cPow
-gM
-if
-gF
-h1
-wB(314,mX
-m8
-wH,"[x+Value_t(1)] cPow"
-,wN);q4
-Lgd;}
-}
-q4
-dY
-gY
-g8
-gQ
-h3:A=hE
-w0
-wB(93,wS" "
-wZ,wX,qB1(A)wM);q4
-Lge;}
-q4
-Default3;g7
-Default3:;A=qK
-qR
-IsBinaryOpcode(A)g2
-h2
-qQ
-hE
-qV
-q6:mW(92,aY
-wD,wX,qB1(A)<<","
-a1);q4
-Lgf;g7
-B
-g4
-IsBinaryOpcode(B)g2
-B)){qQ
-oC
-qV
-q6:mW(96,aY
-wK,mK,qB1(A)q91(B)<<","
-a1);q4
-Lgg;g7
-C=oC
-qO
-C)){wB(94,"C[IsVarOpcode(C)] "
-wK,mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgh;}
-if(gV
-C)g2
-C)){wB(95,"C[IsUnaryOpcode(C)&&!HasInvalidRangesOpcode(C)] "
-wK,"B "
-mK,qB1(A)q91(B)<<", C"
-wY(C)wM);q4
-Lgi;}
-}
-}
-if(d1
-B)){wB(90,aX
-wD,wX,qB1(A)q91(B)wM);q4
-Lge;}
-if(gV
-B)g2
-B)){wB(91,"B[IsUnaryOpcode(B)&&!HasInvalidRangesOpcode(B)] "
-wD,mK,qB1(A)q91(B)wM);q4
-Lgj;}
-}
-}
-if(d1
-h2
-wB(88,a5" "
-wZ,"[x]"
-,qB1(A)wM);q4
-Lgk;}
-if(gV
-A)g2
-h2
-wB(89,"A[IsUnaryOpcode(A)&&!HasInvalidRangesOpcode(A)] "
-wZ,wX,qB1(A)wM);q4
-Lgl;}
-}
-}
-qQ
-h9
-hS:qQ
-hE
-qV
-cDup
-d4
-x+oU
-wB(316,"cDup[x+x==Value_t(1)]"
-aZ
-a7,,wN);q4
-Lgm;}
-wB(317,aH
-a7,"[x+x]"
-wH,wN);q4
-Lgn
-qU
-o5
-3
-qZ
-hO
-A=qL
-4]w0
-wB(386,a5" y"
-wH
-aZ
-a7,wX" A "
-m3
-aZ,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lgo;}
-w9
-mW(385,aY"cAdd"
-a7,wX" [y*x]"
-aZ,q81);q4
-Lgp;qT
-cDeg:wB(209,"cDeg"
-a7,"[RadiansToDegrees(x)]"
-wH,wN);q4
-Lgq
-qU
-cDiv
-oB
-qV
-o5
-4
-qZ
-mW(278,"y"
-wH" "
-aX
-mH,m3
-qH1,wA","
-a8(B)<<","
-a1);q4
-Lha;qT
-hI
-wB(279,m0
-aX
-mH,mI
-qH1,wA","
-a8(B)wM);q4
-Lhb
-qU
-q6:mW(277,aY
-aX
-mH,"[y*x] B"
-mF,wA","
-a8(B)<<","
-a1);q4
-Lhc;}
-qT
-h3:qQ
-hE
-d3
-3
-h1
-if(x+oU
-wB(318,"cDup[x+x==Value_t(1)]"
-aZ
-wH
-a7,"cMul"
-,wN);q4
-Lhd;}
-wB(319,aH
-wH
-a7,"cMul [x+x]"
-wH,wN);q4
-Lhe;w9
-hP
-y*oU
-wB(70,"y[y*x==Value_t(1)]"
-wH
-a7,,q81);q4
-Lhf;}
-if((y*x)==fp_const_rad_to_deg
-h7
-wB(307,"y[(y*x)==fp_const_rad_to_deg<Value_t>()]"
-wH
-a7,"cDeg"
-,q81);q4
-Ldg;}
-if((y*x)==fp_const_deg_to_rad
-h7
-wB(308,"y[(y*x)==fp_const_deg_to_rad<Value_t>()]"
-wH
-a7,"cRad"
-,q81);q4
-Ldh;}
-wB(128,"y"
-wH
-a7,m3,q81);q4
-Lhg;qT
-hI
-wB(122,qC1
-a7,mI,wN);q4
-Lhh
-qU
-cRDiv:qQ
-hE
-qV
-o5
-3
-qZ
-mW(285,"y"
-wH
-a9
-a7,m3
-a9,q81);q4
-Lhi;qT
-hI
-wB(286,qC1
-a9
-a7,mI
-a9,wN);q4
-Lhj
-qU
-q6:mW(284,"y"
-a9
-a7,"[y*x]"
-a9,q81);q4
-Lhk;qT
-cRad:wB(210,"cRad"
-a7,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lhl
-qU
-cSub
-hL
-oM
-if(qL
-3
-qZ
-hO
-A=qL
-4]w0
-wB(387,a5" y"
-wH
-aW
-a7,wX" A "
-m3
-aW,wA", "
-aY"= "
-<<y
-qE1(A)wM);q4
-Lhm;}
-}
-w9
-mW(102,"y"
-a7,"[y*x]"
-,q81);q4
-Lhn;}
-g8
-oG
-wB(55,"x[x==Value_t(1)]"
-wH,,wN);q4
-Lba;}
-g8-oG
-wB(124,"x[x==Value_t(-1)]"
-wH,qC1,wN);q4
-Lho;}
-g8
-2)){wB(198,"x[x==Value_t(2)]"
-wH,aH,wN);q4
-Lhp;}
-if(x==fp_const_rad_to_deg
-h7
-wB(207,"x[x==fp_const_rad_to_deg<Value_t>()]"
-wH,"cDeg"
-,wN);q4
-Lhq;}
-if(x==fp_const_deg_to_rad
-h7
-wB(208,"x[x==fp_const_deg_to_rad<Value_t>()]"
-wH,"cRad"
-,wN);q4
-Lia;h8
-g7
-dY:;A=dF
-qO
-A
-gQ
-cDiv:hC
-wB(274,aX"cDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-qH1,aI(A)q91(B)wM);incStackPtr();--mStackPtr;q4
-Lib;}
-q4
-d5
-h3:qQ
-hE
-qV
-hI
-B=hQ
-wB(470,aK
-aA
-wH" "
-wS,m5
-wH
-aA,aI(A)q91(B)wM);q4
-Lgc;}
-q4
-dZ;g7
-dZ:;hD
-wB(461,aK
-wH" "
-wS,m5
-wH,aI(A)q91(B)wM);q4
-Lic;}
-}
-q4
-d5
-hI
-hD
-wB(464,aK
-aA" "
-wS,m5
-aA,aI(A)q91(B)wM);q4
-Lgb;}
-q4
-d5
-cRDiv
-hL
-qZ
-qC
-wB(267,"x"
-a9" "
-wS,"[DO_STACKPLUS1] "
-mK
-a9,aI(A)qD1
-wM);incStackPtr();--mStackPtr;q4
-Lid;}
-wB(281,"cRDiv "
-wS,"[DO_STACKPLUS1] A"
-wH
-a9,aI(A)wM);incStackPtr();--mStackPtr;q4
-Lie;g7
-Default4:;B=qK
-qR
-w4
-wB(458,aK" "
-wS,m5,aI(A)q91(B)wM);q4
-Lfq;}
-}
-}
-if(gV
-h2
-B=qK
-qO
-B
-qP
-1
-gA
-oM
-C=oC
-qR
-C==A){D=qL
-4]qR
-D==B){wB(477,"D[D==B] C[C==A]"
-wH" B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-wH,"D C cSqr"
-wH,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Lif;}
-}
-}
-}
-qG
-TailCall_cNEqual:g5
-cNEqual:oL
-hU
-wB(360,m1
-wW,"[x] "
-wW,wN);q4
-Lig
-qU
-cSqr:wB(362,q41
-wL
-wW,"[x] "
-wW,wN);q4
-Lig;}
-}
-m9(116,mA
-wW,"[fp_nequal(y,x)]"
-,q81);q4
-Lih;qG
-TailCall_cNeg:g5
-hI
-qS
-h3
-gM
-wB(123,"x"
-wH
-aA,mI,wN);q4
-Lii;qT
-hI
-wB(61,qC1
-aA,,);oS
-qU
-cSin:g9
-wB(244,"x"
-wH" "
-mP
-aA,mI" "
-mP,wN);q4
-Lij;}
-qT
-oQ
-g9
-wB(245,"x"
-wH" cSinh"
-aA,mI" cSinh"
-,wN);q4
-Lik;}
-qT
-cTan:g9
-wB(246,"x"
-wH" "
-mR
-aA,mI" "
-mR,wN);q4
-Lil;}
-qT
-cTanh:g9
-wB(247,"x"
-wH" cTanh"
-aA,mI" cTanh"
-,wN);q4
-Lim;}
-qT
-hM
-wB(100,"x"
-aA,"[-x]"
-,wN);q4
-Lin;}
-qH
-TailCall_cNot:g5
-cNot:qS
-cAbsNotNot:wB(231,"cAbsNotNot"
-a0,aS,);q4
-Lio
-qU
-w8:wB(220,aE
-a0,wW,);q4
-Lip
-qU
-o1:wB(218,m2
-a0,aR,);q4
-Liq
-qU
-dK:wB(219,aG
-a0,mJ,);q4
-Lja
-qU
-cLess:wB(216,mJ
-a0,aG,);q4
-Ljb
-qU
-cLessOrEq:wB(217,aR
-a0,m2,);q4
-Ljc
-qU
-cNEqual:wB(221,wW
-a0,aE,);q4
-Ljd
-qU
-cNot:wB(229,"cNot"
-a0,aJ,);q4
-Lbd
-qU
-dS:wB(230,aJ
-a0,"cNot"
-,);q4
-Lje
-gY
-wB(107,"x"
-a0,"[fp_not(x)]"
-,wN);q4
-Ljf;}
-qH
-TailCall_cNotNot:g5
-dS
-d4
-dF==cNot){wB(232,"cNot "
-aJ,"cNot"
-,);gJ}
-qH
-TailCall_cOr:g5
-cOr
-hH
-wB(223,mX"cOr"
-,aJ,);q4
-w7
-m9(118,mA"cOr"
-,"[fp_or(x,y)]"
-,q81);q4
-Ljg;h8}
-qH
-TailCall_cPolar:g5
-cPolar
-d4
-q0[0
-qZ
-y=q7;qJ
-x
-gO
-wB(194,"x "
-aY"cPolar"
-,"[fp_polar(x,y)]"
-," with "
-aY"= "
-<<y
-qD1
-wM);q4
-Ljh;qG
-TailCall_cPow:g5
-cPow:qY
-if(isInteger(x
-gQ
-w2
-wB(43,q21
-wT,wX
-mL,wN);q4
-Lji
-qU
-cExp2:wB(44,"cExp2 "
-wT,wX
-q31,wN);q4
-Ljj
-qU
-cPow
-hL
-qZ
-hP!isInteger(y)){wB(42,"y[!isInteger(y)] "
-q61
-wT,aP,q81);q4
-Ljk;}
-}
-wB(45,q61
-wT,wX" cPow"
-,wN);q4
-Ljl;}
-}
-g8)){wB(83,"x[x==Value_t()] cPow"
-,"[Value_t()]"
-wH" [Value_t(1)]"
-aZ,wN);q4
-Ljm;}
-g8
-oO
-wB(332,"x[x==Value_t(0.5)] cPow"
-,q51,wN);q4
-Ljn;}
-g8
-1)/g1
-3)){wB(333,"x[x==Value_t(1)/Value_t(3)] cPow"
-,"cCbrt"
-,wN);q4
-Ljo;}
-g8
-1)/g1-3)){wB(334,"x[x==Value_t(1)/Value_t(-3)] cPow"
-,"cCbrt "
-aU,wN);q4
-Ljp;}
-g8-oO
-wB(335,"x[x==Value_t(-0.5)] cPow"
-,"cRSqrt"
-,wN);q4
-Ljq;}
-g8-oG
-wB(336,"x[x==Value_t(-1)] cPow"
-,aU,wN);q4
-Lka;}
-qQ
-h9
-cPow
-hL
-qZ
-mW(330,aY
-q61
-m8,aP,q81);q4
-Ljk;o2
-wB(46,q41
-m8,"[x+x] cPow"
-,wN);q4
-Lkb
-qU
-q6:mW(189,aY
-m8,"[fp_pow(y,x)]"
-,q81);q4
-Lkc;}
-wB(455,m8,"[DO_POWI]"
-,wN)qR
-TryCompilePowi(x))gJ}
-qH
-TailCall_cRDiv:g5
-cRDiv:qS
-cSinCos:wB(503,"cSinCos"
-a9,"cCot"
-,);q4
-Leq
-qU
-cSinhCosh:wB(510,"cSinhCosh"
-a9,"cTanh "
-aU,);q4
-Lkd
-gY
-g8
-oG
-wB(268,wO"cRDiv"
-,aU,wN);q4
-Lka;h8}
-qH
-TailCall_cRSub:g5
-cRSub
-d4
-q0[0
-h1
-wB(77,"cDup"
-mE,"[Value_t()]"
-wH,);q4
-Leh;}
-qH
-TailCall_cRad:g5
-cRad:qS
-h3
-gM
-wB(211,"x"
-wH" cRad"
-,"[DegreesToRadians(x)]"
-wH,wN);q4
-Lke;qT
-hM
-wB(134,"x cRad"
-,"[DegreesToRadians(x)]"
-,wN);q4
-Lkf;}
-qH
-TailCall_cReal:g5
-cReal:qY
-wB(191,"x cReal"
-,"[fp_real(x)]"
-,wN);q4
-Lkg;}
-qH
-TailCall_cSec:g5
-cSec:A=qN
-qQ
-h9
-cCos:hD
-wB(497,aK" "
-aO" "
-wI"cSec"
-,"B "
-aO" "
-aT,aI(A)q91(B)wM);q4
-Lcb;qT
-cSin:hD
-wB(495,aK" "
-mP" "
-wI"cSec"
-,"B cSinCos "
-aU,aI(A)q91(B)wM);q4
-Lkh;h8
-qG
-TailCall_cSin:g5
-cSin:qS
-cAsin:wB(345,"cAsin "
-mP,,);q4
-oE
-wB(240,m0
-mP,mP
-aA,);q4
-Lki
-gY
-wB(183,"x "
-mP,"[fp_sin(x)]"
-,wN);q4
-Lkj;oH
-qN
-oY
-cCsc
-q11(499,aK" cCsc "
-wI
-mP,"B cCsc "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-}
-qG
-TailCall_cSinh:g5
-oQ
-qS
-cAcosh:wB(437,"cAcosh cSinh"
-,"[DO_STACKPLUS1] "
-q41"[Value_t(-1)] "
-aQ,);incStackPtr();--mStackPtr;q4
-Lkk
-qU
-cAsinh:wB(349,"cAsinh cSinh"
-,,);q4
-oE
-wB(241,m0"cSinh"
-,"cSinh"
-aA,);q4
-Lkl
-gY
-wB(184,"x cSinh"
-,"[fp_sinh(x)]"
-,wN);q4
-Lkm;}
-qH
-TailCall_cSqr:g5
-cSqr:qS
-cAbs:wB(204,mV" cSqr"
-,"cSqr"
-,);q4
-Lkn
-oF
-wB(203,m0"cSqr"
-,"cSqr"
-,);q4
-Lkn
-qU
-cSqrt:A=dE
-wB(338,wJ
-q51" cSqr"
-,"A"
-,aI(A)wM);oS;h8}
-qH
-TailCall_cSqrt:g5
-cSqrt:qS
-hS
-d4
-qK
-o3
-A=hE
-w0
-if(oC
-o3
-wB(512,"cSqr"
-a3
-q41
-aQ,"A cHypot"
-,aI(A)wM);q4
-Lko;}
-}
-B
-g4
-gV
-B)){A=oC
-w0
-if(qL
-4]o3
-wB(513,"cSqr"
-a3"B[IsUnaryOpcode(B)] "
-q41
-aQ,"A B cHypot"
-," with"
-a8(B)qE1(A)wM);q4
-Lkp;}
-}
-}
-o2
-wB(23,q41
-q51,mV,);q4
-Lkq
-gY
-wB(185,"x "
-q51,"[fp_sqrt(x)]"
-,wN);q4
-Lla;}
-qH
-TailCall_cSub:g5
-cSub
-hH
-wB(76,"cDup"
-aW,"[Value_t()]"
-wH,);q4
-Leh
-oF
-wB(200,qC1
-aW,"cAdd"
-,);q4
-Llb
-gY
-g8)){wB(58,"x[x==Value_t()]"
-aW,,wN);q4
-Lba;}
-m9(106,aY"x"
-aW,"[y-x]"
-,q81);q4
-Llc;}
-wB(51,"x"
-aW,"[-x]"
-aZ,wN);q4
-Lld
-gR
-w0
-oY
-cRSub
-dV
-wB(289,"x"
-mE
-a3"cSub"
-,"A"
-aZ" [x]"
-mE,aI(A)qD1
-wM);q4
-Lle;}
-wB(296,a6
-a3"cSub"
-,"[DO_STACKPLUS1] A"
-aW
-mE,aI(A)wM);incStackPtr();--mStackPtr;q4
-Llf;}
-qG
-TailCall_cTan:g5
-cTan:qS
-cAtan2:wB(354,"cAtan2 "
-mR,"cDiv"
-,);q4
-Lga
-oF
-wB(242,m0
-mR,mR
-aA,);q4
-Llg
-gY
-wB(187,"x "
-mR,"[fp_tan(x)]"
-,wN);q4
-Llh;oH
-qN
-oY
-cCot
-q11(501,aK" cCot "
-wI
-mR,"B cCot "
-aT,aI(A)q91(B)wM);q4
-Lcb;}
-}
-qG
-TailCall_cTanh:g5
-cTanh:qS
-cAtanh:wB(352,"cAtanh cTanh"
-,,);q4
-oE
-wB(243,m0"cTanh"
-,"cTanh"
-aA,);q4
-Lli
-gY
-wB(188,"x cTanh"
-,"[fp_tanh(x)]"
-,wN);q4
-Llj;}
-qH
-TailCall_cTrunc:g5
-cTrunc:qS
-hM
-wB(138,"x cTrunc"
-,"[fp_trunc(x)]"
-,wN);q4
-Llk
-gS
-wB(394,"A[IsAlwaysIntegerOpcode(A)] cTrunc"
-,"A"
-,aI(A)wM);gJ
-qG
-g7
-Default0:;A=w5
-w1
-0){B=q0[0
-hZ
-wB(475,aK" A[IsVarOpcode(A)&&mData->mByteCode.size()>0]"
-,"B"
-mQ,aI(A)q91(B)wM);q4
-Lll;}
-}
-if(gV
-h2
-B=dF
-qO
-B
-qP
-1){C=qK
-qR
-C==A){D
-g4
-D==B){wB(476,"D[D==B] C[C==A] B[IsVarOpcode(B)&&mData->mByteCode.size()>1] A[IsUnaryOpcode(A)]"
-,"D C"
-mQ,aI(A)q91(B)<<", C"
-wY(C)<<", D"
-wY(D)wM);q4
-Llm;}
-}
-}
-}
-C=w5
-qR
-IsCommutativeOrParamSwappableBinaryOpcode(C)){qS
-cSin:A=qK
-w1
-3
-gA]==cCos){B=hQ
-wB(505,aK" "
-aO" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] "
-mP" C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinCos {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Lln;}
-}
-qT
-oQ
-A=qK
-w1
-3
-gA]==cCosh){B=hQ
-wB(506,aK" "
-aM" A[IsVarOpcode(A)&&mData->mByteCode.size()>3] cSinh C[IsCommutativeOrParamSwappableBinaryOpcode(C)]"
-,"B cSinhCosh {GetParamSwappedBinaryOpcode(C)}"
-," with C"
-wY(C)qE1(A)q91(B)wM);q4
-Llo;}
-}
-h8}
-}
-}
-q4
-Laa;Laa:qW
-w5);gJ
-Lab:g6
-Llp:wE(cAbs);q4
-TailCall_cAbs;Lac:q7=dP;gJ
-Lad:q7=fp_acos
-m6
-Lae:q7=fp_acosh
-m6
-Laf:oZ
-4));gG
-Llq:w5=h3;Lma:g0
-Lmb:wE(cMul);q4
-TailCall_cMul;Lag:hV
-4
-dT
-oZ
-4));Lmc:qW
-q6
-hY;Lah:q7=x+g1
-1);gG
-Lfb:w5=h3;q4
-Lmb;Lai:gU
-cSub;Lmd:wE(cSub);q4
-TailCall_cSub;Laj:hW
-2
-gH
-Lme:g0
-Lmf:wE(cAdd);q4
-TailCall_cAdd;Lak:hW
-oR
-Lmg:qE
-hS);Lmh:w5=cRSub;g0
-wE(cRSub);q4
-TailCall_cRSub;Lal:o9;qL
-2
-gK
-q4
-Lmg;Lam:hW
-2
-gH
-q4
-Lmh;Lan:hW
-4
-gH
-Lmi:qE
-hS);Lmj:qE
-B);Lmk:w5=cSub;g0
-q4
-Lmd;Lao:o9;oC=q6
-q9
-oR
-q4
-Lmi;Lap:hW
-oR
-q4
-Lmj;Laq:gT
-y+x;Lba:qM
-Lbo:q5
-gJ
-Lbb:q8
-oV
-o7
-x
-q71
-gX
-Lmg;Lbc:mM
-A
-gX
-Lmg;Lbd:gU
-dS;wE(cNotNot);q4
-TailCall_cNotNot;Lbe:gT
-fp_and(x
-d6
-Lbf:q7=fp_arg
-m6
-Lbg:q7=fp_asin
-m6
-Lbh:q7=fp_asinh
-m6
-Lbi:q7=fp_atan
-m6
-Lbj:gT
-fp_atan2(gW
-Lbk:q7=fp_atanh
-m6
-Lbl:q7=fp_cbrt
-m6
-Lbm:q1
-cFloor);Lml:w5=cNeg;g0
-wE(cNeg);q4
-TailCall_cNeg;Lbn:q7=fp_ceil
-m6
-Lbp:q7=fp_conj
-m6
-Lbq:g6
-Lmm:wE(cCos);q4
-TailCall_cCos;Lca:q7=fp_cos
-m6
-Lcb:dF=cDup;w5=cInv;Lmn:wE(cInv);q4
-TailCall_cInv;Lcc:mM
-cSinCos);gJ
-Lcd:q1
-cSqr
-o7
-g1
-1));Lmo:qW
-q6
-oJ
-hS);Lmp:w5=cSqrt;g0
-wE(cSqrt);q4
-TailCall_cSqrt;Lce:g6
-wE(cCosh);q4
-TailCall_cCosh;Lcf:q7=fp_cosh
-m6
-Lcg:mM
-cSinhCosh);gJ
-Lch:q7=RadiansToDegrees
-m6
-Lci:q1
-cSec
-hY;Lcj:q1
-cTan
-hY;Lck:q1
-cSin
-hY;Lcl:oZ));dF
-dJ
-Lmq:qE
-dU
-oZ
-1));Lna:qW
-q6);Lnb:w5=hS;q4
-Lme;Lcm:q1
-cNeg
-oJ
-cExp
-hY;Lcn:q1
-cNeg
-oJ
-cExp2
-hY;Lco:g6
-q4
-Lfb;Lcp:q1
-cNeg
-oJ
-cPow
-hY;Lcq:q1
-cCos
-hY;Lda:q1
-cCsc
-hY;Ldb:gU
-cTan;Lnc:wE(cTan);q4
-TailCall_cTan;Ldc:gU
-cTanh;Lnd:wE(cTanh);q4
-TailCall_cTanh;Ldd:q1
-cCot
-hY;Lde:o9;dI
-Lne:wE(cDiv);q4
-TailCall_cDiv;Ldf:gT
-y/x;q4
-Lba;Ldg:qF1
-q8
-oR
-Lnf:w5=cDeg;g0
-wE(cDeg);q4
-TailCall_cDeg;Ldh:qF1
-q8
-oR
-Lng:w5=cRad;g0
-wE(cRad);q4
-TailCall_cRad;Ldi:gT
-y/x;dG
-Llq;Ldj:q7=g1
-1)/x;q4
-Lfb;Ldk:mM
-oI
-Lnh:g0
-q4
-Lne;Ldl:q8
-3
-gC
-oI
-qF
-x
-q71);Lni:w5=cRDiv;g0
-wE(cRDiv);q4
-TailCall_cRDiv;Ldm:hV
-3
-gC
-oI
-qE
-B
-gX
-Lni;Ldn:dI
-Lnj:wE(cEqual);q4
-TailCall_cEqual;Ldo:gT
-fp_equal(gW
-Ldp:d7
-cExp
-o7
-fp_exp(x)gX
-Lmc;Ldq:q7=fp_exp
-m6
-Lea:d7
-cExp2
-o7
-fp_exp2(x)gX
-Lmc;Leb:q7=fp_exp2
-m6
-Lec:qF
-oW
-g1
-2))q71);Lnk:qE
-h3
-gI
-cExp;g0
-wE(cExp);q4
-TailCall_cExp;Led:q1
-cCeil
-oT
-Lee:q7=fp_floor
-m6
-Lef:gT
-fp_less(x
-d6
-Leg:gT
-fp_lessOrEq(x
-d6
-Leh:oZ));Lnl:dF
-dJ
-q4
-Llq;Lei:q7=fp_imag
-m6
-Lej:q7=fp_int
-m6
-Lek:gU
-cSec;wE(cSec);q4
-TailCall_cSec;Lel:gU
-cSin;Lnm:wE(cSin);q4
-TailCall_cSin;Lem:q1
-cNeg
-gI
-cPow;Lnn:g0
-Lno:wE(cPow);q4
-TailCall_cPow;Len:gU
-cCos;q4
-Lmm;Leo:gU
-cCsc;wE(cCsc);q4
-TailCall_cCsc;Lep:q1
-cRSqrt);gJ
-Leq:g6
-Lnp:w5=cCot;wE(cCot);q4
-TailCall_cCot;Lfa:q7=g1
-1)/x;gJ
-Lfc:gT
-fp_less(gW
-Lfd:gT
-fp_lessOrEq(gW
-Lfe:d7
-cLog
-o7
-oW
-x)gX
-Lna;Lff:q7=oW
-x);gJ
-Lfg:qF
-dR
-fp_const_e<dH>())gX
-Lnl;Lfh:d7
-cLog10
-o7
-dR
-x)gX
-Lna;Lfi:q7=dR
-x);gJ
-Lfj:qF
-o4
-fp_const_e<dH>())gX
-Lnl;Lfk:d7
-cLog2
-o7
-o4
-x)gX
-Lna;Lfl:q7=o4
-x);gJ
-Lfm:gT
-fp_max(x
-d6
-Lfn:gT
-fp_min(x
-d6
-Lfo:gT
-fp_mod(gW
-Lfp:hV
-oR
-q0-=3;q4
-Lnp;Lfq:gU
-cSqr;Lnq:wE(cSqr);q4
-TailCall_cSqr;Lga:gU
-cDiv;q4
-Lne;Lgb:mM
-cSqr
-oT
-Lgc:hV
-3
-gC
-cSqr);dM
-Lml;Lgd:q7=x+g1
-1);gG
-w5=cPow;q4
-Lno;Lge:gG
-q4
-Lmb;Lgf:gT
-x;Loa:dG
-Lma;Lgg:qF1
-qM
-Lob:hV
-4
-gH
-Loc:o6
-x);Lod:qW
-q6
-gX
-Lma;Lgh:qM
-q4
-Lob;Lgi:q8
-4
-gC
-B
-gX
-Loc;Lgj:q8
-oR
-q4
-Loc;Lgk:qK
-dJ
-oS;Lgl:dI
-q4
-Lmb;Lgm:qM
-Loe:hV
-oR
-gJ
-Lgn:q7=x+x;q4
-Lge;Lgo:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lnb;Lgp:gT
-x;d7
-dU
-qF
-y*x
-gX
-Lna;Lgq:q7=RadiansToDegrees(x
-gX
-Lgl;Lha:qG1
-q8
-4
-gH
-Lof:qE
-dU
-Log:qE
-B
-gI
-cDiv;q4
-Lnh;Lhb:o9;oC=q6
-q9
-oR
-q4
-Lof;Lhc:qG1
-q8
-oR
-q4
-Log;Lhd:q8
-4
-gH
-q4
-Lma;Lhe:q8
-4
-dT
-qF
-x+x
-gX
-Lod;Lhf:qF1
-qM
-q4
-Loe;Lhg:qG1
-q4
-Loa;Lhh:o9;q4
-Lgl;Lhi:qG1
-q8
-oR
-Loh:dM
-Lni;Lhj:o9;qL
-2
-gK
-q4
-Loh;Lhk:qG1
-dG
-Lni;Lhl:q7=h4
-gX
-Lgl;Lhm:gT
-x;qL
-4]dJ
-q8
-4
-dT
-o6
-y*x
-q71);dM
-Lmk;Lhn:qG1
-q4
-Lba;Lho:qM
-w3
-Lml;Lhp:dF=cDup;dW-=1;qM
-Loi:w5=hS;q4
-Lmf;Lhq:qM
-w3
-Lnf;Lia:qM
-w3
-Lng;Lib:hV
-oV
-gX
-Lof;Lic:hV
-2
-gH
-Loj:qE
-cSqr
-gX
-Lma;Lid:q8
-oV
-o7
-x
-q71
-gX
-Loh;Lie:mM
-A
-gX
-Loh;Lif:hV
-oR
-q4
-Loj;Lig:dI
-Lok:wE(cNEqual);q4
-TailCall_cNEqual;Lih:gT
-fp_nequal(gW
-Lii:o9;q4
-Lco;Lij:o9
-gB
-cSin;g0
-q4
-Lnm;Lik:o9
-gB
-cSinh;g0
-wE(cSinh);q4
-TailCall_cSinh;Lil:o9
-gB
-cTan;g0
-q4
-Lnc;Lim:o9
-gB
-cTanh;g0
-q4
-Lnd;Lin:o9;gJ
-Lio:q1
-cAbsNot);gJ
-Lip:gU
-cNEqual;q4
-Lok;Liq:gU
-cLessOrEq;wE(cLessOrEq);q4
-TailCall_cLessOrEq;Lja:gU
-cLess;wE(cLess);q4
-TailCall_cLess;Ljb:gU
-dK;wE(cGreaterOrEq);q4
-TailCall_cGreaterOrEq;Ljc:gU
-o1;wE(cGreater);q4
-TailCall_cGreater;Ljd:gU
-w8;q4
-Lnj;Lje:g6
-wE(cNot);q4
-TailCall_cNot;Ljf:q7=fp_not
-m6
-Ljg:gT
-fp_or(x
-d6
-Ljh:gT
-fp_polar(x
-d6
-Lji:dL
-Lnk;Ljj:qK=d8
-cExp2;g0
-wE(cExp2);q4
-TailCall_cExp2;Ljk:qG1
-dG
-Lnn;Ljl:qK
-dJ
-q1
-h3
-gX
-Lnn;Ljm:q7=g1
-gX
-Lmq;Ljn:qM
-w3
-Lmp;Ljo:qM
-q5
-w5=cCbrt;g0
-wE(cCbrt);q4
-TailCall_cCbrt;Ljp:qM
-q1
-cCbrt);Lol:w5=cInv;g0
-q4
-Lmn;Ljq:qM
-q4
-Lep;Lka:qM
-w3
-Lol;Lkb:q7=x+x;dI
-q4
-Lno;Lkc:gT
-oX
-gW
-Lkd:q1
-cTanh
-gX
-Lol;Lke:q7=h4
-gX
-Lco;Lkf:q7=h4);gJ
-Lkg:q7=fp_real
-m6
-Lkh:mM
-cSinCos
-gX
-Lol;Lki:q1
-cSin
-oT
-Lkj:q7=fp_sin
-m6
-Lkk:q1
-cSqr
-o7
-g1-1)gX
-Lmo;Lkl:q1
-cSinh
-oT
-Lkm:q7=fp_sinh
-m6
-Lkn:g6
-q4
-Lnq;Lko:hV
-4
-gC
-A);Lom:w5=cHypot;g0
-wE(cHypot);q4
-TailCall_cHypot;Lkp:hV
-5
-gC
-A
-oJ
-B
-gX
-Lom;Lkq:gU
-cAbs;q4
-Llp;Lla:q7=fp_sqrt
-m6
-Llb:g6
-q4
-Loi;Llc:gT
-y-x;q4
-Lba;Lld:o9;q4
-Loi;Lle:q8
-oV
-oJ
-hS
-o7
-x
-q71
-gX
-Lmh;Llf:mM
-A
-oJ
-cSub
-gX
-Lmh;Llg:q1
-cTan
-oT
-Llh:q7=fp_tan
-m6
-Lli:q1
-cTanh
-oT
-Llj:q7=fp_tanh
-m6
-Llk:q7=fp_trunc
-m6
-Lll:qW
-cDup);gJ
-Llm:dF=cDup;gJ
-Lln:hV
-3
-gC
-cSinCos);Lon:qE
-GetParamSwappedBinaryOpcode(C));gJ
-Llo:hV
-3
-gC
-cSinhCosh
-gX
-Lon;gJ
-q4
-TailCall_cAcos;q4
-TailCall_cAcosh;q4
-TailCall_cAnd;q4
-TailCall_cArg;q4
-TailCall_cAsin;q4
-TailCall_cAsinh;q4
-TailCall_cAtan;q4
-TailCall_cAtan2;q4
-TailCall_cAtanh;q4
-TailCall_cCeil;q4
-TailCall_cConj;q4
-TailCall_cFloor;q4
-TailCall_cImag;q4
-TailCall_cInt;q4
-TailCall_cLog;q4
-TailCall_cLog10;q4
-TailCall_cLog2;q4
-TailCall_cMax;q4
-TailCall_cMin;q4
-TailCall_cMod;q4
-TailCall_cOr;q4
-TailCall_cPolar;q4
-TailCall_cRDiv;q4
-TailCall_cRad;q4
-TailCall_cReal;q4
-TailCall_cSec;q4
-TailCall_cSin;q4
-TailCall_cSinh;q4
-TailCall_cSqrt;q4
-TailCall_cSub;q4
-TailCall_cTan;q4
-TailCall_cTanh;q4
-TailCall_cTrunc;
-#endif
-#undef FP_ReDefinePointers
-#undef FP_TRACE_BYTECODE_OPTIMIZATION
-#undef FP_TRACE_OPCODENAME
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// NOTE:
-// This file contains only internal types for the function parser library.
-// You don't need to include this file in your code. Include "fparser.hh"
-// only.
-
-#ifndef ONCE_FPARSER_AUX_H_
-#define ONCE_FPARSER_AUX_H_
-
-#include "fptypes.hh"
-
-#include <cmath>
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-#include "mpfr/MpfrFloat.hh"
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-#include "mpfr/GmpInt.hh"
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-#include <complex>
-#endif
-
-#ifdef ONCE_FPARSER_H_
-namespace FUNCTIONPARSERTYPES
-{
- template<typename>
- struct IsIntType
- {
- enum { result = false };
- };
- template<>
- struct IsIntType<long>
- {
- enum { result = true };
- };
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- struct IsIntType<GmpInt>
- {
- enum { result = true };
- };
-#endif
-
- template<typename>
- struct IsComplexType
- {
- enum { result = false };
- };
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- struct IsComplexType<std::complex<T> >
- {
- enum { result = true };
- };
-#endif
-
-
-//==========================================================================
-// Constants
-//==========================================================================
- template<typename Value_t>
- inline Value_t fp_const_pi() // CONSTANT_PI
- {
- return Value_t(3.1415926535897932384626433832795028841971693993751L);
- }
-
- template<typename Value_t>
- inline Value_t fp_const_e() // CONSTANT_E
- {
- return Value_t(2.7182818284590452353602874713526624977572L);
- }
- template<typename Value_t>
- inline Value_t fp_const_einv() // CONSTANT_EI
- {
- return Value_t(0.367879441171442321595523770161460867445811131L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log2() // CONSTANT_L2, CONSTANT_L2EI
- {
- return Value_t(0.69314718055994530941723212145817656807550013436025525412L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log10() // CONSTANT_L10, CONSTANT_L10EI
- {
- return Value_t(2.302585092994045684017991454684364207601101488628772976L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log2inv() // CONSTANT_L2I, CONSTANT_L2E
- {
- return Value_t(1.442695040888963407359924681001892137426645954L);
- }
- template<typename Value_t>
- inline Value_t fp_const_log10inv() // CONSTANT_L10I, CONSTANT_L10E
- {
- return Value_t(0.434294481903251827651128918916605082294397L);
- }
-
- template<typename Value_t>
- inline const Value_t& fp_const_deg_to_rad() // CONSTANT_DR
- {
- static const Value_t factor = fp_const_pi<Value_t>() / Value_t(180); // to rad from deg
- return factor;
- }
-
- template<typename Value_t>
- inline const Value_t& fp_const_rad_to_deg() // CONSTANT_RD
- {
- static const Value_t factor = Value_t(180) / fp_const_pi<Value_t>(); // to deg from rad
- return factor;
- }
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline MpfrFloat fp_const_pi<MpfrFloat>() { return MpfrFloat::const_pi(); }
-
- template<>
- inline MpfrFloat fp_const_e<MpfrFloat>() { return MpfrFloat::const_e(); }
-
- template<>
- inline MpfrFloat fp_const_einv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_e(); }
-
- template<>
- inline MpfrFloat fp_const_log2<MpfrFloat>() { return MpfrFloat::const_log2(); }
-
- /*
- template<>
- inline MpfrFloat fp_const_log10<MpfrFloat>() { return fp_log(MpfrFloat(10)); }
-
- template<>
- inline MpfrFloat fp_const_log2inv<MpfrFloat>() { return MpfrFloat(1) / MpfrFloat::const_log2(); }
-
- template<>
- inline MpfrFloat fp_const_log10inv<MpfrFloat>() { return fp_log10(MpfrFloat::const_e()); }
- */
-#endif
-
-
-//==========================================================================
-// Generic math functions
-//==========================================================================
- template<typename Value_t>
- inline Value_t fp_abs(const Value_t& x) { return std::fabs(x); }
-
- template<typename Value_t>
- inline Value_t fp_acos(const Value_t& x) { return std::acos(x); }
-
- template<typename Value_t>
- inline Value_t fp_asin(const Value_t& x) { return std::asin(x); }
-
- template<typename Value_t>
- inline Value_t fp_atan(const Value_t& x) { return std::atan(x); }
-
- template<typename Value_t>
- inline Value_t fp_atan2(const Value_t& x, const Value_t& y)
- { return std::atan2(x, y); }
-
- template<typename Value_t>
- inline Value_t fp_ceil(const Value_t& x) { return std::ceil(x); }
-
- template<typename Value_t>
- inline Value_t fp_cos(const Value_t& x) { return std::cos(x); }
-
- template<typename Value_t>
- inline Value_t fp_cosh(const Value_t& x) { return std::cosh(x); }
-
- template<typename Value_t>
- inline Value_t fp_exp(const Value_t& x) { return std::exp(x); }
-
- template<typename Value_t>
- inline Value_t fp_floor(const Value_t& x) { return std::floor(x); }
-
- template<typename Value_t>
- inline Value_t fp_log(const Value_t& x) { return std::log(x); }
-
- template<typename Value_t>
- inline Value_t fp_mod(const Value_t& x, const Value_t& y)
- { return std::fmod(x, y); }
-
- template<typename Value_t>
- inline Value_t fp_sin(const Value_t& x) { return std::sin(x); }
-
- template<typename Value_t>
- inline Value_t fp_sinh(const Value_t& x) { return std::sinh(x); }
-
- template<typename Value_t>
- inline Value_t fp_sqrt(const Value_t& x) { return std::sqrt(x); }
-
- template<typename Value_t>
- inline Value_t fp_tan(const Value_t& x) { return std::tan(x); }
-
- template<typename Value_t>
- inline Value_t fp_tanh(const Value_t& x) { return std::tanh(x); }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_asinh(const Value_t& x) { return std::asinh(x); }
-
- template<typename Value_t>
- inline Value_t fp_acosh(const Value_t& x) { return std::acosh(x); }
-
- template<typename Value_t>
- inline Value_t fp_atanh(const Value_t& x) { return std::atanh(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_asinh(const Value_t& x)
- { return fp_log(x + fp_sqrt(x*x + Value_t(1))); }
-
- template<typename Value_t>
- inline Value_t fp_acosh(const Value_t& x)
- { return fp_log(x + fp_sqrt(x*x - Value_t(1))); }
-
- template<typename Value_t>
- inline Value_t fp_atanh(const Value_t& x)
- {
- return fp_log( (Value_t(1)+x) / (Value_t(1)-x)) * Value_t(0.5);
- // Note: x = +1 causes division by zero
- // x = -1 causes log(0)
- // Thus, x must not be +-1
- }
-#endif // FP_SUPPORT_ASINH
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
- { return std::hypot(x,y); }
-#else
- template<typename Value_t>
- inline Value_t fp_hypot(const Value_t& x, const Value_t& y)
- { return fp_sqrt(x*x + y*y); }
-#endif
-
- template<typename Value_t>
- inline Value_t fp_pow_base(const Value_t& x, const Value_t& y)
- { return std::pow(x, y); }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_log2(const Value_t& x) { return std::log2(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_log2(const Value_t& x)
- {
- return fp_log(x) * fp_const_log2inv<Value_t>();
- }
-#endif // FP_SUPPORT_LOG2
-
- template<typename Value_t>
- inline Value_t fp_log10(const Value_t& x)
- {
- return fp_log(x) * fp_const_log10inv<Value_t>();
- }
-
- template<typename Value_t>
- inline Value_t fp_trunc(const Value_t& x)
- {
- return x < Value_t() ? fp_ceil(x) : fp_floor(x);
- }
-
- template<typename Value_t>
- inline Value_t fp_int(const Value_t& x)
- {
- return x < Value_t() ?
- fp_ceil(x - Value_t(0.5)) : fp_floor(x + Value_t(0.5));
- }
-
- template<typename Value_t>
- inline void fp_sinCos(Value_t& sinvalue, Value_t& cosvalue,
- const Value_t& param)
- {
- // Assuming that "cosvalue" and "param" do not
- // overlap, but "sinvalue" and "param" may.
- cosvalue = fp_cos(param);
- sinvalue = fp_sin(param);
- }
-
- template<typename Value_t>
- inline void fp_sinhCosh(Value_t& sinhvalue, Value_t& coshvalue,
- const Value_t& param)
- {
- const Value_t ex(fp_exp(param)), emx(fp_exp(-param));
- sinhvalue = Value_t(0.5)*(ex-emx);
- coshvalue = Value_t(0.5)*(ex+emx);
- }
-
- template<typename Value_t>
- struct Epsilon
- {
- static Value_t value;
- static Value_t defaultValue() { return 0; }
- };
-
- template<> inline double Epsilon<double>::defaultValue() { return 1E-12; }
- template<> inline float Epsilon<float>::defaultValue() { return 1E-5F; }
- template<> inline long double Epsilon<long double>::defaultValue() { return 1E-14L; }
-
- template<> inline std::complex<double>
- Epsilon<std::complex<double> >::defaultValue() { return 1E-12; }
-
- template<> inline std::complex<float>
- Epsilon<std::complex<float> >::defaultValue() { return 1E-5F; }
-
- template<> inline std::complex<long double>
- Epsilon<std::complex<long double> >::defaultValue() { return 1E-14L; }
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<> inline MpfrFloat
- Epsilon<MpfrFloat>::defaultValue() { return MpfrFloat::someEpsilon(); }
-#endif
-
- template<typename Value_t> Value_t Epsilon<Value_t>::value =
- Epsilon<Value_t>::defaultValue();
-
-
-#ifdef _GNU_SOURCE
- inline void fp_sinCos(double& sin, double& cos, const double& a)
- {
- sincos(a, &sin, &cos);
- }
- inline void fp_sinCos(float& sin, float& cos, const float& a)
- {
- sincosf(a, &sin, &cos);
- }
- inline void fp_sinCos(long double& sin, long double& cos,
- const long double& a)
- {
- sincosl(a, &sin, &cos);
- }
-#endif
-
-
-// -------------------------------------------------------------------------
-// Long int
-// -------------------------------------------------------------------------
- inline long fp_abs(const long& x) { return x < 0 ? -x : x; }
- inline long fp_acos(const long&) { return 0; }
- inline long fp_asin(const long&) { return 0; }
- inline long fp_atan(const long&) { return 0; }
- inline long fp_atan2(const long&, const long&) { return 0; }
- inline long fp_cbrt(const long&) { return 0; }
- inline long fp_ceil(const long& x) { return x; }
- inline long fp_cos(const long&) { return 0; }
- inline long fp_cosh(const long&) { return 0; }
- inline long fp_exp(const long&) { return 0; }
- inline long fp_exp2(const long&) { return 0; }
- inline long fp_floor(const long& x) { return x; }
- inline long fp_log(const long&) { return 0; }
- inline long fp_log2(const long&) { return 0; }
- inline long fp_log10(const long&) { return 0; }
- inline long fp_mod(const long& x, const long& y) { return x % y; }
- inline long fp_pow(const long&, const long&) { return 0; }
- inline long fp_sin(const long&) { return 0; }
- inline long fp_sinh(const long&) { return 0; }
- inline long fp_sqrt(const long&) { return 1; }
- inline long fp_tan(const long&) { return 0; }
- inline long fp_tanh(const long&) { return 0; }
- inline long fp_asinh(const long&) { return 0; }
- inline long fp_acosh(const long&) { return 0; }
- inline long fp_atanh(const long&) { return 0; }
- inline long fp_pow_base(const long&, const long&) { return 0; }
- inline void fp_sinCos(long&, long&, const long&) {}
- inline void fp_sinhCosh(long&, long&, const long&) {}
-
- //template<> inline long fp_epsilon<long>() { return 0; }
-
-
-// -------------------------------------------------------------------------
-// MpfrFloat
-// -------------------------------------------------------------------------
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- inline MpfrFloat fp_abs(const MpfrFloat& x) { return MpfrFloat::abs(x); }
- inline MpfrFloat fp_acos(const MpfrFloat& x) { return MpfrFloat::acos(x); }
- inline MpfrFloat fp_acosh(const MpfrFloat& x) { return MpfrFloat::acosh(x); }
- inline MpfrFloat fp_asin(const MpfrFloat& x) { return MpfrFloat::asin(x); }
- inline MpfrFloat fp_asinh(const MpfrFloat& x) { return MpfrFloat::asinh(x); }
- inline MpfrFloat fp_atan(const MpfrFloat& x) { return MpfrFloat::atan(x); }
- inline MpfrFloat fp_atan2(const MpfrFloat& x, const MpfrFloat& y)
- { return MpfrFloat::atan2(x, y); }
- inline MpfrFloat fp_atanh(const MpfrFloat& x) { return MpfrFloat::atanh(x); }
- inline MpfrFloat fp_cbrt(const MpfrFloat& x) { return MpfrFloat::cbrt(x); }
- inline MpfrFloat fp_ceil(const MpfrFloat& x) { return MpfrFloat::ceil(x); }
- inline MpfrFloat fp_cos(const MpfrFloat& x) { return MpfrFloat::cos(x); }
- inline MpfrFloat fp_cosh(const MpfrFloat& x) { return MpfrFloat::cosh(x); }
- inline MpfrFloat fp_exp(const MpfrFloat& x) { return MpfrFloat::exp(x); }
- inline MpfrFloat fp_exp2(const MpfrFloat& x) { return MpfrFloat::exp2(x); }
- inline MpfrFloat fp_floor(const MpfrFloat& x) { return MpfrFloat::floor(x); }
- inline MpfrFloat fp_hypot(const MpfrFloat& x, const MpfrFloat& y)
- { return MpfrFloat::hypot(x, y); }
- inline MpfrFloat fp_int(const MpfrFloat& x) { return MpfrFloat::round(x); }
- inline MpfrFloat fp_log(const MpfrFloat& x) { return MpfrFloat::log(x); }
- inline MpfrFloat fp_log2(const MpfrFloat& x) { return MpfrFloat::log2(x); }
- inline MpfrFloat fp_log10(const MpfrFloat& x) { return MpfrFloat::log10(x); }
- inline MpfrFloat fp_mod(const MpfrFloat& x, const MpfrFloat& y) { return x % y; }
- inline MpfrFloat fp_sin(const MpfrFloat& x) { return MpfrFloat::sin(x); }
- inline MpfrFloat fp_sinh(const MpfrFloat& x) { return MpfrFloat::sinh(x); }
- inline MpfrFloat fp_sqrt(const MpfrFloat& x) { return MpfrFloat::sqrt(x); }
- inline MpfrFloat fp_tan(const MpfrFloat& x) { return MpfrFloat::tan(x); }
- inline MpfrFloat fp_tanh(const MpfrFloat& x) { return MpfrFloat::tanh(x); }
- inline MpfrFloat fp_trunc(const MpfrFloat& x) { return MpfrFloat::trunc(x); }
-
- inline MpfrFloat fp_pow(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
- inline MpfrFloat fp_pow_base(const MpfrFloat& x, const MpfrFloat& y) { return MpfrFloat::pow(x, y); }
-
-
- inline void fp_sinCos(MpfrFloat& sin, MpfrFloat& cos, const MpfrFloat& a)
- {
- MpfrFloat::sincos(a, sin, cos);
- }
-
- inline void fp_sinhCosh(MpfrFloat& sinhvalue, MpfrFloat& coshvalue,
- const MpfrFloat& param)
- {
- const MpfrFloat paramCopy = param;
- sinhvalue = fp_sinh(paramCopy);
- coshvalue = fp_cosh(paramCopy);
- }
-#endif // FP_SUPPORT_MPFR_FLOAT_TYPE
-
-
-// -------------------------------------------------------------------------
-// GMP int
-// -------------------------------------------------------------------------
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- inline GmpInt fp_abs(const GmpInt& x) { return GmpInt::abs(x); }
- inline GmpInt fp_acos(const GmpInt&) { return 0; }
- inline GmpInt fp_acosh(const GmpInt&) { return 0; }
- inline GmpInt fp_asin(const GmpInt&) { return 0; }
- inline GmpInt fp_asinh(const GmpInt&) { return 0; }
- inline GmpInt fp_atan(const GmpInt&) { return 0; }
- inline GmpInt fp_atan2(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_atanh(const GmpInt&) { return 0; }
- inline GmpInt fp_cbrt(const GmpInt&) { return 0; }
- inline GmpInt fp_ceil(const GmpInt& x) { return x; }
- inline GmpInt fp_cos(const GmpInt&) { return 0; }
- inline GmpInt fp_cosh(const GmpInt&) { return 0; }
- inline GmpInt fp_exp(const GmpInt&) { return 0; }
- inline GmpInt fp_exp2(const GmpInt&) { return 0; }
- inline GmpInt fp_floor(const GmpInt& x) { return x; }
- inline GmpInt fp_hypot(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_int(const GmpInt& x) { return x; }
- inline GmpInt fp_log(const GmpInt&) { return 0; }
- inline GmpInt fp_log2(const GmpInt&) { return 0; }
- inline GmpInt fp_log10(const GmpInt&) { return 0; }
- inline GmpInt fp_mod(const GmpInt& x, const GmpInt& y) { return x % y; }
- inline GmpInt fp_pow(const GmpInt&, const GmpInt&) { return 0; }
- inline GmpInt fp_sin(const GmpInt&) { return 0; }
- inline GmpInt fp_sinh(const GmpInt&) { return 0; }
- inline GmpInt fp_sqrt(const GmpInt&) { return 0; }
- inline GmpInt fp_tan(const GmpInt&) { return 0; }
- inline GmpInt fp_tanh(const GmpInt&) { return 0; }
- inline GmpInt fp_trunc(const GmpInt& x) { return x; }
- inline GmpInt fp_pow_base(const GmpInt&, const GmpInt&) { return 0; }
- inline void fp_sinCos(GmpInt&, GmpInt&, const GmpInt&) {}
- inline void fp_sinhCosh(GmpInt&, GmpInt&, const GmpInt&) {}
-#endif // FP_SUPPORT_GMP_INT_TYPE
-
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename Value_t>
- inline Value_t fp_cbrt(const Value_t& x) { return std::cbrt(x); }
-#else
- template<typename Value_t>
- inline Value_t fp_cbrt(const Value_t& x)
- {
- return (x > Value_t() ? fp_exp(fp_log( x) / Value_t(3)) :
- x < Value_t() ? -fp_exp(fp_log(-x) / Value_t(3)) :
- Value_t());
- }
-#endif
-
-// -------------------------------------------------------------------------
-// Synthetic functions and fallbacks for when an optimized
-// implementation or a library function is not available
-// -------------------------------------------------------------------------
- template<typename Value_t> inline Value_t fp_arg(const Value_t& x);
- template<typename Value_t> inline Value_t fp_exp2(const Value_t& x);
- template<typename Value_t> inline Value_t fp_int(const Value_t& x);
- template<typename Value_t> inline Value_t fp_trunc(const Value_t& x);
- template<typename Value_t>
- inline void fp_sinCos(Value_t& , Value_t& , const Value_t& );
- template<typename Value_t>
- inline void fp_sinhCosh(Value_t& , Value_t& , const Value_t& );
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- /* NOTE: Complex multiplication of a and b can be done with:
- tmp = b.real * (a.real + a.imag)
- result.real = tmp - a.imag * (b.real + b.imag)
- result.imag = tmp + a.real * (b.imag - b.real)
- This has fewer multiplications than the standard
- algorithm. Take note, if you support mpfr complex one day.
- */
-
- template<typename T>
- struct FP_ProbablyHasFastLibcComplex
- { enum { result = false }; };
- /* The generic sqrt() etc. implementations in libstdc++
- * are very plain and non-optimized; however, it contains
- * callbacks to libc complex math functions where possible,
- * and I suspect that those may actually be well optimized.
- * So we use std:: functions when we suspect they may be fast,
- * and otherwise we use our own optimized implementations.
- */
-#ifdef __GNUC__
- template<> struct FP_ProbablyHasFastLibcComplex<float>
- { enum { result = true }; };
- template<> struct FP_ProbablyHasFastLibcComplex<double>
- { enum { result = true }; };
- template<> struct FP_ProbablyHasFastLibcComplex<long double>
- { enum { result = true }; };
-#endif
-
- template<typename T>
- inline const std::complex<T> fp_make_imag(const std::complex<T>& v)
- {
- return std::complex<T> ( T(), v.real() );
- }
-
- template<typename T>
- inline std::complex<T> fp_real(const std::complex<T>& x)
- {
- return x.real();
- }
- template<typename T>
- inline std::complex<T> fp_imag(const std::complex<T>& x)
- {
- return x.imag();
- }
- template<typename T>
- inline std::complex<T> fp_arg(const std::complex<T>& x)
- {
- return std::arg(x);
- }
- template<typename T>
- inline std::complex<T> fp_conj(const std::complex<T>& x)
- {
- return std::conj(x);
- }
- template<typename T, bool>
- inline std::complex<T> fp_polar(const T& x, const T& y)
- {
- T si, co; fp_sinCos(si, co, y);
- return std::complex<T> (x*co, x*si);
- }
- template<typename T>
- inline std::complex<T> fp_polar(const std::complex<T>& x, const std::complex<T>& y)
- {
- // x * cos(y) + i * x * sin(y) -- arguments are supposed to be REAL numbers
- return fp_polar<T,true> (x.real(), y.real());
- //return std::polar(x.real(), y.real());
- //return x * (fp_cos(y) + (std::complex<T>(0,1) * fp_sin(y));
- }
-
- // These provide fallbacks in case there's no library function
- template<typename T>
- inline std::complex<T> fp_floor(const std::complex<T>& x)
- {
- return std::complex<T> (fp_floor(x.real()), fp_floor(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_trunc(const std::complex<T>& x)
- {
- return std::complex<T> (fp_trunc(x.real()), fp_trunc(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_int(const std::complex<T>& x)
- {
- return std::complex<T> (fp_int(x.real()), fp_int(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_ceil(const std::complex<T>& x)
- {
- return std::complex<T> (fp_ceil(x.real()), fp_ceil(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_abs(const std::complex<T>& x)
- {
- return std::abs(x);
- //T extent = fp_max(fp_abs(x.real()), fp_abs(x.imag()));
- //if(extent == T()) return x;
- //return extent * fp_hypot(x.real() / extent, x.imag() / extent);
- }
- template<typename T>
- inline std::complex<T> fp_exp(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::exp(x);
- return fp_polar<T,true>(fp_exp(x.real()), x.imag());
- }
- template<typename T>
- inline std::complex<T> fp_log(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::log(x);
- // log(abs(x)) + i*arg(x)
- // log(Xr^2+Xi^2)*0.5 + i*arg(x)
- if(x.imag()==T())
- return std::complex<T>( fp_log(fp_abs(x.real())),
- fp_arg(x.real()) ); // Note: Uses real-value fp_arg() here!
- return std::complex<T>(
- fp_log(std::norm(x)) * T(0.5),
- fp_arg(x).real() );
- }
- template<typename T>
- inline std::complex<T> fp_sqrt(const std::complex<T>& x)
- {
- if(FP_ProbablyHasFastLibcComplex<T>::result)
- return std::sqrt(x);
- return fp_polar<T,true> (fp_sqrt(fp_abs(x).real()),
- T(0.5)*fp_arg(x).real());
- }
- template<typename T>
- inline std::complex<T> fp_acos(const std::complex<T>& x)
- {
- // -i * log(x + i * sqrt(1 - x^2))
- const std::complex<T> i (T(), T(1));
- return -i * fp_log(x + i * fp_sqrt(T(1) - x*x));
- // Note: Real version of acos() cannot handle |x| > 1,
- // because it would cause sqrt(negative value).
- }
- template<typename T>
- inline std::complex<T> fp_asin(const std::complex<T>& x)
- {
- // -i * log(i*x + sqrt(1 - x^2))
- const std::complex<T> i (T(), T(1));
- return -i * fp_log(i*x + fp_sqrt(T(1) - x*x));
- // Note: Real version of asin() cannot handle |x| > 1,
- // because it would cause sqrt(negative value).
- }
- template<typename T>
- inline std::complex<T> fp_atan(const std::complex<T>& x)
- {
- // 0.5i * (log(1-i*x) - log(1+i*x))
- // -0.5i * log( (1+i*x) / (1-i*x) )
- const std::complex<T> i (T(), T(1));
- return (T(-0.5)*i) * fp_log( (T(1)+i*x) / (T(1)-i*x) );
- // Note: x = -1i causes division by zero
- // x = +1i causes log(0)
- // Thus, x must not be +-1i
- }
- template<typename T>
- inline std::complex<T> fp_cos(const std::complex<T>& x)
- {
- return std::cos(x);
- // // (exp(i*x) + exp(-i*x)) / (2)
- // //const std::complex<T> i (T(), T(1));
- // //return (fp_exp(i*x) + fp_exp(-i*x)) * T(0.5);
- // // Also: cos(Xr)*cosh(Xi) - i*sin(Xr)*sinh(Xi)
- // return std::complex<T> (
- // fp_cos(x.real())*fp_cosh(x.imag()),
- // -fp_sin(x.real())*fp_sinh(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_sin(const std::complex<T>& x)
- {
- return std::sin(x);
- // // (exp(i*x) - exp(-i*x)) / (2i)
- // //const std::complex<T> i (T(), T(1));
- // //return (fp_exp(i*x) - fp_exp(-i*x)) * (T(-0.5)*i);
- // // Also: sin(Xr)*cosh(Xi) + cos(Xr)*sinh(Xi)
- // return std::complex<T> (
- // fp_sin(x.real())*fp_cosh(x.imag()),
- // fp_cos(x.real())*fp_sinh(x.imag()));
- }
- template<typename T>
- inline void fp_sinCos(
- std::complex<T>& sinvalue,
- std::complex<T>& cosvalue,
- const std::complex<T>& x)
- {
- //const std::complex<T> i (T(), T(1)), expix(fp_exp(i*x)), expmix(fp_exp((-i)*x));
- //cosvalue = (expix + expmix) * T(0.5);
- //sinvalue = (expix - expmix) * (i*T(-0.5));
- // The above expands to the following:
- T srx, crx; fp_sinCos(srx, crx, x.real());
- T six, cix; fp_sinhCosh(six, cix, x.imag());
- sinvalue = std::complex<T>(srx*cix, crx*six);
- cosvalue = std::complex<T>(crx*cix, -srx*six);
- }
- template<typename T>
- inline void fp_sinhCosh(
- std::complex<T>& sinhvalue,
- std::complex<T>& coshvalue,
- const std::complex<T>& x)
- {
- T srx, crx; fp_sinhCosh(srx, crx, x.real());
- T six, cix; fp_sinCos(six, cix, x.imag());
- sinhvalue = std::complex<T>(srx*cix, crx*six);
- coshvalue = std::complex<T>(crx*cix, srx*six);
- }
- template<typename T>
- inline std::complex<T> fp_tan(const std::complex<T>& x)
- {
- return std::tan(x);
- //std::complex<T> si, co;
- //fp_sinCos(si, co, x);
- //return si/co;
- // // (i-i*exp(2i*x)) / (exp(2i*x)+1)
- // const std::complex<T> i (T(), T(1)), exp2ix=fp_exp((2*i)*x);
- // return (i-i*exp2ix) / (exp2ix+T(1));
- // // Also: sin(x)/cos(y)
- // // return fp_sin(x)/fp_cos(x);
- }
- template<typename T>
- inline std::complex<T> fp_cosh(const std::complex<T>& x)
- {
- return std::cosh(x);
- // // (exp(x) + exp(-x)) * 0.5
- // // Also: cosh(Xr)*cos(Xi) + i*sinh(Xr)*sin(Xi)
- // return std::complex<T> (
- // fp_cosh(x.real())*fp_cos(x.imag()),
- // fp_sinh(x.real())*fp_sin(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_sinh(const std::complex<T>& x)
- {
- return std::sinh(x);
- // // (exp(x) - exp(-x)) * 0.5
- // // Also: sinh(Xr)*cos(Xi) + i*cosh(Xr)*sin(Xi)
- // return std::complex<T> (
- // fp_sinh(x.real())*fp_cos(x.imag()),
- // fp_cosh(x.real())*fp_sin(x.imag()));
- }
- template<typename T>
- inline std::complex<T> fp_tanh(const std::complex<T>& x)
- {
- return std::tanh(x);
- //std::complex<T> si, co;
- //fp_sinhCosh(si, co, x);
- //return si/co;
- // // (exp(2*x)-1) / (exp(2*x)+1)
- // // Also: sinh(x)/tanh(x)
- // const std::complex<T> exp2x=fp_exp(x+x);
- // return (exp2x-T(1)) / (exp2x+T(1));
- }
-
-#ifdef FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
- template<typename T>
- inline std::complex<T> fp_acosh(const std::complex<T>& x)
- { return fp_log(x + fp_sqrt(x*x - std::complex<T>(1))); }
- template<typename T>
- inline std::complex<T> fp_asinh(const std::complex<T>& x)
- { return fp_log(x + fp_sqrt(x*x + std::complex<T>(1))); }
- template<typename T>
- inline std::complex<T> fp_atanh(const std::complex<T>& x)
- { return fp_log( (std::complex<T>(1)+x) / (std::complex<T>(1)-x))
- * std::complex<T>(0.5); }
-#endif
- template<typename T>
- inline std::complex<T> fp_pow(const std::complex<T>& x, const std::complex<T>& y)
- {
- // return std::pow(x,y);
-
- // With complex numbers, pow(x,y) can be solved with
- // the general formula: exp(y*log(x)). It handles
- // all special cases gracefully.
- // It expands to the following:
- // A)
- // t1 = log(x)
- // t2 = y * t1
- // res = exp(t2)
- // B)
- // t1.r = log(x.r * x.r + x.i * x.i) * 0.5 \ fp_log()
- // t1.i = atan2(x.i, x.r) /
- // t2.r = y.r*t1.r - y.i*t1.i \ multiplication
- // t2.i = y.r*t1.i + y.i*t1.r /
- // rho = exp(t2.r) \ fp_exp()
- // theta = t2.i /
- // res.r = rho * cos(theta) \ fp_polar(), called from
- // res.i = rho * sin(theta) / fp_exp(). Uses sincos().
- // Aside from the common "norm" calculation in atan2()
- // and in the log parameter, both of which are part of fp_log(),
- // there does not seem to be any incentive to break this
- // function down further; it would not help optimizing it.
- // However, we do handle the following special cases:
- //
- // When x is real (positive or negative):
- // t1.r = log(abs(x.r))
- // t1.i = x.r<0 ? -pi : 0
- // When y is real:
- // t2.r = y.r * t1.r
- // t2.i = y.r * t1.i
- const std::complex<T> t =
- (x.imag() != T())
- ? fp_log(x)
- : std::complex<T> (fp_log(fp_abs(x.real())),
- fp_arg(x.real())); // Note: Uses real-value fp_arg() here!
- return y.imag() != T()
- ? fp_exp(y * t)
- : fp_polar<T,true> (fp_exp(y.real()*t.real()), y.real()*t.imag());
- }
- template<typename T>
- inline std::complex<T> fp_cbrt(const std::complex<T>& x)
- {
- // For real numbers, prefer giving a real solution
- // rather than a complex solution.
- // For example, cbrt(-3) has the following three solutions:
- // A) 0.7211247966535 + 1.2490247864016i
- // B) 0.7211247966535 - 1.2490247864016i
- // C) -1.442249593307
- // exp(log(x)/3) gives A, but we prefer to give C.
- if(x.imag() == T()) return fp_cbrt(x.real());
- const std::complex<T> t(fp_log(x));
- return fp_polar<T,true> (fp_exp(t.real() / T(3)), t.imag() / T(3));
- }
-
- template<typename T>
- inline std::complex<T> fp_exp2(const std::complex<T>& x)
- {
- // pow(2, x)
- // polar(2^Xr, Xi*log(2))
- return fp_polar<T,true> (fp_exp2(x.real()), x.imag()*fp_const_log2<T>());
- }
- template<typename T>
- inline std::complex<T> fp_mod(const std::complex<T>& x, const std::complex<T>& y)
- {
- // Modulo function is probably not defined for complex numbers.
- // But we do our best to calculate it the same way as it is done
- // with real numbers, so that at least it is in some way "consistent".
- if(y.imag() == 0) return fp_mod(x.real(), y.real()); // optimization
- std::complex<T> n = fp_trunc(x / y);
- return x - n * y;
- }
-
- /* libstdc++ already defines a streaming operator for complex values,
- * but we redefine our own that it is compatible with the input
- * accepted by fparser. I.e. instead of (5,3) we now get (5+3i),
- * and instead of (-4,0) we now get -4.
- */
- template<typename T>
- inline std::ostream& operator<<(std::ostream& os, const std::complex<T>& value)
- {
- if(value.imag() == T()) return os << value.real();
- if(value.real() == T()) return os << value.imag() << 'i';
- if(value.imag() < T())
- return os << '(' << value.real() << "-" << -value.imag() << "i)";
- else
- return os << '(' << value.real() << "+" << value.imag() << "i)";
- }
-
- /* Less-than or greater-than operators are not technically defined
- * for Complex types. However, in fparser and its tool set, these
- * operators are widely required to be present.
- * Our implementation here is based on converting the complex number
- * into a scalar and the doing a scalar comparison on the value.
- * The means by which the number is changed into a scalar is based
- * on the following principles:
- * - Does not introduce unjustified amounts of extra inaccuracy
- * - Is transparent to purely real values
- * (this disqualifies something like x.real() + x.imag())
- * - Does not ignore the imaginary value completely
- * (this may be relevant especially in testbed)
- * - Is not so complicated that it would slow down a great deal
- *
- * Basically our formula here is the same as std::abs(),
- * except that it keeps the sign of the original real number,
- * and it does not do a sqrt() calculation that is not really
- * needed because we are only interested in the relative magnitudes.
- *
- * Equality and nonequality operators must not need to be overloaded.
- * They are already implemented in standard, and we must
- * not introduce flawed equality assumptions.
- */
- template<typename T>
- inline T fp_complexScalarize(const std::complex<T>& x)
- {
- T res(std::norm(x));
- if(x.real() < T()) res = -res;
- return res;
- }
- template<typename T>
- inline T fp_realComplexScalarize(const T& x)
- {
- T res(x*x);
- if(x < T()) res = -res;
- return res;
- }
- // { return x.real() * (T(1.0) + fp_abs(x.imag())); }
- #define d(op) \
- template<typename T> \
- inline bool operator op (const std::complex<T>& x, T y) \
- { return fp_complexScalarize(x) op fp_realComplexScalarize(y); } \
- template<typename T> \
- inline bool operator op (const std::complex<T>& x, const std::complex<T>& y) \
- { return fp_complexScalarize(x) op \
- fp_complexScalarize(y); } \
- template<typename T> \
- inline bool operator op (T x, const std::complex<T>& y) \
- { return fp_realComplexScalarize(x) op fp_complexScalarize(y); }
- d( < ) d( <= ) d( > ) d( >= )
- #undef d
-#endif
-
- template<typename Value_t>
- inline Value_t fp_real(const Value_t& x) { return x; }
- template<typename Value_t>
- inline Value_t fp_imag(const Value_t& ) { return Value_t(); }
- template<typename Value_t>
- inline Value_t fp_arg(const Value_t& x)
- { return x < Value_t() ? -fp_const_pi<Value_t>() : Value_t(); }
- template<typename Value_t>
- inline Value_t fp_conj(const Value_t& x) { return x; }
- template<typename Value_t>
- inline Value_t fp_polar(const Value_t& x, const Value_t& y)
- { return x * fp_cos(y); } // This is of course a meaningless function.
-
- template<typename Value_t>
- inline std::complex<Value_t> fp_atan2(const std::complex<Value_t>& y,
- const std::complex<Value_t>& x)
- {
- if(y == Value_t()) return fp_arg(x);
- if(x == Value_t()) return fp_const_pi<Value_t>() * Value_t(-0.5);
- // 2*atan(y / (sqrt(x^2+y^2) + x) )
- // 2*atan( (sqrt(x^2+y^2) - x) / y)
- std::complex<Value_t> res( fp_atan(y / (fp_hypot(x,y) + x)) );
- return res+res;
- }
-
-// -------------------------------------------------------------------------
-// Comparison
-// -------------------------------------------------------------------------
- template<typename Value_t>
- inline bool fp_equal(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x == y)
- : (fp_abs(x - y) <= Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_nequal(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x != y)
- : (fp_abs(x - y) > Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_less(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x < y)
- : (x < y - Epsilon<Value_t>::value); }
-
- template<typename Value_t>
- inline bool fp_lessOrEq(const Value_t& x, const Value_t& y)
- { return IsIntType<Value_t>::result
- ? (x <= y)
- : (x <= y + Epsilon<Value_t>::value); }
-
-
- template<typename Value_t>
- inline bool fp_greater(const Value_t& x, const Value_t& y)
- { return fp_less(y, x); }
-
- template<typename Value_t>
- inline bool fp_greaterOrEq(const Value_t& x, const Value_t& y)
- { return fp_lessOrEq(y, x); }
-
- template<typename Value_t>
- inline bool fp_truth(const Value_t& d)
- {
- return IsIntType<Value_t>::result
- ? d != Value_t()
- : fp_abs(d) >= Value_t(0.5);
- }
-
- template<typename Value_t>
- inline bool fp_absTruth(const Value_t& abs_d)
- {
- return IsIntType<Value_t>::result
- ? abs_d > Value_t()
- : abs_d >= Value_t(0.5);
- }
-
- template<typename Value_t>
- inline const Value_t& fp_min(const Value_t& d1, const Value_t& d2)
- { return d1<d2 ? d1 : d2; }
-
- template<typename Value_t>
- inline const Value_t& fp_max(const Value_t& d1, const Value_t& d2)
- { return d1>d2 ? d1 : d2; }
-
- template<typename Value_t>
- inline const Value_t fp_not(const Value_t& b)
- { return Value_t(!fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_notNot(const Value_t& b)
- { return Value_t(fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absNot(const Value_t& b)
- { return Value_t(!fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absNotNot(const Value_t& b)
- { return Value_t(fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_and(const Value_t& a, const Value_t& b)
- { return Value_t(fp_truth(a) && fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_or(const Value_t& a, const Value_t& b)
- { return Value_t(fp_truth(a) || fp_truth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absAnd(const Value_t& a, const Value_t& b)
- { return Value_t(fp_absTruth(a) && fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_absOr(const Value_t& a, const Value_t& b)
- { return Value_t(fp_absTruth(a) || fp_absTruth(b)); }
-
- template<typename Value_t>
- inline const Value_t fp_make_imag(const Value_t& ) // Imaginary 1. In real mode, always zero.
- {
- return Value_t();
- }
-
- /////////////
- /* Opcode analysis functions are used by fp_opcode_add.inc */
- /* Moved here from fparser.cc because fp_opcode_add.inc
- * is also now included by fpoptimizer.cc
- */
- bool IsLogicalOpcode(unsigned op);
- bool IsComparisonOpcode(unsigned op);
- unsigned OppositeComparisonOpcode(unsigned op);
- bool IsNeverNegativeValueOpcode(unsigned op);
- bool IsAlwaysIntegerOpcode(unsigned op);
- bool IsUnaryOpcode(unsigned op);
- bool IsBinaryOpcode(unsigned op);
- bool IsVarOpcode(unsigned op);
- bool IsCommutativeOrParamSwappableBinaryOpcode(unsigned op);
- unsigned GetParamSwappedBinaryOpcode(unsigned op);
-
- template<bool ComplexType>
- bool HasInvalidRangesOpcode(unsigned op);
-
- template<typename Value_t>
- inline Value_t DegreesToRadians(const Value_t& degrees)
- {
- return degrees * fp_const_deg_to_rad<Value_t>();
- }
-
- template<typename Value_t>
- inline Value_t RadiansToDegrees(const Value_t& radians)
- {
- return radians * fp_const_rad_to_deg<Value_t>();
- }
-
- template<typename Value_t>
- inline long makeLongInteger(const Value_t& value)
- {
- return (long) fp_int(value);
- }
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- inline long makeLongInteger(const std::complex<T>& value)
- {
- return (long) fp_int( std::abs(value) );
- }
-#endif
-
- // Is value an integer that fits in "long" datatype?
- template<typename Value_t>
- inline bool isLongInteger(const Value_t& value)
- {
- return value == Value_t( makeLongInteger(value) );
- }
-
- template<typename Value_t>
- inline bool isOddInteger(const Value_t& value)
- {
- const Value_t halfValue = (value + Value_t(1)) * Value_t(0.5);
- return fp_equal(halfValue, fp_floor(halfValue));
- }
-
- template<typename Value_t>
- inline bool isEvenInteger(const Value_t& value)
- {
- const Value_t halfValue = value * Value_t(0.5);
- return fp_equal(halfValue, fp_floor(halfValue));
- }
-
- template<typename Value_t>
- inline bool isInteger(const Value_t& value)
- {
- return fp_equal(value, fp_floor(value));
- }
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline bool isEvenInteger(const long& value)
- {
- return value%2 == 0;
- }
-
- template<>
- inline bool isInteger(const long&) { return true; }
-
- template<>
- inline bool isLongInteger(const long&) { return true; }
-
- template<>
- inline long makeLongInteger(const long& value)
- {
- return value;
- }
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline bool isInteger(const MpfrFloat& value) { return value.isInteger(); }
-
- template<>
- inline bool isEvenInteger(const MpfrFloat& value)
- {
- return isInteger(value) && value%2 == 0;
- }
-
- template<>
- inline long makeLongInteger(const MpfrFloat& value)
- {
- return (long) value.toInt();
- }
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- inline bool isEvenInteger(const GmpInt& value)
- {
- return value%2 == 0;
- }
-
- template<>
- inline bool isInteger(const GmpInt&) { return true; }
-
- template<>
- inline long makeLongInteger(const GmpInt& value)
- {
- return (long) value.toInt();
- }
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline bool isOddInteger(const long& value)
- {
- return value%2 != 0;
- }
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
- template<>
- inline bool isOddInteger(const MpfrFloat& value)
- {
- return value.isInteger() && value%2 != 0;
- }
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<>
- inline bool isOddInteger(const GmpInt& value)
- {
- return value%2 != 0;
- }
-#endif
-
-
-// -------------------------------------------------------------------------
-// fp_pow
-// -------------------------------------------------------------------------
- // Commented versions in fparser.cc
- template<typename Value_t>
- inline Value_t fp_pow_with_exp_log(const Value_t& x, const Value_t& y)
- {
- return fp_exp(fp_log(x) * y);
- }
-
- template<typename Value_t>
- inline Value_t fp_powi(Value_t x, unsigned long y)
- {
- Value_t result(1);
- while(y != 0)
- {
- if(y & 1) { result *= x; y -= 1; }
- else { x *= x; y /= 2; }
- }
- return result;
- }
-
- template<typename Value_t>
- Value_t fp_pow(const Value_t& x, const Value_t& y)
- {
- if(x == Value_t(1)) return Value_t(1);
- if(isLongInteger(y))
- {
- if(y >= Value_t(0))
- return fp_powi(x, makeLongInteger(y));
- else
- return Value_t(1) / fp_powi(x, -makeLongInteger(y));
- }
- if(y >= Value_t(0))
- {
- if(x > Value_t(0)) return fp_pow_with_exp_log(x, y);
- if(x == Value_t(0)) return Value_t(0);
- if(!isInteger(y*Value_t(16)))
- return -fp_pow_with_exp_log(-x, y);
- }
- else
- {
- if(x > Value_t(0)) return fp_pow_with_exp_log(Value_t(1) / x, -y);
- if(x < Value_t(0))
- {
- if(!isInteger(y*Value_t(-16)))
- return -fp_pow_with_exp_log(Value_t(-1) / x, -y);
- }
- }
- return fp_pow_base(x, y);
- }
-
- template<typename Value_t>
- inline Value_t fp_exp2(const Value_t& x)
- {
- return fp_pow(Value_t(2), x);
- }
-} // namespace FUNCTIONPARSERTYPES
-
-#endif // ONCE_FPARSER_H_
-#endif // ONCE_FPARSER_AUX_H_
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// NOTE:
-// This file contains only internal types for the function parser library.
-// You don't need to include this file in your code. Include "fparser.hh"
-// only.
-
-#ifndef ONCE_FPARSER_TYPES_H_
-#define ONCE_FPARSER_TYPES_H_
-
-#include "../fpconfig.hh"
-#include <cstring>
-
-#ifdef ONCE_FPARSER_H_
-#include <map>
-#endif
-
-namespace FUNCTIONPARSERTYPES
-{
- enum OPCODE
- {
-// The order of opcodes in the function list must
-// match that which is in the Functions[] array.
- cAbs,
- cAcos, cAcosh,
- cArg, /* get the phase angle of a complex value */
- cAsin, cAsinh,
- cAtan, cAtan2, cAtanh,
- cCbrt, cCeil,
- cConj, /* get the complex conjugate of a complex value */
- cCos, cCosh, cCot, cCsc,
- cExp, cExp2, cFloor, cHypot,
- cIf,
- cImag, /* get imaginary part of a complex value */
- cInt, cLog, cLog10, cLog2, cMax, cMin,
- cPolar, /* create a complex number from polar coordinates */
- cPow,
- cReal, /* get real part of a complex value */
- cSec, cSin, cSinh, cSqrt, cTan, cTanh,
- cTrunc,
-
-// These do not need any ordering:
-// Except that if you change the order of {eq,neq,lt,le,gt,ge}, you
-// must also change the order in ConstantFolding_ComparisonOperations().
- cImmed, cJump,
- cNeg, cAdd, cSub, cMul, cDiv, cMod,
- cEqual, cNEqual, cLess, cLessOrEq, cGreater, cGreaterOrEq,
- cNot, cAnd, cOr,
- cNotNot, /* Protects the double-not sequence from optimizations */
-
- cDeg, cRad, /* Multiplication and division by 180 / pi */
-
- cFCall, cPCall,
-
-#ifdef FP_SUPPORT_OPTIMIZER
- cPopNMov, /* cPopNMov(x,y) moves [y] to [x] and deletes anything
- * above [x]. Used for disposing of temporaries.
- */
- cLog2by, /* log2by(x,y) = log2(x) * y */
- cNop, /* Used by fpoptimizer internally; should not occur in bytecode */
-#endif
- cSinCos, /* sin(x) followed by cos(x) (two values are pushed to stack) */
- cSinhCosh, /* hyperbolic equivalent of sincos */
- cAbsAnd, /* As cAnd, but assume both operands are absolute values */
- cAbsOr, /* As cOr, but assume both operands are absolute values */
- cAbsNot, /* As cAbsNot, but assume the operand is an absolute value */
- cAbsNotNot, /* As cAbsNotNot, but assume the operand is an absolute value */
- cAbsIf, /* As cAbsIf, but assume the 1st operand is an absolute value */
-
- cDup, /* Duplicates the last value in the stack: Push [Stacktop] */
- cFetch, /* Same as Dup, except with absolute index
- * (next value is index) */
- cInv, /* Inverts the last value in the stack (x = 1/x) */
- cSqr, /* squares the last operand in the stack, no push/pop */
- cRDiv, /* reverse division (not x/y, but y/x) */
- cRSub, /* reverse subtraction (not x-y, but y-x) */
- cRSqrt, /* inverse square-root (1/sqrt(x)) */
-
- VarBegin
- };
-
-#ifdef ONCE_FPARSER_H_
- struct FuncDefinition
- {
- enum FunctionFlags
- {
- Enabled = 0x01,
- AngleIn = 0x02,
- AngleOut = 0x04,
- OkForInt = 0x08,
- ComplexOnly = 0x10
- };
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
- const char name[8];
-#else
- struct name { } name;
-#endif
- unsigned params : 8;
- unsigned flags : 8;
-
- inline bool okForInt() const { return (flags & OkForInt) != 0; }
- inline bool complexOnly() const { return (flags & ComplexOnly) != 0; }
- };
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-# define FP_FNAME(n) n
-#else
-# define FP_FNAME(n) {}
-#endif
-// This list must be in the same order as that in OPCODE enum,
-// because the opcode value is used to index this array, and
-// the pointer to array element is used for generating the opcode.
- const FuncDefinition Functions[]=
- {
- /*cAbs */ { FP_FNAME("abs"), 1, FuncDefinition::OkForInt },
- /*cAcos */ { FP_FNAME("acos"), 1, FuncDefinition::AngleOut },
- /*cAcosh*/ { FP_FNAME("acosh"), 1, FuncDefinition::AngleOut },
- /*cArg */ { FP_FNAME("arg"), 1, FuncDefinition::AngleOut | FuncDefinition::ComplexOnly },
- /*cAsin */ { FP_FNAME("asin"), 1, FuncDefinition::AngleOut },
- /*cAsinh*/ { FP_FNAME("asinh"), 1, FuncDefinition::AngleOut },
- /*cAtan */ { FP_FNAME("atan"), 1, FuncDefinition::AngleOut },
- /*cAtan2*/ { FP_FNAME("atan2"), 2, FuncDefinition::AngleOut },
- /*cAtanh*/ { FP_FNAME("atanh"), 1, 0 },
- /*cCbrt */ { FP_FNAME("cbrt"), 1, 0 },
- /*cCeil */ { FP_FNAME("ceil"), 1, 0 },
- /*cConj */ { FP_FNAME("conj"), 1, FuncDefinition::ComplexOnly },
- /*cCos */ { FP_FNAME("cos"), 1, FuncDefinition::AngleIn },
- /*cCosh */ { FP_FNAME("cosh"), 1, FuncDefinition::AngleIn },
- /*cCot */ { FP_FNAME("cot"), 1, FuncDefinition::AngleIn },
- /*cCsc */ { FP_FNAME("csc"), 1, FuncDefinition::AngleIn },
- /*cExp */ { FP_FNAME("exp"), 1, 0 },
- /*cExp2 */ { FP_FNAME("exp2"), 1, 0 },
- /*cFloor*/ { FP_FNAME("floor"), 1, 0 },
- /*cHypot*/ { FP_FNAME("hypot"), 2, 0 },
- /*cIf */ { FP_FNAME("if"), 0, FuncDefinition::OkForInt },
- /*cImag */ { FP_FNAME("imag"), 1, FuncDefinition::ComplexOnly },
- /*cInt */ { FP_FNAME("int"), 1, 0 },
- /*cLog */ { FP_FNAME("log"), 1, 0 },
- /*cLog10*/ { FP_FNAME("log10"), 1, 0 },
- /*cLog2 */ { FP_FNAME("log2"), 1, 0 },
- /*cMax */ { FP_FNAME("max"), 2, FuncDefinition::OkForInt },
- /*cMin */ { FP_FNAME("min"), 2, FuncDefinition::OkForInt },
- /*cPolar */{ FP_FNAME("polar"), 2, FuncDefinition::ComplexOnly | FuncDefinition::AngleIn },
- /*cPow */ { FP_FNAME("pow"), 2, 0 },
- /*cReal */ { FP_FNAME("real"), 1, FuncDefinition::ComplexOnly },
- /*cSec */ { FP_FNAME("sec"), 1, FuncDefinition::AngleIn },
- /*cSin */ { FP_FNAME("sin"), 1, FuncDefinition::AngleIn },
- /*cSinh */ { FP_FNAME("sinh"), 1, FuncDefinition::AngleIn },
- /*cSqrt */ { FP_FNAME("sqrt"), 1, 0 },
- /*cTan */ { FP_FNAME("tan"), 1, FuncDefinition::AngleIn },
- /*cTanh */ { FP_FNAME("tanh"), 1, FuncDefinition::AngleIn },
- /*cTrunc*/ { FP_FNAME("trunc"), 1, 0 }
- };
-#undef FP_FNAME
-
- struct NamePtr
- {
- const char* name;
- unsigned nameLength;
-
- NamePtr(const char* n, unsigned l): name(n), nameLength(l) {}
-
- inline bool operator==(const NamePtr& rhs) const
- {
- return nameLength == rhs.nameLength
- && std::memcmp(name, rhs.name, nameLength) == 0;
- }
- inline bool operator<(const NamePtr& rhs) const
- {
- for(unsigned i = 0; i < nameLength; ++i)
- {
- if(i == rhs.nameLength) return false;
- const char c1 = name[i], c2 = rhs.name[i];
- if(c1 < c2) return true;
- if(c2 < c1) return false;
- }
- return nameLength < rhs.nameLength;
- }
- };
-
- template<typename Value_t>
- struct NameData
- {
- enum DataType { CONSTANT, UNIT, FUNC_PTR, PARSER_PTR, VARIABLE };
- DataType type;
- unsigned index;
- Value_t value;
-
- NameData(DataType t, unsigned v) : type(t), index(v), value() { }
- NameData(DataType t, Value_t v) : type(t), index(), value(v) { }
- NameData() { }
- };
-
- template<typename Value_t>
- class NamePtrsMap: public
- std::map<FUNCTIONPARSERTYPES::NamePtr,
- FUNCTIONPARSERTYPES::NameData<Value_t> >
- {
- };
-
- const unsigned FUNC_AMOUNT = sizeof(Functions)/sizeof(Functions[0]);
-#endif // ONCE_FPARSER_H_
-}
-
-#ifdef ONCE_FPARSER_H_
-#include <vector>
-
-template<typename Value_t>
-struct FunctionParserBase<Value_t>::Data
-{
- unsigned mReferenceCounter;
-
- char mDelimiterChar;
- ParseErrorType mParseErrorType;
- int mEvalErrorType;
- bool mUseDegreeConversion;
- bool mHasByteCodeFlags;
- const char* mErrorLocation;
-
- unsigned mVariablesAmount;
- std::string mVariablesString;
- FUNCTIONPARSERTYPES::NamePtrsMap<Value_t> mNamePtrs;
-
- struct InlineVariable
- {
- FUNCTIONPARSERTYPES::NamePtr mName;
- unsigned mFetchIndex;
- };
-
- typedef std::vector<InlineVariable> InlineVarNamesContainer;
- InlineVarNamesContainer mInlineVarNames;
-
- struct FuncWrapperPtrData
- {
- /* Only one of the pointers will point to a function, the other
- will be null. (The raw function pointer could be implemented
- as a FunctionWrapper specialization, but it's done like this
- for efficiency.) */
- FunctionPtr mRawFuncPtr;
- FunctionWrapper* mFuncWrapperPtr;
- unsigned mParams;
-
- FuncWrapperPtrData();
- ~FuncWrapperPtrData();
- FuncWrapperPtrData(const FuncWrapperPtrData&);
- FuncWrapperPtrData& operator=(const FuncWrapperPtrData&);
- };
-
- struct FuncParserPtrData
- {
- FunctionParserBase<Value_t>* mParserPtr;
- unsigned mParams;
- };
-
- std::vector<FuncWrapperPtrData> mFuncPtrs;
- std::vector<FuncParserPtrData> mFuncParsers;
-
- std::vector<unsigned> mByteCode;
- std::vector<Value_t> mImmed;
-
-#if !defined(FP_USE_THREAD_SAFE_EVAL) && \
- !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
- std::vector<Value_t> mStack;
- // Note: When mStack exists,
- // mStack.size() and mStackSize are mutually redundant.
-#endif
-
- unsigned mStackSize;
-
- Data();
- Data(const Data&);
- Data& operator=(const Data&); // not implemented on purpose
- ~Data();
-};
-#endif
-
-//#include "fpaux.hh"
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-#include "fpconfig.hh"
-#include "fparser.hh"
-
-#include <set>
-#include <cstdlib>
-#include <cstring>
-#include <cctype>
-#include <cmath>
-#include <cassert>
-#include <limits>
-
-#include "extrasrc/fptypes.hh"
-#include "extrasrc/fpaux.hh"
-using namespace FUNCTIONPARSERTYPES;
-
-#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
-#ifndef FP_USE_THREAD_SAFE_EVAL
-#define FP_USE_THREAD_SAFE_EVAL
-#endif
-#endif
-
-#ifdef __GNUC__
-# define likely(x) __builtin_expect(!!(x), 1)
-# define unlikely(x) __builtin_expect(!!(x), 0)
-#else
-# define likely(x) (x)
-# define unlikely(x) (x)
-#endif
-
-//=========================================================================
-// Opcode analysis functions
-//=========================================================================
-// These functions are used by the Parse() bytecode optimizer (mostly from
-// code in fp_opcode_add.inc).
-
-bool FUNCTIONPARSERTYPES::IsLogicalOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsComparisonOpcode(unsigned op)
-{
- switch(op)
- {
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- return true;
- default: break;
- }
- return false;
-}
-
-unsigned FUNCTIONPARSERTYPES::OppositeComparisonOpcode(unsigned op)
-{
- switch(op)
- {
- case cLess: return cGreater;
- case cGreater: return cLess;
- case cLessOrEq: return cGreaterOrEq;
- case cGreaterOrEq: return cLessOrEq;
- }
- return op;
-}
-
-bool FUNCTIONPARSERTYPES::IsNeverNegativeValueOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- case cSqrt: case cRSqrt: case cSqr:
- case cHypot:
- case cAbs:
- case cAcos: case cCosh:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsAlwaysIntegerOpcode(unsigned op)
-{
- switch(op)
- {
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cEqual: case cNEqual:
- case cLess: case cLessOrEq:
- case cGreater: case cGreaterOrEq:
- case cInt: case cFloor: case cCeil: case cTrunc:
- return true;
- default: break;
- }
- return false;
-}
-
-bool FUNCTIONPARSERTYPES::IsUnaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cInv: case cNeg:
- case cNot: case cAbsNot:
- case cNotNot: case cAbsNotNot:
- case cSqr: case cRSqrt:
- case cDeg: case cRad:
- return true;
- }
- return (op < FUNC_AMOUNT && Functions[op].params == 1);
-}
-
-bool FUNCTIONPARSERTYPES::IsBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd: case cSub: case cRSub:
- case cMul: case cDiv: case cRDiv:
- case cMod:
- case cEqual: case cNEqual: case cLess:
- case cLessOrEq: case cGreater: case cGreaterOrEq:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- return true;
- }
- return (op < FUNC_AMOUNT && Functions[op].params == 2);
-}
-
-bool FUNCTIONPARSERTYPES::IsVarOpcode(unsigned op)
-{
- // See comment in declaration of FP_ParamGuardMask
- return int(op) >= VarBegin;
-}
-
-bool FUNCTIONPARSERTYPES::IsCommutativeOrParamSwappableBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd:
- case cMul:
- case cEqual: case cNEqual:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cMin: case cMax: case cHypot:
- return true;
- case cDiv: case cSub: case cRDiv: case cRSub:
- return true;
- case cLess: case cGreater:
- case cLessOrEq: case cGreaterOrEq: return true;
- }
- return false;
-}
-
-unsigned FUNCTIONPARSERTYPES::GetParamSwappedBinaryOpcode(unsigned op)
-{
- switch(op)
- {
- case cAdd:
- case cMul:
- case cEqual: case cNEqual:
- case cAnd: case cAbsAnd:
- case cOr: case cAbsOr:
- case cMin: case cMax: case cHypot:
- return op;
- case cDiv: return cRDiv;
- case cSub: return cRSub;
- case cRDiv: return cDiv;
- case cRSub: return cSub;
- case cLess: return cGreater;
- case cGreater: return cLess;
- case cLessOrEq: return cGreaterOrEq;
- case cGreaterOrEq: return cLessOrEq;
- }
- return op; // Error
-}
-
-template<bool ComplexType>
-bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode(unsigned op)
-{
- // Returns true, if the given opcode has a range of
- // input values that gives an error.
- if(ComplexType)
- {
- // COMPLEX:
- switch(op)
- {
- case cAtan: // allowed range: x != +-1i
- case cAtanh: // allowed range: x != +-1
- //case cCot: // allowed range: tan(x) != 0
- //case cCsc: // allowed range: sin(x) != 0
- case cLog: // allowed range: x != 0
- case cLog2: // allowed range: x != 0
- case cLog10: // allowed range: x != 0
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by:// allowed range: x != 0
- #endif
- //case cPow: // allowed when: x != 0 or y != 0
- //case cSec: // allowed range: cos(x) != 0
- //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
- //case cTanh: // allowed range: log(x) != -1 --> x != +-(pi/2)i
- case cRSqrt: // allowed range: x != 0
- //case cDiv: // allowed range: y != 0
- //case cRDiv: // allowed range: x != 0
- //case cInv: // allowed range: x != 0
- return true;
- }
- }
- else
- {
- // REAL:
- switch(op)
- {
- case cAcos: // allowed range: |x| <= 1
- case cAsin: // allowed range: |x| <= 1
- case cAcosh: // allowed range: x >= 1
- case cAtanh: // allowed range: |x| < 1
- //case cCot: // allowed range: tan(x) != 0
- //case cCsc: // allowed range: sin(x) != 0
- case cLog: // allowed range: x > 0
- case cLog2: // allowed range: x > 0
- case cLog10: // allowed range: x > 0
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by:// allowed range: x > 0
- #endif
- //case cPow: // allowed when: x > 0 or (x = 0 and y != 0) or (x<0)
- // Technically, when (x<0 and y is not integer),
- // it is not allowed, but we allow it anyway
- // in order to make nontrivial roots work.
- //case cSec: // allowed range: cos(x) != 0
- case cSqrt: // allowed range: x >= 0
- case cRSqrt: // allowed range: x > 0
- //case cTan: // allowed range: cos(x) != 0 --> x != +-(pi/2)
- //case cDiv: // allowed range: y != 0
- //case cRDiv: // allowed range: x != 0
- //case cInv: // allowed range: x != 0
- return true;
- }
- }
- return false;
-}
-
-template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<false>(unsigned op);
-template bool FUNCTIONPARSERTYPES::HasInvalidRangesOpcode<true>(unsigned op);
-
-
-#if(0) // Implementation moved to fpaux.hh due to linker problems
-//=========================================================================
-// Mathematical template functions
-//=========================================================================
-/* fp_pow() is a wrapper for std::pow()
- * that produces an identical value for
- * exp(1) ^ 2.0 (0x4000000000000000)
- * as exp(2.0) (0x4000000000000000)
- * - std::pow() on x86_64
- * produces 2.0 (0x3FFFFFFFFFFFFFFF) instead!
- * See comments below for other special traits.
- */
-namespace
-{
- template<typename ValueT>
- inline ValueT fp_pow_with_exp_log(const ValueT& x, const ValueT& y)
- {
- // Exponentiation using exp(log(x)*y).
- // See http://en.wikipedia.org/wiki/Exponentiation#Real_powers
- // Requirements: x > 0.
- return fp_exp(fp_log(x) * y);
- }
-
- template<typename ValueT>
- inline ValueT fp_powi(ValueT x, unsigned long y)
- {
- // Fast binary exponentiation algorithm
- // See http://en.wikipedia.org/wiki/Exponentiation_by_squaring
- // Requirements: y is non-negative integer.
- ValueT result(1);
- while(y != 0)
- {
- if(y & 1) { result *= x; y -= 1; }
- else { x *= x; y /= 2; }
- }
- return result;
- }
-}
-
-template<typename ValueT>
-ValueT FUNCTIONPARSERTYPES::fp_pow(const ValueT& x, const ValueT& y)
-{
- if(x == ValueT(1)) return ValueT(1);
- // y is now zero or positive
- if(isLongInteger(y))
- {
- // Use fast binary exponentiation algorithm
- if(y >= ValueT(0))
- return fp_powi(x, makeLongInteger(y));
- else
- return ValueT(1) / fp_powi(x, -makeLongInteger(y));
- }
- if(y >= ValueT(0))
- {
- // y is now positive. Calculate using exp(log(x)*y).
- if(x > ValueT(0)) return fp_pow_with_exp_log(x, y);
- if(x == ValueT(0)) return ValueT(0);
- // At this point, y > 0.0 and x is known to be < 0.0,
- // because positive and zero cases are already handled.
- if(!isInteger(y*ValueT(16)))
- return -fp_pow_with_exp_log(-x, y);
- // ^This is not technically correct, but it allows
- // functions such as cbrt(x^5), that is, x^(5/3),
- // to be evaluated when x is negative.
- // It is too complicated (and slow) to test whether y
- // is a formed from a ratio of an integer to an odd integer.
- // (And due to floating point inaccuracy, pointless too.)
- // For example, x^1.30769230769... is
- // actually x^(17/13), i.e. (x^17) ^ (1/13).
- // (-5)^(17/13) gives us now -8.204227562330453.
- // To see whether the result is right, we can test the given
- // root: (-8.204227562330453)^13 gives us the value of (-5)^17,
- // which proves that the expression was correct.
- //
- // The y*16 check prevents e.g. (-4)^(3/2) from being calculated,
- // as it would confuse functioninfo when pow() returns no error
- // but sqrt() does when the formula is converted into sqrt(x)*x.
- //
- // The errors in this approach are:
- // (-2)^sqrt(2) should produce NaN
- // or actually sqrt(2)I + 2^sqrt(2),
- // produces -(2^sqrt(2)) instead.
- // (Impact: Neglible)
- // Thus, at worst, we're changing a NaN (or complex)
- // result into a negative real number result.
- }
- else
- {
- // y is negative. Utilize the x^y = 1/(x^-y) identity.
- if(x > ValueT(0)) return fp_pow_with_exp_log(ValueT(1) / x, -y);
- if(x < ValueT(0))
- {
- if(!isInteger(y*ValueT(-16)))
- return -fp_pow_with_exp_log(ValueT(-1) / x, -y);
- // ^ See comment above.
- }
- // Remaining case: 0.0 ^ negative number
- }
- // This is reached when:
- // x=0, and y<0
- // x<0, and y*16 is either positive or negative integer
- // It is used for producing error values and as a safe fallback.
- return fp_pow_base(x, y);
-}
-#endif
-
-
-//=========================================================================
-// Elementary (atom) parsing functions
-//=========================================================================
-namespace
-{
- const unsigned FP_ParamGuardMask = 1U << (sizeof(unsigned) * 8u - 1u);
- // ^ This mask is used to prevent cFetch/other opcode's parameters
- // from being confused into opcodes or variable indices within the
- // bytecode optimizer. Because the way it is tested in bytecoderules.dat
- // for speed reasons, it must also be the sign-bit of the "int" datatype.
- // Perhaps an "assert(IsVarOpcode(X | FP_ParamGuardMask) == false)"
- // might be justified to put somewhere in the code, just in case?
-
-
- /* Reads an UTF8-encoded sequence which forms a valid identifier name from
- the given input string and returns its length. If bit 31 is set, the
- return value also contains the internal function opcode (defined in
- fptypes.hh) that matches the name.
- */
- unsigned readIdentifierCommon(const char* input)
- {
- /* Assuming unsigned = 32 bits:
- 76543210 76543210 76543210 76543210
- Return value if built-in function:
- 1PPPPPPP PPPPPPPP LLLLLLLL LLLLLLLL
- P = function opcode (15 bits)
- L = function name length (16 bits)
- Return value if not built-in function:
- 0LLLLLLL LLLLLLLL LLLLLLLL LLLLLLLL
- L = identifier length (31 bits)
- If unsigned has more than 32 bits, the other
- higher order bits are to be assumed zero.
- */
-#include "extrasrc/fp_identifier_parser.inc"
- return 0;
- }
-
- template<typename Value_t>
- inline unsigned readIdentifier(const char* input)
- {
- const unsigned value = readIdentifierCommon(input);
- if( (value & 0x80000000U) != 0) // Function?
- {
- // Verify that the function actually exists for this datatype
- if(IsIntType<Value_t>::result
- && !Functions[(value >> 16) & 0x7FFF].okForInt())
- {
- // If it does not exist, return it as an identifier instead
- return value & 0xFFFFu;
- }
- if(!IsComplexType<Value_t>::result
- && Functions[(value >> 16) & 0x7FFF].complexOnly())
- {
- // If it does not exist, return it as an identifier instead
- return value & 0xFFFFu;
- }
- }
- return value;
- }
-
- // Returns true if the entire string is a valid identifier
- template<typename Value_t>
- bool containsOnlyValidIdentifierChars(const std::string& name)
- {
- if(name.empty()) return false;
- return readIdentifier<Value_t>(name.c_str()) == (unsigned) name.size();
- }
-
-
- // -----------------------------------------------------------------------
- // Wrappers for strto... functions
- // -----------------------------------------------------------------------
- template<typename Value_t>
- inline Value_t fp_parseLiteral(const char* str, char** endptr)
- {
- return std::strtod(str, endptr);
- }
-
-#if defined(FP_USE_STRTOLD) || defined(FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS)
- template<>
- inline long double fp_parseLiteral<long double>(const char* str,
- char** endptr)
- {
- using namespace std; // Just in case strtold() is not inside std::
- return strtold(str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- inline long fp_parseLiteral<long>(const char* str, char** endptr)
- {
- return std::strtol(str, endptr, 10);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- template<typename T>
- inline std::complex<T> fp_parseComplexLiteral(const char* str,
- char** endptr)
- {
- T result = fp_parseLiteral<T> (str,endptr);
- const char* end = *endptr;
- if( (*end == 'i' || *end == 'I')
- && !std::isalnum(end[1]) )
- {
- ++*endptr;
- return std::complex<T> (T(), result);
- }
- return std::complex<T> (result, T());
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
- template<>
- inline std::complex<double> fp_parseLiteral<std::complex<double> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<double> (str,endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
- template<>
- inline std::complex<float> fp_parseLiteral<std::complex<float> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<float> (str,endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
- template<>
- inline std::complex<long double> fp_parseLiteral<std::complex<long double> >
- (const char* str, char** endptr)
- {
- return fp_parseComplexLiteral<long double> (str,endptr);
- }
-#endif
-
- // -----------------------------------------------------------------------
- // Hexadecimal floating point literal parsing
- // -----------------------------------------------------------------------
- inline int testXdigit(unsigned c)
- {
- if((c-'0') < 10u) return c&15; // 0..9
- if(((c|0x20)-'a') < 6u) return 9+(c&15); // A..F or a..f
- return -1; // Not a hex digit
- }
-
- template<typename elem_t, unsigned n_limbs, unsigned limb_bits>
- inline void addXdigit(elem_t* buffer, unsigned nibble)
- {
- for(unsigned p=0; p<n_limbs; ++p)
- {
- unsigned carry = unsigned( buffer[p] >> (elem_t)(limb_bits-4) );
- buffer[p] = (buffer[p] << 4) | nibble;
- nibble = carry;
- }
- }
-
- template<typename Value_t>
- Value_t parseHexLiteral(const char* str, char** endptr)
- {
- const unsigned bits_per_char = 8;
-
- const int MantissaBits =
- std::numeric_limits<Value_t>::radix == 2
- ? std::numeric_limits<Value_t>::digits
- : (((sizeof(Value_t) * bits_per_char) &~ 3) - 4);
-
- typedef unsigned long elem_t;
- const int ExtraMantissaBits = 4 + ((MantissaBits+3)&~3); // Store one digit more for correct rounding
- const unsigned limb_bits = sizeof(elem_t) * bits_per_char;
- const unsigned n_limbs = (ExtraMantissaBits + limb_bits-1) / limb_bits;
- elem_t mantissa_buffer[n_limbs] = { 0 };
-
- int n_mantissa_bits = 0; // Track the number of bits
- int exponent = 0; // The exponent that will be used to multiply the mantissa
- // Read integer portion
- while(true)
- {
- int xdigit = testXdigit(*str);
- if(xdigit < 0) break;
- addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
- ++str;
-
- n_mantissa_bits += 4;
- if(n_mantissa_bits >= ExtraMantissaBits)
- {
- // Exhausted the precision. Parse the rest (until exponent)
- // normally but ignore the actual digits.
- for(; testXdigit(*str) >= 0; ++str)
- exponent += 4;
- // Read but ignore decimals
- if(*str == '.')
- for(++str; testXdigit(*str) >= 0; ++str)
- {}
- goto read_exponent;
- }
- }
- // Read decimals
- if(*str == '.')
- for(++str; ; )
- {
- int xdigit = testXdigit(*str);
- if(xdigit < 0) break;
- addXdigit<elem_t,n_limbs,limb_bits> (mantissa_buffer, xdigit);
- ++str;
-
- exponent -= 4;
- n_mantissa_bits += 4;
- if(n_mantissa_bits >= ExtraMantissaBits)
- {
- // Exhausted the precision. Skip the rest
- // of the decimals, until the exponent.
- while(testXdigit(*str) >= 0)
- ++str;
- break;
- }
- }
-
- // Read exponent
- read_exponent:
- if(*str == 'p' || *str == 'P')
- {
- const char* str2 = str+1;
- long p_exponent = strtol(str2, const_cast<char**> (&str2), 10);
- if(str2 != str+1 && p_exponent == (long)(int)p_exponent)
- {
- exponent += (int)p_exponent;
- str = str2;
- }
- }
-
- if(endptr) *endptr = const_cast<char*> (str);
-
- Value_t result = std::ldexp(Value_t(mantissa_buffer[0]), exponent);
- for(unsigned p=1; p<n_limbs; ++p)
- {
- exponent += limb_bits;
- result += ldexp(Value_t(mantissa_buffer[p]), exponent);
- }
- return result;
- }
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<>
- long parseHexLiteral<long>(const char* str, char** endptr)
- {
- return std::strtol(str, endptr, 16);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
- template<>
- std::complex<double>
- parseHexLiteral<std::complex<double> >(const char* str, char** endptr)
- {
- return parseHexLiteral<double> (str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
- template<>
- std::complex<float>
- parseHexLiteral<std::complex<float> >(const char* str, char** endptr)
- {
- return parseHexLiteral<float> (str, endptr);
- }
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
- template<>
- std::complex<long double>
- parseHexLiteral<std::complex<long double> >(const char* str, char** endptr)
- {
- return parseHexLiteral<long double> (str, endptr);
- }
-#endif
-}
-
-//=========================================================================
-// Utility functions
-//=========================================================================
-namespace
-{
- // -----------------------------------------------------------------------
- // Add a new identifier to the specified identifier map
- // -----------------------------------------------------------------------
- // Return value will be false if the name already existed
- template<typename Value_t>
- bool addNewNameData(NamePtrsMap<Value_t>& namePtrs,
- std::pair<NamePtr, NameData<Value_t> >& newName,
- bool isVar)
- {
- typename NamePtrsMap<Value_t>::iterator nameIter =
- namePtrs.lower_bound(newName.first);
-
- if(nameIter != namePtrs.end() && newName.first == nameIter->first)
- {
- // redefining a var is not allowed.
- if(isVar) return false;
-
- // redefining other tokens is allowed, if the type stays the same.
- if(nameIter->second.type != newName.second.type)
- return false;
-
- // update the data
- nameIter->second = newName.second;
- return true;
- }
-
- if(!isVar)
- {
- // Allocate a copy of the name (pointer stored in the map key)
- // However, for VARIABLEs, the pointer points to VariableString,
- // which is managed separately. Thusly, only done when !IsVar.
- char* namebuf = new char[newName.first.nameLength];
- memcpy(namebuf, newName.first.name, newName.first.nameLength);
- newName.first.name = namebuf;
- }
-
- namePtrs.insert(nameIter, newName);
- return true;
- }
-}
-
-
-//=========================================================================
-// Data struct implementation
-//=========================================================================
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::Data():
- mReferenceCounter(1),
- mDelimiterChar(0),
- mParseErrorType(NO_FUNCTION_PARSED_YET),
- mEvalErrorType(0),
- mUseDegreeConversion(false),
- mErrorLocation(0),
- mVariablesAmount(0),
- mStackSize(0)
-{}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::Data(const Data& rhs):
- mReferenceCounter(0),
- mDelimiterChar(rhs.mDelimiterChar),
- mParseErrorType(rhs.mParseErrorType),
- mEvalErrorType(rhs.mEvalErrorType),
- mUseDegreeConversion(rhs.mUseDegreeConversion),
- mErrorLocation(rhs.mErrorLocation),
- mVariablesAmount(rhs.mVariablesAmount),
- mVariablesString(rhs.mVariablesString),
- mNamePtrs(),
- mFuncPtrs(rhs.mFuncPtrs),
- mFuncParsers(rhs.mFuncParsers),
- mByteCode(rhs.mByteCode),
- mImmed(rhs.mImmed),
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mStack(rhs.mStackSize),
-#endif
- mStackSize(rhs.mStackSize)
-{
- for(typename NamePtrsMap<Value_t>::const_iterator i = rhs.mNamePtrs.begin();
- i != rhs.mNamePtrs.end();
- ++i)
- {
- if(i->second.type == NameData<Value_t>::VARIABLE)
- {
- const std::size_t variableStringOffset =
- i->first.name - rhs.mVariablesString.c_str();
- std::pair<NamePtr, NameData<Value_t> > tmp
- (NamePtr(&mVariablesString[variableStringOffset],
- i->first.nameLength),
- i->second);
- mNamePtrs.insert(mNamePtrs.end(), tmp);
- }
- else
- {
- std::pair<NamePtr, NameData<Value_t> > tmp
- (NamePtr(new char[i->first.nameLength], i->first.nameLength),
- i->second );
- memcpy(const_cast<char*>(tmp.first.name), i->first.name,
- tmp.first.nameLength);
- mNamePtrs.insert(mNamePtrs.end(), tmp);
- }
- }
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::~Data()
-{
- for(typename NamePtrsMap<Value_t>::iterator i = mNamePtrs.begin();
- i != mNamePtrs.end();
- ++i)
- {
- if(i->second.type != NameData<Value_t>::VARIABLE)
- delete[] i->first.name;
- }
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::incFuncWrapperRefCount
-(FunctionWrapper* wrapper)
-{
- ++wrapper->mReferenceCount;
-}
-
-template<typename Value_t>
-unsigned FunctionParserBase<Value_t>::decFuncWrapperRefCount
-(FunctionWrapper* wrapper)
-{
- return --wrapper->mReferenceCount;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData():
- mRawFuncPtr(0), mFuncWrapperPtr(0), mParams(0)
-{}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::~FuncWrapperPtrData()
-{
- if(mFuncWrapperPtr &&
- FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
- delete mFuncWrapperPtr;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::FuncWrapperPtrData
-(const FuncWrapperPtrData& rhs):
- mRawFuncPtr(rhs.mRawFuncPtr),
- mFuncWrapperPtr(rhs.mFuncWrapperPtr),
- mParams(rhs.mParams)
-{
- if(mFuncWrapperPtr)
- FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::Data::FuncWrapperPtrData&
-FunctionParserBase<Value_t>::Data::FuncWrapperPtrData::operator=
-(const FuncWrapperPtrData& rhs)
-{
- if(&rhs != this)
- {
- if(mFuncWrapperPtr &&
- FunctionParserBase::decFuncWrapperRefCount(mFuncWrapperPtr) == 0)
- delete mFuncWrapperPtr;
- mRawFuncPtr = rhs.mRawFuncPtr;
- mFuncWrapperPtr = rhs.mFuncWrapperPtr;
- mParams = rhs.mParams;
- if(mFuncWrapperPtr)
- FunctionParserBase::incFuncWrapperRefCount(mFuncWrapperPtr);
- }
- return *this;
-}
-
-
-//=========================================================================
-// FunctionParser constructors, destructor and assignment
-//=========================================================================
-template<typename Value_t>
-FunctionParserBase<Value_t>::FunctionParserBase():
- mData(new Data),
- mStackPtr(0)
-{
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::~FunctionParserBase()
-{
- if(--(mData->mReferenceCounter) == 0)
- delete mData;
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>::FunctionParserBase(const FunctionParserBase& cpy):
- mData(cpy.mData),
- mStackPtr(0)
-{
- ++(mData->mReferenceCounter);
-}
-
-template<typename Value_t>
-FunctionParserBase<Value_t>&
-FunctionParserBase<Value_t>::operator=(const FunctionParserBase& cpy)
-{
- if(mData != cpy.mData)
- {
- if(--(mData->mReferenceCounter) == 0) delete mData;
-
- mData = cpy.mData;
- ++(mData->mReferenceCounter);
- }
- return *this;
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::Data*
-FunctionParserBase<Value_t>::getParserData()
-{
- return mData;
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::setDelimiterChar(char c)
-{
- mData->mDelimiterChar = c;
-}
-
-
-//---------------------------------------------------------------------------
-// Copy-on-write method
-//---------------------------------------------------------------------------
-template<typename Value_t>
-void FunctionParserBase<Value_t>::CopyOnWrite()
-{
- if(mData->mReferenceCounter > 1)
- {
- Data* oldData = mData;
- mData = new Data(*oldData);
- --(oldData->mReferenceCounter);
- mData->mReferenceCounter = 1;
- }
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::ForceDeepCopy()
-{
- CopyOnWrite();
-}
-
-
-//=========================================================================
-// Epsilon
-//=========================================================================
-template<typename Value_t>
-Value_t FunctionParserBase<Value_t>::epsilon()
-{
- return Epsilon<Value_t>::value;
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::setEpsilon(Value_t value)
-{
- Epsilon<Value_t>::value = value;
-}
-
-
-//=========================================================================
-// User-defined identifier addition functions
-//=========================================================================
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddConstant(const std::string& name,
- Value_t value)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::CONSTANT, value));
-
- return addNewNameData(mData->mNamePtrs, newName, false);
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddUnit(const std::string& name,
- Value_t value)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::UNIT, value));
- return addNewNameData(mData->mNamePtrs, newName, false);
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddFunction
-(const std::string& name, FunctionPtr ptr, unsigned paramsAmount)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name)) return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::FUNC_PTR,
- unsigned(mData->mFuncPtrs.size())));
-
- const bool success = addNewNameData(mData->mNamePtrs, newName, false);
- if(success)
- {
- mData->mFuncPtrs.push_back(typename Data::FuncWrapperPtrData());
- mData->mFuncPtrs.back().mRawFuncPtr = ptr;
- mData->mFuncPtrs.back().mParams = paramsAmount;
- }
- return success;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::addFunctionWrapperPtr
-(const std::string& name, FunctionWrapper* wrapper, unsigned paramsAmount)
-{
- if(!AddFunction(name, FunctionPtr(0), paramsAmount)) return false;
- mData->mFuncPtrs.back().mFuncWrapperPtr = wrapper;
- return true;
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::FunctionWrapper*
-FunctionParserBase<Value_t>::GetFunctionWrapper(const std::string& name)
-{
- CopyOnWrite();
- NamePtr namePtr(name.data(), unsigned(name.size()));
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(namePtr);
-
- if(nameIter != mData->mNamePtrs.end() &&
- nameIter->second.type == NameData<Value_t>::FUNC_PTR)
- {
- return mData->mFuncPtrs[nameIter->second.index].mFuncWrapperPtr;
- }
- return 0;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::CheckRecursiveLinking
-(const FunctionParserBase* fp) const
-{
- if(fp == this) return true;
- for(unsigned i = 0; i < fp->mData->mFuncParsers.size(); ++i)
- if(CheckRecursiveLinking(fp->mData->mFuncParsers[i].mParserPtr))
- return true;
- return false;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::AddFunction(const std::string& name,
- FunctionParserBase& fp)
-{
- if(!containsOnlyValidIdentifierChars<Value_t>(name) ||
- CheckRecursiveLinking(&fp))
- return false;
-
- CopyOnWrite();
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(name.data(), unsigned(name.size())),
- NameData<Value_t>(NameData<Value_t>::PARSER_PTR,
- unsigned(mData->mFuncParsers.size())));
-
- const bool success = addNewNameData(mData->mNamePtrs, newName, false);
- if(success)
- {
- mData->mFuncParsers.push_back(typename Data::FuncParserPtrData());
- mData->mFuncParsers.back().mParserPtr = &fp;
- mData->mFuncParsers.back().mParams = fp.mData->mVariablesAmount;
- }
- return success;
-}
-
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::RemoveIdentifier(const std::string& name)
-{
- CopyOnWrite();
-
- NamePtr namePtr(name.data(), unsigned(name.size()));
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(namePtr);
-
- if(nameIter != mData->mNamePtrs.end())
- {
- if(nameIter->second.type == NameData<Value_t>::VARIABLE)
- {
- // Illegal attempt to delete variables
- return false;
- }
- delete[] nameIter->first.name;
- mData->mNamePtrs.erase(nameIter);
- return true;
- }
- return false;
-}
-
-
-//=========================================================================
-// Function parsing
-//=========================================================================
-namespace
-{
- // Error messages returned by ErrorMsg():
- const char* const ParseErrorMessage[]=
- {
- "Syntax error", // 0
- "Mismatched parenthesis", // 1
- "Missing ')'", // 2
- "Empty parentheses", // 3
- "Syntax error: Operator expected", // 4
- "Not enough memory", // 5
- "An unexpected error occurred. Please make a full bug report "
- "to the author", // 6
- "Syntax error in parameter 'Vars' given to "
- "FunctionParser::Parse()", // 7
- "Illegal number of parameters to function", // 8
- "Syntax error: Premature end of string", // 9
- "Syntax error: Expecting ( after function", // 10
- "Syntax error: Unknown identifier", // 11
- "(No function has been parsed yet)",
- ""
- };
-
- template<typename Value_t>
- inline typename FunctionParserBase<Value_t>::ParseErrorType
- noCommaError(char c)
- {
- return c == ')' ?
- FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
- FunctionParserBase<Value_t>::SYNTAX_ERROR;
- }
-
- template<typename Value_t>
- inline typename FunctionParserBase<Value_t>::ParseErrorType
- noParenthError(char c)
- {
- return c == ',' ?
- FunctionParserBase<Value_t>::ILL_PARAMS_AMOUNT :
- FunctionParserBase<Value_t>::MISSING_PARENTH;
- }
-
- template<unsigned offset>
- struct IntLiteralMask
- {
- enum { mask =
- // ( 1UL << ('-'-offset)) |
- (0x3FFUL << ('0'-offset)) }; /* 0x3FF = 10 bits worth "1" */
- // Note: If you change fparser to support negative numbers parsing
- // (as opposed to parsing them as cNeg followed by literal),
- // enable the '-' line above, and change the offset value
- // in BeginsLiteral() to '-' instead of '.'.
- };
-
- template<typename Value_t, unsigned offset>
- struct LiteralMask
- {
- enum { mask =
- ( 1UL << ('.'-offset)) |
- IntLiteralMask<offset>::mask };
- };
-#ifdef FP_SUPPORT_LONG_INT_TYPE
- template<unsigned offset>
- struct LiteralMask<long, offset>: public IntLiteralMask<offset>
- {
- };
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
- template<unsigned offset>
- struct LiteralMask<GmpInt, offset>: public IntLiteralMask<offset>
- {
- };
-#endif
-
- template<unsigned offset>
- struct SimpleSpaceMask
- {
- enum { mask =
- (1UL << ('\r'-offset)) |
- (1UL << ('\n'-offset)) |
- (1UL << ('\v'-offset)) |
- (1UL << ('\t'-offset)) |
- (1UL << (' ' -offset)) };
- };
-
- template<typename Value_t>
- inline bool BeginsLiteral(unsigned byte)
- {
- enum { n = sizeof(unsigned long)>=8 ? 0 : '.' };
- byte -= n;
- if(byte > (unsigned char)('9'-n)) return false;
- unsigned long shifted = 1UL << byte;
- const unsigned long mask = LiteralMask<Value_t, n>::mask;
- return (mask & shifted) != 0;
- }
-
- template<typename CharPtr>
- inline void SkipSpace(CharPtr& function)
- {
-/*
- Space characters in unicode:
-U+0020 SPACE Depends on font, often adjusted (see below)
-U+00A0 NO-BREAK SPACE As a space, but often not adjusted
-U+2000 EN QUAD 1 en (= 1/2 em)
-U+2001 EM QUAD 1 em (nominally, the height of the font)
-U+2002 EN SPACE 1 en (= 1/2 em)
-U+2003 EM SPACE 1 em
-U+2004 THREE-PER-EM SPACE 1/3 em
-U+2005 FOUR-PER-EM SPACE 1/4 em
-U+2006 SIX-PER-EM SPACE 1/6 em
-U+2007 FIGURE SPACE Tabular width, the width of digits
-U+2008 PUNCTUATION SPACE The width of a period .
-U+2009 THIN SPACE 1/5 em (or sometimes 1/6 em)
-U+200A HAIR SPACE Narrower than THIN SPACE
-U+200B ZERO WIDTH SPACE Nominally no width, but may expand
-U+202F NARROW NO-BREAK SPACE Narrower than NO-BREAK SPACE (or SPACE)
-U+205F MEDIUM MATHEMATICAL SPACE 4/18 em
-U+3000 IDEOGRAPHIC SPACE The width of ideographic (CJK) characters.
- Also:
-U+000A \n
-U+000D \r
-U+0009 \t
-U+000B \v
- As UTF-8 sequences:
- 09
- 0A
- 0B
- 0D
- 20
- C2 A0
- E2 80 80-8B
- E2 80 AF
- E2 81 9F
- E3 80 80
-*/
- while(true)
- {
- enum { n = sizeof(unsigned long)>=8 ? 0 : '\t' };
- typedef signed char schar;
- unsigned byte = (unsigned char)*function;
- byte -= n;
- // ^Note: values smaller than n intentionally become
- // big values here due to integer wrap. The
- // comparison below thus excludes them, making
- // the effective range 0x09..0x20 (32-bit)
- // or 0x00..0x20 (64-bit) within the if-clause.
- if(byte <= (unsigned char)(' '-n))
- {
- unsigned long shifted = 1UL << byte;
- const unsigned long mask = SimpleSpaceMask<n>::mask;
- if(mask & shifted)
- { ++function; continue; } // \r, \n, \t, \v and space
- break;
- }
- if(likely(byte < 0xC2-n)) break;
-
- if(byte == 0xC2-n && function[1] == char(0xA0))
- { function += 2; continue; } // U+00A0
- if(byte == 0xE3-n &&
- function[1] == char(0x80) && function[2] == char(0x80))
- { function += 3; continue; } // U+3000
- if(byte == 0xE2-n)
- {
- if(function[1] == char(0x81))
- {
- if(function[2] != char(0x9F)) break;
- function += 3; // U+205F
- continue;
- }
- if(function[1] == char(0x80))
- if(function[2] == char(0xAF) || // U+202F
- schar(function[2]) <= schar(0x8B) // U+2000..U+200B
- )
- {
- function += 3;
- continue;
- }
- }
- break;
- } // while(true)
- } // SkipSpace(CharPtr& function)
-}
-
-// ---------------------------------------------------------------------------
-// Return parse error message
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::ErrorMsg() const
-{
- return ParseErrorMessage[mData->mParseErrorType];
-}
-
-template<typename Value_t>
-typename FunctionParserBase<Value_t>::ParseErrorType
-FunctionParserBase<Value_t>::GetParseErrorType() const
-{
- return mData->mParseErrorType;
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::EvalError() const
-{
- return mData->mEvalErrorType;
-}
-
-
-// ---------------------------------------------------------------------------
-// Parse variables
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-bool FunctionParserBase<Value_t>::ParseVariables
-(const std::string& inputVarString)
-{
- if(mData->mVariablesString == inputVarString) return true;
-
- /* Delete existing variables from mNamePtrs */
- for(typename NamePtrsMap<Value_t>::iterator i =
- mData->mNamePtrs.begin();
- i != mData->mNamePtrs.end(); )
- {
- if(i->second.type == NameData<Value_t>::VARIABLE)
- {
- typename NamePtrsMap<Value_t>::iterator j (i);
- ++i;
- mData->mNamePtrs.erase(j);
- }
- else ++i;
- }
- mData->mVariablesString = inputVarString;
-
- const std::string& vars = mData->mVariablesString;
- const unsigned len = unsigned(vars.size());
-
- unsigned varNumber = VarBegin;
-
- const char* beginPtr = vars.c_str();
- const char* finalPtr = beginPtr + len;
- while(beginPtr < finalPtr)
- {
- SkipSpace(beginPtr);
- unsigned nameLength = readIdentifier<Value_t>(beginPtr);
- if(nameLength == 0 || (nameLength & 0x80000000U)) return false;
- const char* endPtr = beginPtr + nameLength;
- SkipSpace(endPtr);
- if(endPtr != finalPtr && *endPtr != ',') return false;
-
- std::pair<NamePtr, NameData<Value_t> > newName
- (NamePtr(beginPtr, nameLength),
- NameData<Value_t>(NameData<Value_t>::VARIABLE, varNumber++));
-
- if(!addNewNameData(mData->mNamePtrs, newName, true))
- {
- return false;
- }
-
- beginPtr = endPtr + 1;
- }
-
- mData->mVariablesAmount = varNumber - VarBegin;
- return true;
-}
-
-// ---------------------------------------------------------------------------
-// Parse() public interface functions
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-int FunctionParserBase<Value_t>::Parse(const char* Function,
- const std::string& Vars,
- bool useDegrees)
-{
- CopyOnWrite();
-
- if(!ParseVariables(Vars))
- {
- mData->mParseErrorType = INVALID_VARS;
- return int(strlen(Function));
- }
-
- return ParseFunction(Function, useDegrees);
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::Parse(const std::string& Function,
- const std::string& Vars,
- bool useDegrees)
-{
- CopyOnWrite();
-
- if(!ParseVariables(Vars))
- {
- mData->mParseErrorType = INVALID_VARS;
- return int(Function.size());
- }
-
- return ParseFunction(Function.c_str(), useDegrees);
-}
-
-
-// ---------------------------------------------------------------------------
-// Main parsing function
-// ---------------------------------------------------------------------------
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseFunction(const char* function,
- bool useDegrees)
-{
- mData->mUseDegreeConversion = useDegrees;
- mData->mParseErrorType = FP_NO_ERROR;
-
- mData->mInlineVarNames.clear();
- mData->mByteCode.clear(); mData->mByteCode.reserve(128);
- mData->mImmed.clear(); mData->mImmed.reserve(128);
- mData->mStackSize = mStackPtr = 0;
-
- mData->mHasByteCodeFlags = false;
-
- const char* ptr = Compile(function);
- mData->mInlineVarNames.clear();
-
- if(mData->mHasByteCodeFlags)
- {
- for(unsigned i = unsigned(mData->mByteCode.size()); i-- > 0; )
- mData->mByteCode[i] &= ~FP_ParamGuardMask;
- }
-
- if(mData->mParseErrorType != FP_NO_ERROR)
- return int(mData->mErrorLocation - function);
-
- assert(ptr); // Should never be null at this point. It's a bug otherwise.
- if(*ptr)
- {
- if(mData->mDelimiterChar == 0 || *ptr != mData->mDelimiterChar)
- mData->mParseErrorType = EXPECT_OPERATOR;
- return int(ptr - function);
- }
-
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mData->mStack.resize(mData->mStackSize);
-#endif
-
- return -1;
-}
-
-
-//=========================================================================
-// Parsing and bytecode compiling functions
-//=========================================================================
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::SetErrorType(ParseErrorType t,
- const char* pos)
-{
- mData->mParseErrorType = t;
- mData->mErrorLocation = pos;
- return 0;
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::incStackPtr()
-{
- if(++mStackPtr > mData->mStackSize) ++(mData->mStackSize);
-}
-
-namespace
-{
- const unsigned char powi_factor_table[128] =
- {
- 0,1,0,0,0,0,0,0, 0, 0,0,0,0,0,0,3,/* 0 - 15 */
- 0,0,0,0,0,0,0,0, 0, 5,0,3,0,0,3,0,/* 16 - 31 */
- 0,0,0,0,0,0,0,3, 0, 0,0,0,0,5,0,0,/* 32 - 47 */
- 0,0,5,3,0,0,3,5, 0, 3,0,0,3,0,0,3,/* 48 - 63 */
- 0,0,0,0,0,0,0,0, 0, 0,0,3,0,0,3,0,/* 64 - 79 */
- 0,9,0,0,0,5,0,3, 0, 0,5,7,0,0,0,5,/* 80 - 95 */
- 0,0,0,3,5,0,3,0, 0, 3,0,0,3,0,5,3,/* 96 - 111 */
- 0,0,3,5,0,9,0,7, 3,11,0,3,0,5,3,0,/* 112 - 127 */
- };
-
- inline int get_powi_factor(long abs_int_exponent)
- {
- if(abs_int_exponent >= int(sizeof(powi_factor_table))) return 0;
- return powi_factor_table[abs_int_exponent];
- }
-
-#if 0
- int EstimatePowiComplexity(int abs_int_exponent)
- {
- int cost = 0;
- while(abs_int_exponent > 1)
- {
- int factor = get_powi_factor(abs_int_exponent);
- if(factor)
- {
- cost += EstimatePowiComplexity(factor);
- abs_int_exponent /= factor;
- continue;
- }
- if(!(abs_int_exponent & 1))
- {
- abs_int_exponent /= 2;
- cost += 3; // sqr
- }
- else
- {
- cost += 4; // dup+mul
- abs_int_exponent -= 1;
- }
- }
- return cost;
- }
-#endif
-
- bool IsEligibleIntPowiExponent(long int_exponent)
- {
- if(int_exponent == 0) return false;
- long abs_int_exponent = int_exponent;
- #if 0
- int cost = 0;
-
- if(abs_int_exponent < 0)
- {
- cost += 11;
- abs_int_exponent = -abs_int_exponent;
- }
-
- cost += EstimatePowiComplexity(abs_int_exponent);
-
- return cost < (10*3 + 4*4);
- #else
- if(abs_int_exponent < 0) abs_int_exponent = -abs_int_exponent;
-
- return (abs_int_exponent >= 1)
- && (abs_int_exponent <= 46 ||
- (abs_int_exponent <= 1024 &&
- (abs_int_exponent & (abs_int_exponent - 1)) == 0));
- #endif
- }
-
- /* Needed by fp_opcode_add.inc if tracing is enabled */
- template<typename Value_t>
- std::string findName(const NamePtrsMap<Value_t>& nameMap,
- unsigned index,
- typename NameData<Value_t>::DataType type)
- {
- for(typename NamePtrsMap<Value_t>::const_iterator
- iter = nameMap.begin();
- iter != nameMap.end();
- ++iter)
- {
- if(iter->second.type == type && iter->second.index == index)
- return std::string(iter->first.name,
- iter->first.name + iter->first.nameLength);
- }
- return "?";
- }
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::AddImmedOpcode(Value_t value)
-{
- mData->mImmed.push_back(value);
- mData->mByteCode.push_back(cImmed);
-}
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::CompilePowi(long abs_int_exponent)
-{
- int num_muls=0;
- while(abs_int_exponent > 1)
- {
- long factor = get_powi_factor(abs_int_exponent);
- if(factor)
- {
- CompilePowi(factor);
- abs_int_exponent /= factor;
- continue;
- }
- if(!(abs_int_exponent & 1))
- {
- abs_int_exponent /= 2;
- mData->mByteCode.push_back(cSqr);
- // ^ Don't put AddFunctionOpcode here,
- // it would slow down a great deal.
- }
- else
- {
- mData->mByteCode.push_back(cDup);
- incStackPtr();
- abs_int_exponent -= 1;
- ++num_muls;
- }
- }
- if(num_muls > 0)
- {
- mData->mByteCode.resize(mData->mByteCode.size()+num_muls, cMul);
- mStackPtr -= num_muls;
- }
-}
-
-template<typename Value_t>
-inline bool FunctionParserBase<Value_t>::TryCompilePowi(Value_t original_immed)
-{
- Value_t changed_immed = original_immed;
- for(int sqrt_count=0; /**/; ++sqrt_count)
- {
- long int_exponent = makeLongInteger(changed_immed);
- if(isLongInteger(changed_immed) &&
- IsEligibleIntPowiExponent(int_exponent))
- {
- long abs_int_exponent = int_exponent;
- if(abs_int_exponent < 0)
- abs_int_exponent = -abs_int_exponent;
-
- mData->mImmed.pop_back(); mData->mByteCode.pop_back();
- --mStackPtr;
- // ^Though the above is accounted for by the procedure
- // that generates cPow, we need it for correct cFetch
- // indexes in CompilePowi().
-
- while(sqrt_count > 0)
- {
- int opcode = cSqrt;
- if(sqrt_count == 1 && int_exponent < 0)
- {
- opcode = cRSqrt;
- int_exponent = -int_exponent;
- }
- mData->mByteCode.push_back(opcode);
- --sqrt_count;
- }
- if((abs_int_exponent & 1) == 0)
- {
- // This special rule fixes the optimization
- // shortcoming of (-x)^2 with minimal overhead.
- AddFunctionOpcode(cSqr);
- abs_int_exponent >>= 1;
- }
- CompilePowi(abs_int_exponent);
- if(int_exponent < 0) mData->mByteCode.push_back(cInv);
- ++mStackPtr; // Needed because cPow adding will assume this.
- return true;
- }
- if(sqrt_count >= 4) break;
- changed_immed += changed_immed;
- }
-
- // When we don't know whether x >= 0, we still know that
- // x^y can be safely converted into exp(y * log(x))
- // when y is _not_ integer, because we know that x >= 0.
- // Otherwise either expression will give a NaN.
- if(/*!isInteger(original_immed) ||*/
- IsNeverNegativeValueOpcode(mData->mByteCode[mData->mByteCode.size()-2]))
- {
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- //--mStackPtr; - accounted for by the procedure that generates cPow
- AddFunctionOpcode(cLog);
- AddImmedOpcode(original_immed);
- //incStackPtr(); - this and the next are redundant because...
- AddFunctionOpcode(cMul);
- //--mStackPtr; - ...because the cImmed was popped earlier.
- AddFunctionOpcode(cExp);
- return true;
- }
- return false;
-}
-
-//#include "fpoptimizer/opcodename.hh"
-// ^ needed only if FP_TRACE_BYTECODE_OPTIMIZATION() is used
-
-template<typename Value_t>
-inline void FunctionParserBase<Value_t>::AddFunctionOpcode(unsigned opcode)
-{
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-template<>
-inline void FunctionParserBase<long>::AddFunctionOpcode(unsigned opcode)
-{
- typedef long Value_t;
-#define FP_FLOAT_VERSION 0
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-inline void FunctionParserBase<GmpInt>::AddFunctionOpcode(unsigned opcode)
-{
- typedef GmpInt Value_t;
-#define FP_FLOAT_VERSION 0
-#define FP_COMPLEX_VERSION 0
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-template<>
-inline void FunctionParserBase<std::complex<double> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<double> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-template<>
-inline void FunctionParserBase<std::complex<float> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<float> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-template<>
-inline void FunctionParserBase<std::complex<long double> >::AddFunctionOpcode(unsigned opcode)
-{
- typedef std::complex<long double> Value_t;
-#define FP_FLOAT_VERSION 1
-#define FP_COMPLEX_VERSION 1
-#include "extrasrc/fp_opcode_add.inc"
-#undef FP_COMPLEX_VERSION
-#undef FP_FLOAT_VERSION
-}
-#endif
-
-template<typename Value_t>
-unsigned
-FunctionParserBase<Value_t>::ParseIdentifier(const char* function)
-{
- return readIdentifier<Value_t>(function);
-}
-
-template<typename Value_t>
-std::pair<const char*, Value_t>
-FunctionParserBase<Value_t>::ParseLiteral(const char* function)
-{
- char* endptr;
-#if 0 /* Profile the hex literal parser */
- if(function[0]=='0' && function[1]=='x')
- {
- // Parse hexadecimal literal if fp_parseLiteral didn't already
- Value_t val = parseHexLiteral<Value_t>(function+2, &endptr);
- if(endptr == function+2)
- return std::pair<const char*,Value_t> (function, Value_t());
- return std::pair<const char*, Value_t> (endptr, val);
- }
-#endif
- Value_t val = fp_parseLiteral<Value_t>(function, &endptr);
-
- if(endptr == function+1 && function[0] == '0' && function[1] == 'x')
- {
- // Parse hexadecimal literal if fp_parseLiteral didn't already
- val = parseHexLiteral<Value_t>(function+2, &endptr);
- if(endptr == function+2)
- return std::pair<const char*,Value_t> (function, Value_t());
- }
- else if(endptr == function)
- return std::pair<const char*,Value_t> (function, Value_t());
-
- return std::pair<const char*,Value_t> (endptr, val);
-}
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-template<>
-std::pair<const char*, MpfrFloat>
-FunctionParserBase<MpfrFloat>::ParseLiteral(const char* function)
-{
- char* endPtr;
- const MpfrFloat val = MpfrFloat::parseString(function, &endPtr);
- if(endPtr == function)
- return std::pair<const char*,MpfrFloat> (function, MpfrFloat());
- return std::pair<const char*,MpfrFloat> (endPtr, val);
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-std::pair<const char*, GmpInt>
-FunctionParserBase<GmpInt>::ParseLiteral(const char* function)
-{
- char* endPtr;
- const GmpInt val = GmpInt::parseString(function, &endPtr);
- if(endPtr == function)
- return std::pair<const char*,GmpInt> (function, GmpInt());
- return std::pair<const char*,GmpInt> (endPtr, val);
-}
-#endif
-
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileLiteral(const char* function)
-{
- std::pair<const char*, Value_t> result = ParseLiteral(function);
-
- if(result.first == function)
- return SetErrorType(SYNTAX_ERROR, result.first);
-
- AddImmedOpcode(result.second);
- incStackPtr();
- SkipSpace(result.first);
- return result.first;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileIf(const char* function)
-{
- if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
-
- function = CompileExpression(function+1);
- if(!function) return 0;
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- OPCODE opcode = cIf;
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
- if(IsNeverNegativeValueOpcode(mData->mByteCode.back()))
- {
- // If we know that the condition to be tested is always
- // a positive value (such as when produced by "x<y"),
- // we can use the faster opcode to evaluate it.
- // cIf tests whether fabs(cond) >= 0.5,
- // cAbsIf simply tests whether cond >= 0.5.
- opcode = cAbsIf;
- }
-
- mData->mByteCode.push_back(opcode);
- const unsigned curByteCodeSize = unsigned(mData->mByteCode.size());
- PushOpcodeParam<false>(0); // Jump index; to be set later
- PushOpcodeParam<true> (0); // Immed jump index; to be set later
-
- --mStackPtr;
-
- function = CompileExpression(function + 1);
- if(!function) return 0;
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- mData->mByteCode.push_back(cJump);
- const unsigned curByteCodeSize2 = unsigned(mData->mByteCode.size());
- const unsigned curImmedSize2 = unsigned(mData->mImmed.size());
- PushOpcodeParam<false>(0); // Jump index; to be set later
- PushOpcodeParam<true> (0); // Immed jump index; to be set later
-
- --mStackPtr;
-
- function = CompileExpression(function + 1);
- if(!function) return 0;
- if(*function != ')')
- return SetErrorType(noParenthError<Value_t>(*function), function);
-
- PutOpcodeParamAt<true> ( mData->mByteCode.back(), unsigned(mData->mByteCode.size()-1) );
- // ^Necessary for guarding against if(x,1,2)+1 being changed
- // into if(x,1,3) by fp_opcode_add.inc
-
- // Set jump indices
- PutOpcodeParamAt<false>( curByteCodeSize2+1, curByteCodeSize );
- PutOpcodeParamAt<false>( curImmedSize2, curByteCodeSize+1 );
- PutOpcodeParamAt<false>( unsigned(mData->mByteCode.size())-1, curByteCodeSize2);
- PutOpcodeParamAt<false>( unsigned(mData->mImmed.size()), curByteCodeSize2+1);
-
- ++function;
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileFunctionParams
-(const char* function, unsigned requiredParams)
-{
- if(*function != '(') return SetErrorType(EXPECT_PARENTH_FUNC, function);
-
- if(requiredParams > 0)
- {
- const char* function_end = CompileExpression(function+1);
- if(!function_end)
- {
- // If an error occurred, verify whether it was caused by ()
- ++function;
- SkipSpace(function);
- if(*function == ')')
- return SetErrorType(ILL_PARAMS_AMOUNT, function);
- // Not caused by (), use the error message given by CompileExpression()
- return 0;
- }
- function = function_end;
-
- for(unsigned i = 1; i < requiredParams; ++i)
- {
- if(*function != ',')
- return SetErrorType(noCommaError<Value_t>(*function), function);
-
- function = CompileExpression(function+1);
- if(!function) return 0;
- }
- // No need for incStackPtr() because each parse parameter calls it
- mStackPtr -= requiredParams-1;
- }
- else
- {
- incStackPtr(); // return value of function is pushed onto the stack
- ++function;
- SkipSpace(function);
- }
-
- if(*function != ')')
- return SetErrorType(noParenthError<Value_t>(*function), function);
- ++function;
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileElement(const char* function)
-{
- if(BeginsLiteral<Value_t>( (unsigned char) *function))
- return CompileLiteral(function);
-
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength == 0)
- {
- // No identifier found
- if(*function == '(') return CompileParenthesis(function);
- if(*function == ')') return SetErrorType(MISM_PARENTH, function);
- return SetErrorType(SYNTAX_ERROR, function);
- }
-
- // Function, variable or constant
- if(nameLength & 0x80000000U) // Function
- {
- OPCODE func_opcode = OPCODE( (nameLength >> 16) & 0x7FFF );
- return CompileFunction(function + (nameLength & 0xFFFF), func_opcode);
- }
-
- NamePtr name(function, nameLength);
- const char* endPtr = function + nameLength;
- SkipSpace(endPtr);
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(name);
- if(nameIter == mData->mNamePtrs.end())
- {
- // Check if it's an inline variable:
- for(typename Data::InlineVarNamesContainer::reverse_iterator iter =
- mData->mInlineVarNames.rbegin();
- iter != mData->mInlineVarNames.rend();
- ++iter)
- {
- if(name == iter->mName)
- {
- if( iter->mFetchIndex+1 == mStackPtr)
- {
- mData->mByteCode.push_back(cDup);
- }
- else
- {
- mData->mByteCode.push_back(cFetch);
- PushOpcodeParam<true>(iter->mFetchIndex);
- }
- incStackPtr();
- return endPtr;
- }
- }
-
- return SetErrorType(UNKNOWN_IDENTIFIER, function);
- }
-
- const NameData<Value_t>* nameData = &nameIter->second;
- switch(nameData->type)
- {
- case NameData<Value_t>::VARIABLE: // is variable
- if(unlikely(!mData->mByteCode.empty() &&
- mData->mByteCode.back() == nameData->index))
- mData->mByteCode.push_back(cDup);
- else
- mData->mByteCode.push_back(nameData->index);
- incStackPtr();
- return endPtr;
-
- case NameData<Value_t>::CONSTANT: // is constant
- AddImmedOpcode(nameData->value);
- incStackPtr();
- return endPtr;
-
- case NameData<Value_t>::UNIT: // is unit (error if appears here)
- break;
-
- case NameData<Value_t>::FUNC_PTR: // is C++ function
- function = CompileFunctionParams
- (endPtr, mData->mFuncPtrs[nameData->index].mParams);
- //if(!function) return 0;
- mData->mByteCode.push_back(cFCall);
- PushOpcodeParam<true>(nameData->index);
- return function;
-
- case NameData<Value_t>::PARSER_PTR: // is FunctionParser
- function = CompileFunctionParams
- (endPtr, mData->mFuncParsers[nameData->index].mParams);
- //if(!function) return 0;
- mData->mByteCode.push_back(cPCall);
- PushOpcodeParam<true>(nameData->index);
- return function;
- }
-
- // When it's an unit (or unrecognized type):
- return SetErrorType(SYNTAX_ERROR, function);
-}
-
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::CompileFunction
-(const char* function, unsigned func_opcode)
-{
- SkipSpace(function);
- const FuncDefinition& funcDef = Functions[func_opcode];
-
- if(func_opcode == cIf) // "if" is a special case
- return CompileIf(function);
-
- unsigned requiredParams = funcDef.params;
-
- function = CompileFunctionParams(function, requiredParams);
- if(!function) return 0;
-
- if(mData->mUseDegreeConversion)
- {
- if(funcDef.flags & FuncDefinition::AngleIn)
- AddFunctionOpcode(cRad);
-
- AddFunctionOpcode(func_opcode);
-
- if(funcDef.flags & FuncDefinition::AngleOut)
- AddFunctionOpcode(cDeg);
- }
- else
- {
- AddFunctionOpcode(func_opcode);
- }
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileParenthesis(const char* function)
-{
- ++function; // Skip '('
-
- SkipSpace(function);
- if(*function == ')') return SetErrorType(EMPTY_PARENTH, function);
- function = CompileExpression(function);
- if(!function) return 0;
-
- if(*function != ')') return SetErrorType(MISSING_PARENTH, function);
- ++function; // Skip ')'
-
- SkipSpace(function);
- return function;
-}
-
-template<typename Value_t>
-const char*
-FunctionParserBase<Value_t>::CompilePossibleUnit(const char* function)
-{
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength & 0x80000000U) return function; // built-in function name
- if(nameLength != 0)
- {
- NamePtr name(function, nameLength);
-
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(name);
- if(nameIter != mData->mNamePtrs.end())
- {
- const NameData<Value_t>* nameData = &nameIter->second;
- if(nameData->type == NameData<Value_t>::UNIT)
- {
- AddImmedOpcode(nameData->value);
- incStackPtr();
- AddFunctionOpcode(cMul);
- --mStackPtr;
-
- const char* endPtr = function + nameLength;
- SkipSpace(endPtr);
- return endPtr;
- }
- }
- }
-
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- function = CompilePossibleUnit(function);
-
- if(*function == '^')
- {
- ++function;
- SkipSpace(function);
-
- unsigned op = cPow;
- if(mData->mByteCode.back() == cImmed)
- {
- if(mData->mImmed.back() == fp_const_e<Value_t>())
- { op = cExp; mData->mByteCode.pop_back();
- mData->mImmed.pop_back(); --mStackPtr; }
- else if(mData->mImmed.back() == Value_t(2))
- { op = cExp2; mData->mByteCode.pop_back();
- mData->mImmed.pop_back(); --mStackPtr; }
- }
-
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- // add opcode
- AddFunctionOpcode(op);
-
- if(op == cPow) --mStackPtr;
- }
- return function;
-}
-
-/* Currently the power operator is skipped for integral types because its
- usefulness with them is questionable, and in the case of GmpInt, for safety
- reasons:
- - With long int almost any power, except for very small ones, would
- overflow the result, so the usefulness of this is rather questionable.
- - With GmpInt the power operator could be easily abused to make the program
- run out of memory (think of a function like "10^10^10^10^1000000").
-*/
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-template<>
-inline const char*
-FunctionParserBase<long>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- return CompilePossibleUnit(function);
-}
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-template<>
-inline const char*
-FunctionParserBase<GmpInt>::CompilePow(const char* function)
-{
- function = CompileElement(function);
- if(!function) return 0;
- return CompilePossibleUnit(function);
-}
-#endif
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileUnaryMinus(const char* function)
-{
- char op = *function;
- switch(op)
- {
- case '-':
- case '!':
- ++function;
- SkipSpace(function);
-
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- AddFunctionOpcode(op=='-' ? cNeg : cNot);
-
- return function;
- default: break;
- }
- return CompilePow(function);
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileMult(const char* function)
-{
- function = CompileUnaryMinus(function);
- if(!function) return 0;
-
- Value_t pending_immed(1);
- #define FP_FlushImmed(do_reset) \
- if(pending_immed != Value_t(1)) \
- { \
- unsigned op = cMul; \
- if(!IsIntType<Value_t>::result && mData->mByteCode.back() == cInv) \
- { \
- /* (...) cInv 5 cMul -> (...) 5 cRDiv */ \
- /* ^ ^ | */ \
- mData->mByteCode.pop_back(); \
- op = cRDiv; \
- } \
- AddImmedOpcode(pending_immed); \
- incStackPtr(); \
- AddFunctionOpcode(op); \
- --mStackPtr; \
- if(do_reset) pending_immed = Value_t(1); \
- }
- while(true)
- {
- char c = *function;
- if(c == '%')
- {
- FP_FlushImmed(true);
- ++function;
- SkipSpace(function);
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- AddFunctionOpcode(cMod);
- --mStackPtr;
- continue;
- }
- if(c != '*' && c != '/') break;
-
- bool safe_cumulation = (c == '*' || !IsIntType<Value_t>::result);
- if(!safe_cumulation)
- {
- FP_FlushImmed(true);
- }
-
- ++function;
- SkipSpace(function);
- if(mData->mByteCode.back() == cImmed
- && (safe_cumulation
- || mData->mImmed.back() == Value_t(1)))
- {
- // 5 (...) cMul --> (...) ||| 5 cMul
- // 5 (...) cDiv --> (...) cInv ||| 5 cMul
- // ^ | ^
- pending_immed *= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- --mStackPtr;
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- if(c == '/')
- AddFunctionOpcode(cInv);
- continue;
- }
- if(safe_cumulation
- && mData->mByteCode.back() == cMul
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) 5 cMul (...) cMul -> (:::) (...) cMul ||| 5 cMul
- // (:::) 5 cMul (...) cDiv -> (:::) (...) cDiv ||| 5 cMul
- // ^ ^
- pending_immed *= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- // cDiv is not tested here because the bytecode
- // optimizer will convert this kind of cDivs into cMuls.
- bool lhs_inverted = false;
- if(!IsIntType<Value_t>::result && c == '*'
- && mData->mByteCode.back() == cInv)
- {
- // (:::) cInv (...) cMul -> (:::) (...) cRDiv
- // (:::) cInv (...) cDiv -> (:::) (...) cMul cInv
- // ^ ^ |
- mData->mByteCode.pop_back();
- lhs_inverted = true;
- }
- function = CompileUnaryMinus(function);
- if(!function) return 0;
- if(safe_cumulation
- && mData->mByteCode.back() == cMul
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cMul cMul -> (:::) (...) cMul ||| 5 Mul
- // (:::) (...) 5 cMul cDiv -> (:::) (...) cDiv ||| /5 Mul
- // ^ ^
- if(c == '*')
- pending_immed *= mData->mImmed.back();
- else
- pending_immed /= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- else
- if(safe_cumulation
- && mData->mByteCode.back() == cRDiv
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cRDiv cMul -> (:::) (...) cDiv ||| 5 cMul
- // (:::) (...) 5 cRDiv cDiv -> (:::) (...) cMul ||| /5 cMul
- // ^ ^
- if(c == '*')
- { c = '/'; pending_immed *= mData->mImmed.back(); }
- else
- { c = '*'; pending_immed /= mData->mImmed.back(); }
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- if(!lhs_inverted) // if (/x/y) was changed to /(x*y), add missing cInv
- {
- AddFunctionOpcode(c == '*' ? cMul : cDiv);
- --mStackPtr;
- }
- else if(c == '*') // (/x)*y -> rdiv(x,y)
- {
- AddFunctionOpcode(cRDiv);
- --mStackPtr;
- }
- else // (/x)/y -> /(x*y)
- {
- AddFunctionOpcode(cMul);
- --mStackPtr;
- AddFunctionOpcode(cInv);
- }
- }
- FP_FlushImmed(false);
- #undef FP_FlushImmed
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileAddition(const char* function)
-{
- function = CompileMult(function);
- if(!function) return 0;
-
- Value_t pending_immed(0);
- #define FP_FlushImmed(do_reset) \
- if(pending_immed != Value_t(0)) \
- { \
- unsigned op = cAdd; \
- if(mData->mByteCode.back() == cNeg) \
- { \
- /* (...) cNeg 5 cAdd -> (...) 5 cRSub */ \
- /* ^ ^ | */ \
- mData->mByteCode.pop_back(); \
- op = cRSub; \
- } \
- AddImmedOpcode(pending_immed); \
- incStackPtr(); \
- AddFunctionOpcode(op); \
- --mStackPtr; \
- if(do_reset) pending_immed = Value_t(0); \
- }
- while(true)
- {
- char c = *function;
- if(c != '+' && c != '-') break;
- ++function;
- SkipSpace(function);
- if(mData->mByteCode.back() == cImmed)
- {
- // 5 (...) cAdd --> (...) ||| 5 cAdd
- // 5 (...) cSub --> (...) cNeg ||| 5 cAdd
- // ^ | ^
- pending_immed += mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- --mStackPtr;
- function = CompileMult(function);
- if(!function) return 0;
- if(c == '-')
- AddFunctionOpcode(cNeg);
- continue;
- }
- if(mData->mByteCode.back() == cAdd
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) 5 cAdd (...) cAdd -> (:::) (...) cAdd ||| 5 cAdd
- // (:::) 5 cAdd (...) cSub -> (:::) (...) cSub ||| 5 cAdd
- // ^ ^
- pending_immed += mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- // cSub is not tested here because the bytecode
- // optimizer will convert this kind of cSubs into cAdds.
- bool lhs_negated = false;
- if(mData->mByteCode.back() == cNeg)
- {
- // (:::) cNeg (...) cAdd -> (:::) (...) cRSub
- // (:::) cNeg (...) cSub -> (:::) (...) cAdd cNeg
- // ^ ^ |
- mData->mByteCode.pop_back();
- lhs_negated = true;
- }
- function = CompileMult(function);
- if(!function) return 0;
- if(mData->mByteCode.back() == cAdd
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cAdd cAdd -> (:::) (...) cAdd ||| 5 Add
- // (:::) (...) 5 cAdd cSub -> (:::) (...) cSub ||| -5 Add
- // ^ ^
- if(c == '+')
- pending_immed += mData->mImmed.back();
- else
- pending_immed -= mData->mImmed.back();
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- else
- if(mData->mByteCode.back() == cRSub
- && mData->mByteCode[mData->mByteCode.size()-2] == cImmed)
- {
- // (:::) (...) 5 cRSub cAdd -> (:::) (...) cSub ||| 5 cAdd
- // (:::) (...) 5 cRSub cSub -> (:::) (...) cAdd ||| -5 cAdd
- // ^ ^
- if(c == '+')
- { c = '-'; pending_immed += mData->mImmed.back(); }
- else
- { c = '+'; pending_immed -= mData->mImmed.back(); }
- mData->mImmed.pop_back();
- mData->mByteCode.pop_back();
- mData->mByteCode.pop_back();
- }
- if(!lhs_negated) // if (-x-y) was changed to -(x+y), add missing cNeg
- {
- AddFunctionOpcode(c == '+' ? cAdd : cSub);
- --mStackPtr;
- }
- else if(c == '+') // (-x)+y -> rsub(x,y)
- {
- AddFunctionOpcode(cRSub);
- --mStackPtr;
- }
- else // (-x)-y -> -(x+y)
- {
- AddFunctionOpcode(cAdd);
- --mStackPtr;
- AddFunctionOpcode(cNeg);
- }
- }
- FP_FlushImmed(false);
- #undef FP_FlushImmed
- return function;
-}
-
-template<typename Value_t>
-inline const char*
-FunctionParserBase<Value_t>::CompileComparison(const char* function)
-{
- unsigned op=0;
- while(true)
- {
- function = CompileAddition(function);
- if(!function) return 0;
-
- if(op)
- {
- AddFunctionOpcode(op);
- --mStackPtr;
- }
- switch(*function)
- {
- case '=':
- ++function; op = cEqual; break;
- case '!':
- if(function[1] == '=')
- { function += 2; op = cNEqual; break; }
- // If '=' does not follow '!', a syntax error will
- // be generated at the outermost parsing level
- return function;
- case '<':
- if(function[1] == '=')
- { function += 2; op = cLessOrEq; break; }
- ++function; op = cLess; break;
- case '>':
- if(function[1] == '=')
- { function += 2; op = cGreaterOrEq; break; }
- ++function; op = cGreater; break;
- default: return function;
- }
- SkipSpace(function);
- }
- return function;
-}
-
-template<typename Value_t>
-inline const char* FunctionParserBase<Value_t>::CompileAnd(const char* function)
-{
- std::size_t param0end=0;
- while(true)
- {
- function = CompileComparison(function);
- if(!function) return 0;
-
- if(param0end)
- {
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
-
- AddFunctionOpcode(cAnd);
- --mStackPtr;
- }
- if(*function != '&') break;
- ++function;
- SkipSpace(function);
- param0end = mData->mByteCode.size();
- }
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::CompileExpression(const char* function)
-{
- std::size_t param0end=0;
- while(true)
- {
- SkipSpace(function);
- function = CompileAnd(function);
- if(!function) return 0;
-
- if(param0end)
- {
- if(mData->mByteCode.back() == cNotNot) mData->mByteCode.pop_back();
-
- AddFunctionOpcode(cOr);
- --mStackPtr;
- }
- if(*function != '|') break;
- ++function;
- param0end = mData->mByteCode.size();
- }
- return function;
-}
-
-template<typename Value_t>
-const char* FunctionParserBase<Value_t>::Compile(const char* function)
-{
- while(true)
- {
- // Check if an identifier appears as first token:
- SkipSpace(function);
- unsigned nameLength = readIdentifier<Value_t>(function);
- if(nameLength > 0 && !(nameLength & 0x80000000U))
- {
- typename Data::InlineVariable inlineVar =
- { NamePtr(function, nameLength), 0 };
-
- // Check if it's an unknown identifier:
- typename NamePtrsMap<Value_t>::iterator nameIter =
- mData->mNamePtrs.find(inlineVar.mName);
- if(nameIter == mData->mNamePtrs.end())
- {
- const char* function2 = function + nameLength;
- SkipSpace(function2);
-
- // Check if ":=" follows the unknown identifier:
- if(function2[0] == ':' && function2[1] == '=')
- {
- // Parse the expression that follows and create the
- // inline variable:
- function2 = CompileExpression(function2 + 2);
- if(!function2) return 0;
- if(*function2 != ';') return function2;
-
- inlineVar.mFetchIndex = mStackPtr - 1;
- mData->mInlineVarNames.push_back(inlineVar);
-
- // Continue with the expression after the ';':
- function = function2 + 1;
- continue;
- }
- }
- }
- break;
- }
-
- return CompileExpression(function);
-}
-
-template<typename Value_t> template<bool PutFlag>
-inline void FunctionParserBase<Value_t>::PushOpcodeParam
- (unsigned value)
-{
- mData->mByteCode.push_back(value | (PutFlag ? FP_ParamGuardMask : 0u));
- if(PutFlag) mData->mHasByteCodeFlags = true;
-}
-
-template<typename Value_t> template<bool PutFlag>
-inline void FunctionParserBase<Value_t>::PutOpcodeParamAt
- (unsigned value, unsigned offset)
-{
- mData->mByteCode[offset] = value | (PutFlag ? FP_ParamGuardMask : 0u);
- if(PutFlag) mData->mHasByteCodeFlags = true;
-}
-
-//===========================================================================
-// Function evaluation
-//===========================================================================
-template<typename Value_t>
-Value_t FunctionParserBase<Value_t>::Eval(const Value_t* Vars)
-{
- if(mData->mParseErrorType != FP_NO_ERROR) return Value_t(0);
-
- const unsigned* const byteCode = &(mData->mByteCode[0]);
- const Value_t* const immed = mData->mImmed.empty() ? 0 : &(mData->mImmed[0]);
- const unsigned byteCodeSize = unsigned(mData->mByteCode.size());
- unsigned IP, DP=0;
- int SP=-1;
-
-#ifdef FP_USE_THREAD_SAFE_EVAL
- /* If Eval() may be called by multiple threads simultaneously,
- * then Eval() must allocate its own stack.
- */
-#ifdef FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
- /* alloca() allocates room from the hardware stack.
- * It is automatically freed when the function returns.
- */
- Value_t* const Stack = (Value_t*)alloca(mData->mStackSize*sizeof(Value_t));
-#else
- /* Allocate from the heap. Ensure that it is freed
- * automatically no matter which exit path is taken.
- */
- struct AutoDealloc
- {
- Value_t* ptr;
- ~AutoDealloc() { delete[] ptr; }
- } AutoDeallocStack = { new Value_t[mData->mStackSize] };
- Value_t*& Stack = AutoDeallocStack.ptr;
-#endif
-#else
- /* No thread safety, so use a global stack. */
- std::vector<Value_t>& Stack = mData->mStack;
-#endif
-
- for(IP=0; IP<byteCodeSize; ++IP)
- {
- switch(byteCode[IP])
- {
-// Functions:
- case cAbs: Stack[SP] = fp_abs(Stack[SP]); break;
-
- case cAcos:
- if(IsComplexType<Value_t>::result == false
- && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_acos(Stack[SP]); break;
-
- case cAcosh:
- if(IsComplexType<Value_t>::result == false
- && Stack[SP] < Value_t(1))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_acosh(Stack[SP]); break;
-
- case cAsin:
- if(IsComplexType<Value_t>::result == false
- && (Stack[SP] < Value_t(-1) || Stack[SP] > Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_asin(Stack[SP]); break;
-
- case cAsinh: Stack[SP] = fp_asinh(Stack[SP]); break;
-
- case cAtan: Stack[SP] = fp_atan(Stack[SP]); break;
-
- case cAtan2: Stack[SP-1] = fp_atan2(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cAtanh:
- if(IsComplexType<Value_t>::result
- ? (Stack[SP] == Value_t(-1) || Stack[SP] == Value_t(1))
- : (Stack[SP] <= Value_t(-1) || Stack[SP] >= Value_t(1)))
- { mData->mEvalErrorType=4; return Value_t(0); }
- Stack[SP] = fp_atanh(Stack[SP]); break;
-
- case cCbrt: Stack[SP] = fp_cbrt(Stack[SP]); break;
-
- case cCeil: Stack[SP] = fp_ceil(Stack[SP]); break;
-
- case cCos: Stack[SP] = fp_cos(Stack[SP]); break;
-
- case cCosh: Stack[SP] = fp_cosh(Stack[SP]); break;
-
- case cCot:
- {
- const Value_t t = fp_tan(Stack[SP]);
- if(t == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/t; break;
- }
-
- case cCsc:
- {
- const Value_t s = fp_sin(Stack[SP]);
- if(s == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/s; break;
- }
-
-
- case cExp: Stack[SP] = fp_exp(Stack[SP]); break;
-
- case cExp2: Stack[SP] = fp_exp2(Stack[SP]); break;
-
- case cFloor: Stack[SP] = fp_floor(Stack[SP]); break;
-
- case cHypot:
- Stack[SP-1] = fp_hypot(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cIf:
- if(fp_truth(Stack[SP--]))
- IP += 2;
- else
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- }
- break;
-
- case cInt: Stack[SP] = fp_int(Stack[SP]); break;
-
- case cLog:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log(Stack[SP]); break;
-
- case cLog10:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log10(Stack[SP]);
- break;
-
- case cLog2:
- if(IsComplexType<Value_t>::result
- ? Stack[SP] == Value_t(0)
- : !(Stack[SP] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP] = fp_log2(Stack[SP]);
- break;
-
- case cMax: Stack[SP-1] = fp_max(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cMin: Stack[SP-1] = fp_min(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cPow:
- // x:Negative ^ y:NonInteger is failure,
- // except when the reciprocal of y forms an integer
- /*if(IsComplexType<Value_t>::result == false
- && Stack[SP-1] < Value_t(0) &&
- !isInteger(Stack[SP]) &&
- !isInteger(1.0 / Stack[SP]))
- { mEvalErrorType=3; return Value_t(0); }*/
- // x:0 ^ y:negative is failure
- if(Stack[SP-1] == Value_t(0) &&
- Stack[SP] < Value_t(0))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP-1] = fp_pow(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cTrunc: Stack[SP] = fp_trunc(Stack[SP]); break;
-
- case cSec:
- {
- const Value_t c = fp_cos(Stack[SP]);
- if(c == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/c; break;
- }
-
- case cSin: Stack[SP] = fp_sin(Stack[SP]); break;
-
- case cSinh: Stack[SP] = fp_sinh(Stack[SP]); break;
-
- case cSqrt:
- if(IsComplexType<Value_t>::result == false &&
- Stack[SP] < Value_t(0))
- { mData->mEvalErrorType=2; return Value_t(0); }
- Stack[SP] = fp_sqrt(Stack[SP]); break;
-
- case cTan: Stack[SP] = fp_tan(Stack[SP]); break;
-
- case cTanh: Stack[SP] = fp_tanh(Stack[SP]); break;
-
-
-// Misc:
- case cImmed: Stack[++SP] = immed[DP++]; break;
-
- case cJump:
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- break;
- }
-
-// Operators:
- case cNeg: Stack[SP] = -Stack[SP]; break;
- case cAdd: Stack[SP-1] += Stack[SP]; --SP; break;
- case cSub: Stack[SP-1] -= Stack[SP]; --SP; break;
- case cMul: Stack[SP-1] *= Stack[SP]; --SP; break;
-
- case cDiv:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] /= Stack[SP]; --SP; break;
-
- case cMod:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] = fp_mod(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cEqual:
- Stack[SP-1] = fp_equal(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cNEqual:
- Stack[SP-1] = fp_nequal(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cLess:
- Stack[SP-1] = fp_less(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cLessOrEq:
- Stack[SP-1] = fp_lessOrEq(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cGreater:
- Stack[SP-1] = fp_less(Stack[SP], Stack[SP-1]);
- --SP; break;
-
- case cGreaterOrEq:
- Stack[SP-1] = fp_lessOrEq(Stack[SP], Stack[SP-1]);
- --SP; break;
-
- case cNot: Stack[SP] = fp_not(Stack[SP]); break;
-
- case cNotNot: Stack[SP] = fp_notNot(Stack[SP]); break;
-
- case cAnd:
- Stack[SP-1] = fp_and(Stack[SP-1], Stack[SP]);
- --SP; break;
-
- case cOr:
- Stack[SP-1] = fp_or(Stack[SP-1], Stack[SP]);
- --SP; break;
-
-// Degrees-radians conversion:
- case cDeg: Stack[SP] = RadiansToDegrees(Stack[SP]); break;
- case cRad: Stack[SP] = DegreesToRadians(Stack[SP]); break;
-
-// User-defined function calls:
- case cFCall:
- {
- const unsigned index = byteCode[++IP];
- const unsigned params = mData->mFuncPtrs[index].mParams;
- const Value_t retVal =
- mData->mFuncPtrs[index].mRawFuncPtr ?
- mData->mFuncPtrs[index].mRawFuncPtr(&Stack[SP-params+1]) :
- mData->mFuncPtrs[index].mFuncWrapperPtr->callFunction
- (&Stack[SP-params+1]);
- SP -= int(params)-1;
- Stack[SP] = retVal;
- break;
- }
-
- case cPCall:
- {
- unsigned index = byteCode[++IP];
- unsigned params = mData->mFuncParsers[index].mParams;
- Value_t retVal =
- mData->mFuncParsers[index].mParserPtr->Eval
- (&Stack[SP-params+1]);
- SP -= int(params)-1;
- Stack[SP] = retVal;
- const int error =
- mData->mFuncParsers[index].mParserPtr->EvalError();
- if(error)
- {
- mData->mEvalErrorType = error;
- return 0;
- }
- break;
- }
-
-
- case cFetch:
- {
- unsigned stackOffs = byteCode[++IP];
- Stack[SP+1] = Stack[stackOffs]; ++SP;
- break;
- }
-
-#ifdef FP_SUPPORT_OPTIMIZER
- case cPopNMov:
- {
- unsigned stackOffs_target = byteCode[++IP];
- unsigned stackOffs_source = byteCode[++IP];
- Stack[stackOffs_target] = Stack[stackOffs_source];
- SP = stackOffs_target;
- break;
- }
-
- case cLog2by:
- if(IsComplexType<Value_t>::result
- ? Stack[SP-1] == Value_t(0)
- : !(Stack[SP-1] > Value_t(0)))
- { mData->mEvalErrorType=3; return Value_t(0); }
- Stack[SP-1] = fp_log2(Stack[SP-1]) * Stack[SP];
- --SP;
- break;
-
- case cNop: break;
-#endif // FP_SUPPORT_OPTIMIZER
-
- case cSinCos:
- fp_sinCos(Stack[SP], Stack[SP+1], Stack[SP]);
- ++SP;
- break;
- case cSinhCosh:
- fp_sinhCosh(Stack[SP], Stack[SP+1], Stack[SP]);
- ++SP;
- break;
-
- case cAbsNot:
- Stack[SP] = fp_absNot(Stack[SP]); break;
- case cAbsNotNot:
- Stack[SP] = fp_absNotNot(Stack[SP]); break;
- case cAbsAnd:
- Stack[SP-1] = fp_absAnd(Stack[SP-1], Stack[SP]);
- --SP; break;
- case cAbsOr:
- Stack[SP-1] = fp_absOr(Stack[SP-1], Stack[SP]);
- --SP; break;
- case cAbsIf:
- if(fp_absTruth(Stack[SP--]))
- IP += 2;
- else
- {
- const unsigned* buf = &byteCode[IP+1];
- IP = buf[0];
- DP = buf[1];
- }
- break;
-
- case cDup: Stack[SP+1] = Stack[SP]; ++SP; break;
-
- case cInv:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1)/Stack[SP];
- break;
-
- case cSqr:
- Stack[SP] = Stack[SP]*Stack[SP];
- break;
-
- case cRDiv:
- if(Stack[SP-1] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP-1] = Stack[SP] / Stack[SP-1]; --SP; break;
-
- case cRSub: Stack[SP-1] = Stack[SP] - Stack[SP-1]; --SP; break;
-
- case cRSqrt:
- if(Stack[SP] == Value_t(0))
- { mData->mEvalErrorType=1; return Value_t(0); }
- Stack[SP] = Value_t(1) / fp_sqrt(Stack[SP]); break;
-
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
- case cReal: Stack[SP] = fp_real(Stack[SP]); break;
- case cImag: Stack[SP] = fp_imag(Stack[SP]); break;
- case cArg: Stack[SP] = fp_arg(Stack[SP]); break;
- case cConj: Stack[SP] = fp_conj(Stack[SP]); break;
- case cPolar:
- Stack[SP-1] = fp_polar(Stack[SP-1], Stack[SP]);
- --SP; break;
-#endif
-
-
-// Variables:
- default:
- Stack[++SP] = Vars[byteCode[IP]-VarBegin];
- }
- }
-
- mData->mEvalErrorType=0;
- return Stack[SP];
-}
-
-
-//===========================================================================
-// Variable deduction
-//===========================================================================
-namespace
-{
- template<typename Value_t>
- int deduceVariables(FunctionParserBase<Value_t>& fParser,
- const char* funcStr,
- std::string& destVarString,
- int* amountOfVariablesFound,
- std::vector<std::string>* destVarNames,
- bool useDegrees)
- {
- typedef std::set<std::string> StrSet;
- StrSet varNames;
-
- int oldIndex = -1;
-
- while(true)
- {
- destVarString.clear();
- for(StrSet::iterator iter = varNames.begin();
- iter != varNames.end();
- ++iter)
- {
- if(iter != varNames.begin()) destVarString += ",";
- destVarString += *iter;
- }
-
- const int index =
- fParser.Parse(funcStr, destVarString, useDegrees);
- if(index < 0) break;
- if(index == oldIndex) return index;
-
- unsigned nameLength = readIdentifier<Value_t>(funcStr + index);
- if(nameLength & 0x80000000U) return index;
- if(nameLength == 0) return index;
-
- varNames.insert(std::string(funcStr + index, nameLength));
- oldIndex = index;
- }
-
- if(amountOfVariablesFound)
- *amountOfVariablesFound = int(varNames.size());
-
- if(destVarNames)
- destVarNames->assign(varNames.begin(), varNames.end());
-
- return -1;
- }
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- int* amountOfVariablesFound,
- bool useDegrees)
-{
- std::string varString;
- return deduceVariables(*this, function.c_str(), varString,
- amountOfVariablesFound, 0, useDegrees);
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound,
- bool useDegrees)
-{
- std::string varString;
- const int index =
- deduceVariables(*this, function.c_str(), varString,
- amountOfVariablesFound, 0, useDegrees);
- if(index < 0) resultVarString = varString;
- return index;
-}
-
-template<typename Value_t>
-int FunctionParserBase<Value_t>::ParseAndDeduceVariables
-(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees)
-{
- std::string varString;
- std::vector<std::string> vars;
- const int index =
- deduceVariables(*this, function.c_str(), varString,
- 0, &vars, useDegrees);
- if(index < 0) resultVars.swap(vars);
- return index;
-}
-
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-//===========================================================================
-// Bytecode injection
-//===========================================================================
-template<typename Value_t>
-void FunctionParserBase<Value_t>::InjectRawByteCode
-(const unsigned* bytecode, unsigned bytecodeAmount,
- const Value_t* immed, unsigned immedAmount, unsigned stackSize)
-{
- CopyOnWrite();
-
- mData->mByteCode.assign(bytecode, bytecode + bytecodeAmount);
- mData->mImmed.assign(immed, immed + immedAmount);
- mData->mStackSize = stackSize;
-
-#ifndef FP_USE_THREAD_SAFE_EVAL
- mData->mStack.resize(stackSize);
-#endif
-}
-
-//===========================================================================
-// Debug output
-//===========================================================================
-#include <iomanip>
-#include <sstream>
-namespace
-{
- inline void printHex(std::ostream& dest, unsigned n)
- {
- std::ios::fmtflags flags = dest.flags();
- dest.width(4); dest.fill('0'); std::hex(dest); //uppercase(dest);
- dest << n;
- dest.flags(flags);
- }
-
- void padLine(std::ostringstream& dest, unsigned destLength)
- {
- for(std::size_t currentLength = dest.str().length();
- currentLength < destLength;
- ++currentLength)
- {
- dest << ' ';
- }
- }
-
- const struct PowiMuliType
- {
- unsigned opcode_square;
- unsigned opcode_cumulate;
- unsigned opcode_invert;
- unsigned opcode_half;
- unsigned opcode_invhalf;
- } iseq_powi = {cSqr,cMul,cInv,cSqrt,cRSqrt},
- iseq_muli = {~unsigned(0), cAdd,cNeg, ~unsigned(0),~unsigned(0) };
-
- template<typename Value_t>
- Value_t ParsePowiMuli(
- const PowiMuliType& opcodes,
- const std::vector<unsigned>& ByteCode, unsigned& IP,
- unsigned limit,
- std::size_t factor_stack_base,
- std::vector<Value_t>& stack,
- bool IgnoreExcess)
- {
- Value_t result = Value_t(1);
- while(IP < limit)
- {
- if(ByteCode[IP] == opcodes.opcode_square)
- {
- if(!isInteger(result)) break;
- result *= Value_t(2);
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_invert)
- {
- if(result < Value_t(0)) break;
- result = -result;
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_half)
- {
- if(result > Value_t(0) && isEvenInteger(result))
- break;
- if(isInteger(result * Value_t(0.5))) break;
- result *= Value_t(0.5);
- ++IP;
- continue;
- }
- if(ByteCode[IP] == opcodes.opcode_invhalf)
- {
- if(result > Value_t(0) && isEvenInteger(result))
- break;
- if(isInteger(result * Value_t(-0.5))) break;
- result *= Value_t(-0.5);
- ++IP;
- continue;
- }
-
- unsigned dup_fetch_pos = IP;
- Value_t lhs = Value_t(1);
-
- if(ByteCode[IP] == cFetch)
- {
- unsigned index = ByteCode[++IP];
- if(index < factor_stack_base
- || std::size_t(index-factor_stack_base) >= stack.size())
- {
- // It wasn't a powi-fetch after all
- IP = dup_fetch_pos;
- break;
- }
- lhs = stack[index - factor_stack_base];
- // Note: ^This assumes that cFetch of recentmost
- // is always converted into cDup.
- goto dup_or_fetch;
- }
-
- if(ByteCode[IP] == cDup)
- {
- lhs = result;
- goto dup_or_fetch;
-
- dup_or_fetch:
- stack.push_back(result);
- ++IP;
- Value_t subexponent = ParsePowiMuli
- (opcodes,
- ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- if(IP >= limit && IgnoreExcess)
- return lhs*subexponent;
- if(IP >= limit || ByteCode[IP] != opcodes.opcode_cumulate)
- {
- // It wasn't a powi-dup after all
- IP = dup_fetch_pos;
- break;
- }
- ++IP; // skip opcode_cumulate
- stack.pop_back();
- result += lhs*subexponent;
- continue;
- }
- break;
- }
- return result;
- }
-
- template<typename Value_t>
- Value_t ParsePowiSequence(const std::vector<unsigned>& ByteCode,
- unsigned& IP, unsigned limit,
- std::size_t factor_stack_base,
- bool IgnoreExcess = false)
- {
- std::vector<Value_t> stack;
- stack.push_back(Value_t(1));
- return ParsePowiMuli(iseq_powi, ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- }
-
- template<typename Value_t>
- Value_t ParseMuliSequence(const std::vector<unsigned>& ByteCode,
- unsigned& IP, unsigned limit,
- std::size_t factor_stack_base,
- bool IgnoreExcess = false)
- {
- std::vector<Value_t> stack;
- stack.push_back(Value_t(1));
- return ParsePowiMuli(iseq_muli, ByteCode, IP, limit,
- factor_stack_base, stack,
- IgnoreExcess);
- }
-
- struct IfInfo
- {
- std::pair<int,std::string> condition;
- std::pair<int,std::string> thenbranch;
- unsigned endif_location;
-
- IfInfo() : condition(), thenbranch(), endif_location() { }
- };
-}
-
-template<typename Value_t>
-void FunctionParserBase<Value_t>::PrintByteCode(std::ostream& dest,
- bool showExpression) const
-{
- dest << "Size of stack: " << mData->mStackSize << "\n";
-
- std::ostringstream outputBuffer;
- std::ostream& output = (showExpression ? outputBuffer : dest);
-
- const std::vector<unsigned>& ByteCode = mData->mByteCode;
- const std::vector<Value_t>& Immed = mData->mImmed;
-
- std::vector<std::pair<int,std::string> > stack;
- std::vector<IfInfo> if_stack;
-
- for(unsigned IP = 0, DP = 0; IP <= ByteCode.size(); ++IP)
- {
- after_powi_or_muli:;
- std::string n;
- bool out_params = false;
- unsigned params = 2, produces = 1, opcode = 0;
-
- if(showExpression && !if_stack.empty() &&
- ( // Normal If termination rule:
- if_stack.back().endif_location == IP
- // This rule matches when cJumps are threaded:
- || (IP < ByteCode.size() && ByteCode[IP] == cJump
- && !if_stack.back().thenbranch.second.empty())
- ))
- {
- printHex(output, IP);
- if(if_stack.back().endif_location == IP)
- output << ": ----- (phi)";
- else
- output << ": ----- (phi+)";
-
- stack.resize(stack.size()+2);
- std::swap(stack[stack.size()-3], stack[stack.size()-1]);
- std::swap(if_stack.back().condition, stack[stack.size()-3]);
- std::swap(if_stack.back().thenbranch, stack[stack.size()-2]);
- opcode = cIf;
- params = 3;
- --IP;
- if_stack.pop_back();
- }
- else
- {
- if(IP >= ByteCode.size()) break;
- opcode = ByteCode[IP];
-
- if(showExpression && (
- opcode == cSqr || opcode == cDup
- || opcode == cInv
- || opcode == cSqrt || opcode == cRSqrt
- || opcode == cFetch
- ))
- {
- unsigned changed_ip = IP;
- Value_t exponent =
- ParsePowiSequence<Value_t>
- (ByteCode, changed_ip,
- if_stack.empty()
- ? (unsigned)ByteCode.size()
- : if_stack.back().endif_location,
- stack.size()-1);
- std::string operation_prefix;
- std::ostringstream operation_value;
- int prio = 0;
- if(exponent == Value_t(1.0))
- {
- if(opcode != cDup) goto not_powi_or_muli;
- Value_t factor =
- ParseMuliSequence<Value_t>
- (ByteCode, changed_ip,
- if_stack.empty()
- ? (unsigned)ByteCode.size()
- : if_stack.back().endif_location,
- stack.size()-1);
- if(factor == Value_t(1) || factor == Value_t(-1))
- goto not_powi_or_muli;
- operation_prefix = "*";
- operation_value << factor;
- prio = 3;
- }
- else
- {
- prio = 2;
- operation_prefix = "^";
- operation_value << exponent;
- }
-
- //unsigned explanation_before = changed_ip-2;
- unsigned explanation_before = changed_ip-1;
-
- const char* explanation_prefix = "_";
- for(const unsigned first_ip = IP; IP < changed_ip; ++IP)
- {
- printHex(output, IP);
- output << ": ";
-
- const char* sep = "|";
- if(first_ip+1 == changed_ip)
- { sep = "="; explanation_prefix = " "; }
- else if(IP == first_ip) sep = "\\";
- else if(IP+1 == changed_ip) sep = "/";
- else explanation_prefix = "=";
-
- switch(ByteCode[IP])
- {
- case cInv: output << "inv"; break;
- case cNeg: output << "neg"; break;
- case cDup: output << "dup"; break;
- case cSqr: output << "sqr"; break;
- case cMul: output << "mul"; break;
- case cAdd: output << "add"; break;
- case cCbrt: output << "cbrt"; break;
- case cSqrt: output << "sqrt"; break;
- case cRSqrt: output << "rsqrt"; break;
- case cFetch:
- {
- unsigned index = ByteCode[++IP];
- output << "cFetch(" << index << ")";
- break;
- }
- default: break;
- }
- padLine(outputBuffer, 20);
- output << sep;
- if(IP >= explanation_before)
- {
- explanation_before = (unsigned)ByteCode.size();
- output << explanation_prefix
- << '[' << (stack.size()-1) << ']';
- std::string last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- output << last;
- output << operation_prefix;
- output << operation_value.str();
- }
- else
- {
- unsigned p = first_ip;
- Value_t exp = operation_prefix=="^" ?
- ParsePowiSequence<Value_t>
- (ByteCode, p, IP+1, stack.size()-1, true) :
- ParseMuliSequence<Value_t>
- (ByteCode, p, IP+1, stack.size()-1, true);
- std::string last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- output << " ..." << last;
- output << operation_prefix;
- output << exp;
- }
- dest << outputBuffer.str() << std::endl;
- outputBuffer.str("");
- }
-
- std::string& last = stack.back().second;
- if(stack.back().first >= prio)
- last = "(" + last + ")";
- last += operation_prefix;
- last += operation_value.str();
- stack.back().first = prio;
-
- goto after_powi_or_muli;
- }
- not_powi_or_muli:;
- printHex(output, IP);
- output << ": ";
-
- switch(opcode)
- {
- case cIf:
- {
- unsigned label = ByteCode[IP+1]+1;
- output << "jz ";
- printHex(output, label);
- params = 1;
- produces = 0;
- IP += 2;
-
- if_stack.resize(if_stack.size() + 1);
- std::swap( if_stack.back().condition, stack.back() );
- if_stack.back().endif_location = (unsigned) ByteCode.size();
- stack.pop_back();
- break;
- }
- case cAbsIf:
- {
- unsigned dp = ByteCode[IP+2];
- unsigned label = ByteCode[IP+1]+1;
- output << "jz_abs " << dp << ",";
- printHex(output, label);
- params = 1;
- produces = 0;
- IP += 2;
-
- if_stack.resize(if_stack.size() + 1);
- std::swap( if_stack.back().condition, stack.back() );
- if_stack.back().endif_location = (unsigned) ByteCode.size();
- stack.pop_back();
- break;
- }
-
- case cJump:
- {
- unsigned dp = ByteCode[IP+2];
- unsigned label = ByteCode[IP+1]+1;
-
- if(!if_stack.empty() && !stack.empty())
- {
- std::swap(if_stack.back().thenbranch, stack.back());
- if_stack.back().endif_location = label;
- stack.pop_back();
- }
-
- output << "jump " << dp << ",";
- printHex(output, label);
- params = 0;
- produces = 0;
- IP += 2;
- break;
- }
- case cImmed:
- {
- if(showExpression)
- {
- std::ostringstream buf;
- buf.precision(8);
- buf << Immed[DP];
- stack.push_back( std::make_pair(0, buf.str()) );
- }
- output.precision(8);
- output << "push " << Immed[DP];
- ++DP;
- produces = 0;
- break;
- }
-
- case cFCall:
- {
- const unsigned index = ByteCode[++IP];
- params = mData->mFuncPtrs[index].mParams;
- static std::string name;
- name = "f:" + findName(mData->mNamePtrs, index,
- NameData<Value_t>::FUNC_PTR);
- n = name.c_str();
- out_params = true;
- break;
- }
-
- case cPCall:
- {
- const unsigned index = ByteCode[++IP];
- params = mData->mFuncParsers[index].mParams;
- static std::string name;
- name = "p:" + findName(mData->mNamePtrs, index,
- NameData<Value_t>::PARSER_PTR);
- n = name.c_str();
- out_params = true;
- break;
- }
-
- default:
- if(IsVarOpcode(opcode))
- {
- if(showExpression)
- {
- stack.push_back(std::make_pair(0,
- (findName(mData->mNamePtrs, opcode,
- NameData<Value_t>::VARIABLE))));
- }
- output << "push Var" << opcode-VarBegin;
- produces = 0;
- }
- else
- {
- switch(OPCODE(opcode))
- {
- case cNeg: n = "neg"; params = 1; break;
- case cAdd: n = "add"; break;
- case cSub: n = "sub"; break;
- case cMul: n = "mul"; break;
- case cDiv: n = "div"; break;
- case cMod: n = "mod"; break;
- case cPow: n = "pow"; break;
- case cEqual: n = "eq"; break;
- case cNEqual: n = "neq"; break;
- case cLess: n = "lt"; break;
- case cLessOrEq: n = "le"; break;
- case cGreater: n = "gt"; break;
- case cGreaterOrEq: n = "ge"; break;
- case cAnd: n = "and"; break;
- case cOr: n = "or"; break;
- case cNot: n = "not"; params = 1; break;
- case cNotNot: n = "notnot"; params = 1; break;
- case cDeg: n = "deg"; params = 1; break;
- case cRad: n = "rad"; params = 1; break;
-
- case cFetch:
- {
- unsigned index = ByteCode[++IP];
- if(showExpression && index < stack.size())
- stack.push_back(stack[index]);
- output << "cFetch(" << index << ")";
- produces = 0;
- break;
- }
- #ifdef FP_SUPPORT_OPTIMIZER
- case cLog2by: n = "log2by"; params = 2; out_params = 1; break;
- case cPopNMov:
- {
- std::size_t a = ByteCode[++IP];
- std::size_t b = ByteCode[++IP];
- if(showExpression && b < stack.size())
- {
- std::pair<int, std::string> stacktop(0, "?");
- if(b < stack.size()) stacktop = stack[b];
- stack.resize(a);
- stack.push_back(stacktop);
- }
- output << "cPopNMov(" << a << ", " << b << ")";
- produces = 0;
- break;
- }
- case cNop:
- output << "nop"; params = 0; produces = 0;
- break;
- #endif
- case cSinCos:
- {
- if(showExpression)
- {
- std::pair<int, std::string> sin = stack.back();
- std::pair<int, std::string> cos(
- 0, "cos(" + sin.second + ")");
- sin.first = 0;
- sin.second = "sin(" + sin.second + ")";
- stack.back() = sin;
- stack.push_back(cos);
- }
- output << "sincos";
- produces = 0;
- break;
- }
- case cSinhCosh:
- {
- if(showExpression)
- {
- std::pair<int, std::string> sinh = stack.back();
- std::pair<int, std::string> cosh(
- 0, "cosh(" + sinh.second + ")");
- sinh.first = 0;
- sinh.second = "sinh(" + sinh.second + ")";
- stack.back() = sinh;
- stack.push_back(cosh);
- }
- output << "sinhcosh";
- produces = 0;
- break;
- }
- case cAbsAnd: n = "abs_and"; break;
- case cAbsOr: n = "abs_or"; break;
- case cAbsNot: n = "abs_not"; params = 1; break;
- case cAbsNotNot: n = "abs_notnot"; params = 1; break;
- case cDup:
- {
- if(showExpression)
- stack.push_back(stack.back());
- output << "dup";
- produces = 0;
- break;
- }
- case cInv: n = "inv"; params = 1; break;
- case cSqr: n = "sqr"; params = 1; break;
- case cRDiv: n = "rdiv"; break;
- case cRSub: n = "rsub"; break;
- case cRSqrt: n = "rsqrt"; params = 1; break;
-
- default:
- n = Functions[opcode-cAbs].name;
- params = Functions[opcode-cAbs].params;
- out_params = params != 1;
- }
- }
- }
- }
- if(produces) output << n;
- if(out_params) output << " (" << params << ")";
- if(showExpression)
- {
- padLine(outputBuffer, 20);
-
- if(produces > 0)
- {
- std::ostringstream buf;
- const char *paramsep = ",", *suff = "";
- int prio = 0; bool commutative = false;
- switch(opcode)
- {
- case cIf: buf << "if("; suff = ")";
- break;
- case cAbsIf: buf << "if("; suff = ")";
- break;
- case cOr: prio = 6; paramsep = "|"; commutative = true;
- break;
- case cAnd: prio = 5; paramsep = "&"; commutative = true;
- break;
- case cAdd: prio = 4; paramsep = "+"; commutative = true;
- break;
- case cSub: prio = 4; paramsep = "-";
- break;
- case cMul: prio = 3; paramsep = "*"; commutative = true;
- break;
- case cDiv: prio = 3; paramsep = "/";
- break;
- case cPow: prio = 2; paramsep = "^";
- break;
- case cAbsOr: prio = 6; paramsep = "|"; commutative = true;
- break;
- case cAbsAnd: prio = 5; paramsep = "&"; commutative = true;
- break;
- case cSqr: prio = 2; suff = "^2";
- break;
- case cNeg: buf << "(-("; suff = "))";
- break;
- case cNot: buf << "(!("; suff = "))";
- break;
- default: buf << n << '('; suff = ")";
- }
-
- const char* sep = "";
- for(unsigned a=0; a<params; ++a)
- {
- buf << sep;
- if(stack.size() + a < params)
- buf << "?";
- else
- {
- const std::pair<int,std::string>& prev =
- stack[stack.size() - params + a];
- if(prio > 0 && (prev.first > prio ||
- (prev.first==prio && !commutative)))
- buf << '(' << prev.second << ')';
- else
- buf << prev.second;
- }
- sep = paramsep;
- }
- if(stack.size() >= params)
- stack.resize(stack.size() - params);
- else
- stack.clear();
- buf << suff;
- stack.push_back(std::make_pair(prio, buf.str()));
- //if(n.size() <= 4 && !out_params) padLine(outputBuffer, 20);
- }
- //padLine(outputBuffer, 20);
- output << "= ";
- if(((opcode == cIf || opcode == cAbsIf) && params != 3)
- || opcode == cJump
- #ifdef FP_SUPPORT_OPTIMIZER
- || opcode == cNop
- #endif
- )
- output << "(void)";
- else if(stack.empty())
- output << "[?] ?";
- else
- output << '[' << (stack.size()-1) << ']'
- << stack.back().second;
- }
-
- if(showExpression)
- {
- dest << outputBuffer.str() << std::endl;
- outputBuffer.str("");
- }
- else
- output << std::endl;
- }
- dest << std::flush;
-}
-#endif
-
-
-#ifndef FP_SUPPORT_OPTIMIZER
-template<typename Value_t>
-void FunctionParserBase<Value_t>::Optimize()
-{
- // Do nothing if no optimizations are supported.
-}
-#endif
-
-
-#define FUNCTIONPARSER_INSTANTIATE_CLASS(type) \
- template class FunctionParserBase< type >;
-
-#ifndef FP_DISABLE_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(double)
-#endif
-
-#ifdef FP_SUPPORT_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(float)
-#endif
-
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(long double)
-#endif
-
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(long)
-#endif
-
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(MpfrFloat)
-#endif
-
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(GmpInt)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<double>)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<float>)
-#endif
-
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-FUNCTIONPARSER_INSTANTIATE_CLASS(std::complex<long double>)
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen, Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_H_
-#define ONCE_FPARSER_H_
-
-#include <string>
-#include <vector>
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-#include <iostream>
-#endif
-
-#ifdef _MSC_VER
-// Visual Studio's warning about missing definitions for the explicit
-// FunctionParserBase instantiations is irrelevant here.
-#pragma warning(disable : 4661)
-#endif
-
-namespace FPoptimizer_CodeTree { template<typename Value_t> class CodeTree; }
-
-template<typename Value_t>
-class FunctionParserBase
-{
- public:
- enum ParseErrorType
- {
- SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH,
- EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS,
- ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC,
- UNKNOWN_IDENTIFIER,
- NO_FUNCTION_PARSED_YET,
- FP_NO_ERROR
- };
-
- typedef Value_t value_type;
-
-
- int Parse(const char* Function, const std::string& Vars,
- bool useDegrees = false);
- int Parse(const std::string& Function, const std::string& Vars,
- bool useDegrees = false);
-
- void setDelimiterChar(char);
-
- static Value_t epsilon();
- static void setEpsilon(Value_t);
-
- const char* ErrorMsg() const;
- ParseErrorType GetParseErrorType() const;
-
- Value_t Eval(const Value_t* Vars);
- int EvalError() const;
-
- bool AddConstant(const std::string& name, Value_t value);
- bool AddUnit(const std::string& name, Value_t value);
-
- typedef Value_t (*FunctionPtr)(const Value_t*);
-
- bool AddFunction(const std::string& name,
- FunctionPtr, unsigned paramsAmount);
- bool AddFunction(const std::string& name, FunctionParserBase&);
-
- class FunctionWrapper;
-
- template<typename DerivedWrapper>
- bool AddFunctionWrapper(const std::string& name, const DerivedWrapper&,
- unsigned paramsAmount);
-
- FunctionWrapper* GetFunctionWrapper(const std::string& name);
-
- bool RemoveIdentifier(const std::string& name);
-
- void Optimize();
-
-
- int ParseAndDeduceVariables(const std::string& function,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
- int ParseAndDeduceVariables(const std::string& function,
- std::string& resultVarString,
- int* amountOfVariablesFound = 0,
- bool useDegrees = false);
- int ParseAndDeduceVariables(const std::string& function,
- std::vector<std::string>& resultVars,
- bool useDegrees = false);
-
-
- FunctionParserBase();
- ~FunctionParserBase();
-
- // Copy constructor and assignment operator (implemented using the
- // copy-on-write technique for efficiency):
- FunctionParserBase(const FunctionParserBase&);
- FunctionParserBase& operator=(const FunctionParserBase&);
-
-
- void ForceDeepCopy();
-
-
-
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
- // For debugging purposes only.
- // Performs no sanity checks or anything. If the values are wrong, the
- // library will crash. Do not use unless you know what you are doing.
- void InjectRawByteCode(const unsigned* bytecode, unsigned bytecodeAmount,
- const Value_t* immed, unsigned immedAmount,
- unsigned stackSize);
-
- void PrintByteCode(std::ostream& dest, bool showExpression = true) const;
-#endif
-
-
-
-//========================================================================
- protected:
-//========================================================================
- // A derived class can implement its own evaluation logic by using
- // the parser data (found in fptypes.hh).
- struct Data;
- Data* getParserData();
-
-
-//========================================================================
- private:
-//========================================================================
-
- friend class FPoptimizer_CodeTree::CodeTree<Value_t>;
-
-// Private data:
-// ------------
- Data* mData;
- unsigned mStackPtr;
-
-
-// Private methods:
-// ---------------
- void CopyOnWrite();
- bool CheckRecursiveLinking(const FunctionParserBase*) const;
- bool NameExists(const char*, unsigned);
- bool ParseVariables(const std::string&);
- int ParseFunction(const char*, bool);
- const char* SetErrorType(ParseErrorType, const char*);
-
- void AddFunctionOpcode(unsigned);
- void AddImmedOpcode(Value_t v);
- void incStackPtr();
- void CompilePowi(long);
- bool TryCompilePowi(Value_t);
-
- const char* CompileIf(const char*);
- const char* CompileFunctionParams(const char*, unsigned);
- const char* CompileElement(const char*);
- const char* CompilePossibleUnit(const char*);
- const char* CompilePow(const char*);
- const char* CompileUnaryMinus(const char*);
- const char* CompileMult(const char*);
- const char* CompileAddition(const char*);
- const char* CompileComparison(const char*);
- const char* CompileAnd(const char*);
- const char* CompileExpression(const char*);
- inline const char* CompileFunction(const char*, unsigned);
- inline const char* CompileParenthesis(const char*);
- inline const char* CompileLiteral(const char*);
- template<bool SetFlag>
- inline void PushOpcodeParam(unsigned);
- template<bool SetFlag>
- inline void PutOpcodeParamAt(unsigned, unsigned offset);
- const char* Compile(const char*);
-
- bool addFunctionWrapperPtr(const std::string&, FunctionWrapper*, unsigned);
- static void incFuncWrapperRefCount(FunctionWrapper*);
- static unsigned decFuncWrapperRefCount(FunctionWrapper*);
-
-protected:
- // Parsing utility functions
- static std::pair<const char*, Value_t> ParseLiteral(const char*);
- static unsigned ParseIdentifier(const char*);
-};
-
-class FunctionParser: public FunctionParserBase<double> {};
-class FunctionParser_f: public FunctionParserBase<float> {};
-class FunctionParser_ld: public FunctionParserBase<long double> {};
-class FunctionParser_li: public FunctionParserBase<long> {};
-
-#include <complex>
-class FunctionParser_cd: public FunctionParserBase<std::complex<double> > {};
-class FunctionParser_cf: public FunctionParserBase<std::complex<float> > {};
-class FunctionParser_cld: public FunctionParserBase<std::complex<long double> > {};
-
-
-
-template<typename Value_t>
-class FunctionParserBase<Value_t>::FunctionWrapper
-{
- unsigned mReferenceCount;
- friend class FunctionParserBase<Value_t>;
-
- public:
- FunctionWrapper(): mReferenceCount(1) {}
- FunctionWrapper(const FunctionWrapper&): mReferenceCount(1) {}
- virtual ~FunctionWrapper() {}
- FunctionWrapper& operator=(const FunctionWrapper&) { return *this; }
-
- virtual Value_t callFunction(const Value_t*) = 0;
-};
-
-template<typename Value_t>
-template<typename DerivedWrapper>
-bool FunctionParserBase<Value_t>::AddFunctionWrapper
-(const std::string& name, const DerivedWrapper& wrapper, unsigned paramsAmount)
-{
- return addFunctionWrapperPtr
- (name, new DerivedWrapper(wrapper), paramsAmount);
-}
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_GMPINT_H_
-#define ONCE_FPARSER_GMPINT_H_
-
-#include "fparser.hh"
-#include "mpfr/GmpInt.hh"
-
-class FunctionParser_gmpint: public FunctionParserBase<GmpInt> {};
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-\***************************************************************************/
-
-#ifndef ONCE_FPARSER_MPFR_H_
-#define ONCE_FPARSER_MPFR_H_
-
-#include "fparser.hh"
-#include "mpfr/MpfrFloat.hh"
-
-class FunctionParser_mpfr: public FunctionParserBase<MpfrFloat> {};
-
-#endif
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Juha Nieminen *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-// Configuration file
-// ------------------
-
-/* NOTE:
- This file is for the internal use of the function parser only.
- You don't need to include this file in your source files, just
- include "fparser.hh".
-*/
-
-
-/* Uncomment any of these lines or define them in your compiler settings
- to enable the correspondent version of the parser. (These are disabled
- by default because they rely on C99 functions, and non-standard libraries
- in the case pf MPFR and GMP, and they make compiling needlessly slower
- and the resulting binary needlessly larger if they are not used in the
- program.)
-*/
-//#define FP_SUPPORT_FLOAT_TYPE
-//#define FP_SUPPORT_LONG_DOUBLE_TYPE
-//#define FP_SUPPORT_LONG_INT_TYPE
-//#define FP_SUPPORT_MPFR_FLOAT_TYPE
-//#define FP_SUPPORT_GMP_INT_TYPE
-//#define FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-//#define FP_SUPPORT_COMPLEX_FLOAT_TYPE
-//#define FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-
-/* If you are using FunctionParser_ld or FunctionParser_cld and your compiler
- supports the strtold() function, you should uncomment the following line.
- */
-//#define FP_USE_STRTOLD
-
-
-/* Uncomment this line or define it in your compiler settings if you want
- to disable compiling the basic double version of the library, in case
- one of the above types is used but not the double type. (If the double
- type is not used, then disabling it makes compiling faster and the
- resulting binary smaller.)
- */
-//#define FP_DISABLE_DOUBLE_TYPE
-
-/* Uncomment this line or define it in your compiler settings to make the
- parser use C++11 math functions. (Note that these may not be supported
- by all compilers.)
-*/
-//#define FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS
-
-/*
- Whether to use shortcut evaluation for the & and | operators:
-*/
-#ifndef FP_DISABLE_SHORTCUT_LOGICAL_EVALUATION
-#define FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#endif
-
-/*
- Comment out the following lines out if you are not going to use the
- optimizer and want a slightly smaller library. The Optimize() method
- can still be called, but it will not do anything.
- If you are unsure, just leave it. It won't slow down the other parts of
- the library.
-*/
-#ifndef FP_NO_SUPPORT_OPTIMIZER
-#define FP_SUPPORT_OPTIMIZER
-#endif
-
-#if defined(FP_SUPPORT_COMPLEX_DOUBLE_TYPE) || defined(FP_SUPPORT_COMPLEX_FLOAT_TYPE) || defined(FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE)
-#define FP_SUPPORT_COMPLEX_NUMBERS
-#endif
-
-
-/*
- No member function of FunctionParser is thread-safe. Most prominently,
- Eval() is not thread-safe. By uncommenting one of these lines the Eval()
- function can be made thread-safe at the cost of a possible small overhead.
- The second version requires that the compiler supports the alloca() function,
- which is not standard, but is faster.
- */
-//#define FP_USE_THREAD_SAFE_EVAL
-//#define FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA
+++ /dev/null
-/***************************************************************************\
-|* Function Parser for C++ v4.5.1 *|
-|*-------------------------------------------------------------------------*|
-|* Function optimizer *|
-|*-------------------------------------------------------------------------*|
-|* Copyright: Joel Yliluoma *|
-|* *|
-|* This library is distributed under the terms of the *|
-|* GNU Lesser General Public License version 3. *|
-|* (See lgpl.txt and gpl.txt for the license text.) *|
-\***************************************************************************/
-
-/* NOTE:
- This file contains generated code (from the optimizer sources) and is
- not intended to be modified by hand. If you want to modify the optimizer,
- download the development version of the library.
-*/
-
-#include <algorithm>
-#include <assert.h>
-#include <cctype>
-#include <iostream>
-#include <limits>
-#include <list>
-#include <map>
-#include <set>
-#include <sstream>
-#include <stdint.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "fpconfig.hh"
-#ifdef FP_SUPPORT_OPTIMIZER
-#include "fparser.hh"
-#include "extrasrc/fptypes.hh"
-#include "extrasrc/fpaux.hh"
-#define l14 {Value_t
-#define l04 ),info,
-#define iZ3 {data->
-#define iY3 ==cNot||
-#define iX3 "Found "
-#define iW3 info.lQ[b
-#define iV3 ;o<<"\n";
-#define iU3 )yR 2,cPow
-#define iT3 ;}static yU1
-#define iS3 (tree)!=
-#define iR3 ),Value(
-#define iQ3 stackpos
-#define iP3 minValue0
-#define iO3 "dup(%u) "
-#define iN3 =true;iO1
-#define iM3 eR{assert
-#define iL3 "%d, cost "
-#define iK3 "PUSH " iL2
-#define iJ3 "immed "<<
-#define iI3 mFuncParsers
-#define iH3 param.data
-#define iG3 stderr
-#define iF3 sep2=" "
-#define iE3 FPHASH_CONST
-#define iD3 cache_needed[
-#define iC3 fprintf
-#define iB3 "Applying "
-#define iA3 FUNCTIONPARSER_INSTANTIATE_OPTIMIZE
-#define i93 FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE
-#define i83 HANDLE_UNARY_CONST_FUNC
-#define i73 {if(n11
-#define i63 second;
-#define i53 within,
-#define i43 AddFrom(
-#define i33 tH3==
-#define i23 c_count
-#define i13 MaxOp
-#define i03 else nM
-#define tZ3 =tZ cL3
-#define tY3 .nJ 0));
-#define tX3 .nJ 1));
-#define tW3 lD m.
-#define tV3 ;a<tree.xB
-#define tU3 iZ);}if
-#define tT3 cS ifp2
-#define tS3 sim.xB1
-#define tR3 );tO tL1
-#define tQ3 ].swap(
-#define tP3 codes[b
-#define tO3 whydump
-#define tN3 for lS1
-#define tM3 for(;a<
-#define tL3 nparams
-#define tK3 281856,
-#define tJ3 cTan i7
-#define tI3 l2 2,2,
-#define tH3 ;if(op
-#define tG3 l4 0,1,
-#define tF3 0x12 nH
-#define tE3 FixIncompleteHashes()
-#define tD3 cSinh,
-#define tC3 ,cTan nS
-#define tB3 ,iX 1,
-#define tA3 nS 0,
-#define t93 cAbs nS
-#define t83 ;case
-#define t73 i1 t83
-#define t63 Params[
-#define t53 Params(
-#define t43 &&p nL3
-#define t33 fp_pow(
-#define t23 false;}
-#define t13 lD1 y4.
-#define t03 cAbsIf)
-#define eZ3 l91++b)
-#define eY3 lX1 nC==
-#define eX3 ;exponent
-#define eW3 =false;
-#define eV3 tN cS1);
-#define eU3 .empty()
-#define eT3 nS3))n92
-#define eS3 (opcode==
-#define eR3 <data eJ3;++
-#define eQ3 l14 nS3(
-#define eP3 ByteCodeSynth xF
-#define eO3 std xM3<
-#define eN3 middle2
-#define eM3 std::string
-#define eL3 SetOpcode(
-#define eK3 ;for iZ1
-#define eJ3 .size()
-#define eI3 ].second
-#define eH3 ].first
-#define eG3 return p
-#define eF3 TreeCountItem
-#define eE3 }return
-#define eD3 Ne_Mask
-#define eC3 Gt_Mask
-#define eB3 Lt_Mask
-#define eA3 const eK
-#define e93 .n7 synth.
-#define e83 range nE3
-#define e73 eK3 a=
-#define e63 ,eQ,c92
-#define e53 eO|lT1)
-#define e43 public:
-#define e33 Rehash(
-#define e23 switch(
-#define e13 pclone
-#define e03 cOr,l6
-#define cZ3 newpow
-#define cY3 change
-#define cX3 (Value_t
-#define cW3 (count
-#define cV3 133,2,
-#define cU3 ,tree
-#define cT3 byteCode
-#define cS3 child)
-#define cR3 (p1 x41)
-#define cQ3 cLog2by
-#define cP3 long iD1
-#define cO3 factor_t
-#define cN3 (p0 yI&&
-#define cM3 value1
-#define cL3 a));if(!
-#define cK3 fp_mod(
-#define cJ3 else{if(
-#define cI3 )min.set(
-#define cH3 xF());nD
-#define cG3 max.known
-#define cF3 known&&
-#define cE3 tX p2;p2
-#define cD3 {tree.x4
-#define cC3 cAbsNot
-#define cB3 ,x53 l8
-#define cA3 e23 lY1
-#define c93 xW 0)nC
-#define c83 IsLogicalValue(xW
-#define c73 }switch
-#define c63 stackptr
-#define c53 cLog);xG
-#define c43 l8 0));
-#define c33 opcodes
-#define c23 did_muli
-#define c13 &Value){
-#define c03 yD const
-#define yZ3 (param.
-#define yY3 ){e23
-#define yX3 :if(&*lE1){
-#define yW3 :{n31 r=
-#define yV3 xY3 e23
-#define yU3 param=*(
-#define yT3 cAbsIf,
-#define yS3 cNotNot,
-#define yR3 l4 16,1,
-#define yQ3 yO3 info
-#define yP3 lE1=r.specs;if(r.found){
-#define yO3 *x8)[a].
-#define yN3 cLess,cH
-#define yM3 default_function_handling
-#define yL3 l4 20,1,
-#define yK3 l4 4,1,
-#define yJ3 450998,
-#define yI3 cExp2 nS
-#define yH3 lJ 2},0,
-#define yG3 )lS 3*3*2*2
-#define yF3 default:
-#define yE3 range<nV
-#define yD3 range xF
-#define yC3 Ge0Lt1
-#define yB3 Gt0Le1
-#define yA3 cAdd lV2
-#define y93 if(op1==
-#define y83 iterator
-#define y73 begin();
-#define y63 TreeSet
-#define y53 parent
-#define y43 insert(i
-#define y33 newrel
-#define y23 y03 xX3 xO2
-#define y13 y03 iF2;if(
-#define y03 ))return
-#define xZ3 ;if(half
-#define xY3 break;}
-#define xX3 IsNever
-#define xW3 e62 eO1
-#define xV3 synth.xH
-#define xU3 b_needed
-#define xT3 cachepos
-#define xS3 ,lE1,info
-#define xR3 half=
-#define xQ3 131,4,1,
-#define xP3 131,8,1,
-#define xO3 ,iM,1,lC1+1);
-#define xN3 4,1,2,1,
-#define xM3 ::vector
-#define xL3 1 y5 n41
-#define xK3 FindPos(
-#define xJ3 src_pos
-#define xI3 xM1 xQ+
-#define xH3 reserve(
-#define xG3 treeptr
-#define xF3 .resize(
-#define xE3 tO1 void
-#define xD3 ImmedTag
-#define xC3 a,const
-#define xB3 RefCount
-#define xA3 Birth();
-#define x93 typename
-#define x83 unsigned
-#define x73 template
-#define x63 7168,
-#define x53 leaf1
-#define x43 cost_t
-#define x33 fpdata
-#define x23 middle
-#define x13 sqrt_cost
-#define x03 const int
-#define nZ3 mul_count
-#define nY3 );nZ l5::
-#define nX3 e62 2)));
-#define nW3 maxValue1
-#define nV3 minValue1
-#define nU3 maxValue0
-#define nT3 ValueType
-#define nS3 result
-#define nR3 nS3;}case
-#define nQ3 nS3.tL
-#define nP3 ::res,b8<
-#define nO3 eG3 yM
-#define nN3 .what nS1
-#define nM3 e62 1),e62 1));
-#define nL3 .max.val
-#define nK3 nS3 yM2
-#define nJ3 nS3 e61
-#define nI3 nS3 yI
-#define nH3 nS3 nL3
-#define nG3 nS3 tG1
-#define nF3 nS3 yM
-#define nE3 xF nS3
-#define nD3 tO n3 0),
-#define nC3 i8);nD lC
-#define nB3 abs_mul
-#define nA3 xM3<x83>&e71
-#define n93 l8 a));
-#define n83 pos_set
-#define n73 goto e1
-#define n63 p1.lT2 p1
-#define n53 [funcno].
-#define n43 eN1[++IP]
-#define n33 sim.x2 1,
-#define n23 {sim.Eat(
-#define n13 eN1[IP]==
-#define n03 subtree
-#define lZ3 invtree
-#define lY3 MakeHash(
-#define lX3 parampair
-#define lW3 rulenumit
-#define lV3 cAnd l3
-#define lU3 ,cMul l3
-#define lT3 cAnd,l6
-#define lS3 x9 lT 2,
-#define lR3 },{{1,
-#define lQ3 cEqual,
-#define lP3 lQ3 lA
-#define lO3 t01},{{3,
-#define lN3 MakeEqual
-#define lM3 nC1,l5::
-#define lL3 nC1,{l5::
-#define lK3 newbase
-#define lJ3 fp_equal(
-#define lI3 branch1op
-#define lH3 branch2op
-#define lG3 if(lJ3
-#define lF3 l8 a)xI
-#define lE3 overlap
-#define lD3 truth_b
-#define lC3 truth_a
-#define lB3 found_dup
-#define lA3 nQ r;r iH
-#define l93 void set(
-#define l83 {tP1 lE
-#define l73 rangeutil
-#define l63 Plan_Has(
-#define l53 StackMax)
-#define l43 i1 true;}
-#define l33 namespace
-#define l23 (cond yX
-#define l13 inverted
-#define l03 xX3:
-#define iZ2 iftree
-#define iY2 depcodes
-#define iX2 explicit
-#define iW2 cCosh nS
-#define iV2 t01 nH
-#define iU2 VarBegin
-#define iT2 t63 a]
-#define iS2 iR2 size()
-#define iR2 Params.
-#define iQ2 ].data);
-#define iP2 i8)));nZ
-#define iO2 yQ1.SubTrees
-#define iN2 yQ1.Others
-#define iM2 );synth
-#define iL2 ;DumpTree(
-#define iK2 ;Value_t
-#define iJ2 begin(),
-#define iI2 cond_add
-#define iH2 cond_mul
-#define iG2 cond_and
-#define iF2 IsAlways
-#define iE2 func lQ1
-#define iD2 bool eM1
-#define iC2 Forget()
-#define iB2 .second);
-#define iA2 Optimize()
-#define i92 costree
-#define i82 sintree
-#define i72 leaf_count
-#define i62 &&cond eD)
-#define i52 .tT1 n]
-#define i42 =GetParam(
-#define i32 sub_params
-#define i22 nC==cLog2&&
-#define i12 nC==cPow&&
-#define i02 printf(
-#define tZ2 cbrt_count
-#define tY2 sqrt_count
-#define tX2 cPow i7
-#define tW2 ,cPow,
-#define tV2 ,cGreater
-#define tU2 exponent);
-#define tT2 Finite
-#define tS2 min.n3 0),
-#define tR2 p1 cS ifp1
-#define tQ2 yR 2,cAdd)
-#define tP2 pcall_tree
-#define tO2 after_powi
-#define tN2 GetHash().
-#define tM2 yP t23
-#define tL2 params)
-#define tK2 grammar
-#define tJ2 cEqual t11
-#define tI2 cLog nS
-#define tH2 cNeg,lT 1,
-#define tG2 ),0},{
-#define tF2 std::move(
-#define tE2 iH cond nC
-#define tD2 tree iH
-#define tC2 ){eL3
-#define tB2 tree))cJ
-#define tA2 );t0=!t0;}
-#define t92 tmp c91 tree
-#define t82 nQ tmp;tmp iH
-#define t72 tree nC
-#define t62 MakeNEqual
-#define t52 )?0:1))l7
-#define t42 isInteger(
-#define t32 Comparison
-#define t22 needs_flip
-#define t12 (half&63)-1;
-#define t02 value]
-#define eZ2 lT1 opcode
-#define eY2 )lS 3*3*3*2
-#define eX2 cS tree);
-#define eW2 mul_item
-#define eV2 innersub
-#define eU2 cbrt_cost
-#define eT2 best_cost
-#define eS2 condition
-#define eR2 nominator
-#define eQ2 per_item
-#define eP2 item_type
-#define eO2 first2
-#define eN2 l4 18,1,
-#define eM2 cIf,iX 3,
-#define eL2 lJ 1},0,
-#define eK2 tJ 1},0,
-#define eJ2 Decision
-#define eI2 not_tree
-#define eH2 (mulgroup
-#define eG2 (lR));nD lC
-#define eF2 Become(xW
-#define eE2 group_by
-#define eD2 exponent=
-#define eC2 ->second
-#define eB2 targetpos
-#define eA2 ParamSpec
-#define e92 rhs.hash2;}
-#define e82 rhs.hash1
-#define e72 struct
-#define e62 Value_t(
-#define e52 .n_int_sqrt
-#define e42 const std::eP
-#define e32 const char*
-#define e22 nT 409641,
-#define e12 ,xF1);lC
-#define e02 );xY3
-#define cZ2 if(t72==
-#define cY2 eO3 bool>
-#define cX2 ,(long double)
-#define cW2 ContainsOtherCandidates
-#define cV2 std::cout
-#define cU2 source_tree
-#define cT2 GetParam eS
-#define cS2 <tP,x43>
-#define cR2 p1_evenness
-#define cQ2 isNegative(
-#define cP2 neg_set
-#define cO2 }else{x8=new
-#define cN2 );}void
-#define cM2 cNop,cNop}}
-#define cL2 cTanh,cNop,
-#define cK2 NewHash
-#define cJ2 >e72 cB<
-#define cI2 matches
-#define cH2 {cV2<<
-#define cG2 iS1 void*)&
-#define cF2 cGreater,cH
-#define cE2 cSin i7
-#define cD2 cCos nS
-#define cC2 ,t21 0x1 nH
-#define cB2 +=1 i1 n91;
-#define cA2 negated
-#define c92 synth);
-#define c82 Specializer
-#define c72 ifdata.ofs
-#define c62 (IfData&ifdata
-#define c52 .push_back(
-#define c42 ;}data;data.
-#define c32 );sim.x2 2,
-#define c22 nP)l14 tmp=
-#define c12 (*x8)[0].info
-#define c02 CodeTree
-#define yZ2 c02 xF
-#define yY2 coshtree
-#define yX2 sinhtree
-#define yW2 best_score
-#define yV2 mulvalue
-#define yU2 pow_item
-#define yT2 subgroup
-#define yS2 PowiResult
-#define yR2 .match_tree
-#define yQ2 )l43
-#define yP2 0));yD3
-#define yO2 maxValue
-#define yN2 minValue
-#define yM2 yI eW3 if(
-#define yL2 fp_min(yL,
-#define yK2 div_tree
-#define yJ2 pow_tree
-#define yI2 preserve
-#define yH2 ,cCos i7
-#define yG2 (rule cU3,info
-#define yF2 e62 0.5)
-#define yE2 PullResult()
-#define yD2 dup_or_fetch
-#define yC2 e33 false
-#define yB2 test_order
-#define yA2 lX3,
-#define y92 .param_count
-#define y82 shift(index)
-#define y72 rulenumber
-#define y62 cTanh nS
-#define y52 cSinh nS
-#define y42 cInv,lT 1,
-#define y32 constraints=
-#define y22 factor_immed
-#define y12 changes
-#define y02 n81 cS y4 l8
-#define xZ2 cS leaf2 l8
-#define xY2 cS x53 l8
-#define xX2 cS cond l8
-#define xW2 exp_diff
-#define xV2 ExponentInfo
-#define xU2 lower_bound(
-#define xT2 factor
-#define xS2 is_logical
-#define xR2 newrel_and
-#define xQ2 tH[c eE
-#define xP2 ;iM.Remember(
-#define xO2 i1 Unknown;}
-#define xN2 res_stackpos
-#define xM2 half_pos
-#define xL2 >>1)):(
-#define xK2 CodeTreeData
-#define xJ2 multiply(
-#define xI2 tO known)
-#define xH2 var_trees
-#define xG2 erase(cs_it);
-#define xF2 parent_opcode
-#define xE2 log2_exponent
-#define xD2 yB swap(tmp);
-#define xC2 Value(Value::
-#define xB2 dup_fetch_pos
-#define xA2 a;if(eK1){x8=
-#define x92 {cZ start_at;
-#define x82 xX3 cQ lC
-#define x72 cSin nS
-#define x62 Value_EvenInt
-#define x52 )){data xC
-#define x42 MakeFalse,{l5
-#define x32 if(list.first
-#define x22 AddCollection
-#define x12 ConditionType
-#define x02 DUP_ONE(apos)
-#define nZ2 SpecialOpcode
-#define nY2 =i eC2.
-#define nX2 IsDefined()
-#define nW2 fp_max(yL);
-#define nV2 (tree,cV2
-#define nU2 e62-1)
-#define nT2 assimilated
-#define nS2 denominator
-#define nR2 fraction
-#define nQ2 l2 18,2,
-#define nP2 .GetDepth()
-#define nO2 iH t72)
-#define nN2 xI leaf2 l8
-#define nM2 DUP_BOTH();
-#define nL2 x73 lL
-#define nK2 -1-offset].
-#define nJ2 tree.GetHash()
-#define nI2 TreeCounts
-#define nH2 ,e62 1))){
-#define nG2 bool t0 eW3
-#define nF2 found_log2
-#define nE2 div_params
-#define nD2 immed_sum
-#define nC2 :sim.Eat(1,
-#define nB2 OPCODE(opcode)
-#define nA2 ;sim.Push(
-#define n92 break;nS3*=
-#define n82 FactorStack xF
-#define n72 iF2 cQ lC
-#define n62 cLessOrEq,
-#define n52 282870 nT
-#define n42 cNotNot nS
-#define n32 cNot nS
-#define n22 replacing_slot
-#define n12 RefParams
-#define n02 if_always[
-#define lZ2 WhatDoWhenCase
-#define lY2 exponent_immed
-#define lX2 new_base_immed
-#define lW2 base_immed
-#define lV2 ||op1==
-#define lU2 remaining
-#define lT2 Rehash t8
-#define lS2 data[a eI3
-#define lR2 lT2 r);}
-#define lQ2 if(newrel_or==
-#define lP2 .UseGetNeeded(
-#define lO2 e7 2,131,
-#define lN2 Immed eJ3);
-#define lM2 OptimizedUsing
-#define lL2 Var_or_Funcno
-#define lK2 lL2;
-#define lJ2 GetParams(
-#define lI2 crc32_t
-#define lH2 signed_chain
-#define lG2 MinusInf
-#define lF2 synth.Find(
-#define lE2 );cV2<<
-#define lD2 return true;
-#define lC2 n_immeds
-#define lB2 stack eJ3
-#define lA2 FindClone(xM
-#define l92 GetOpcode())
-#define l82 needs_rehash
-#define l72 AnyWhere_Rec
-#define l62 minimum_need
-#define l52 ~x83(0)
-#define l42 41,42,43,44,
-#define l32 p1_logical_b
-#define l22 p0_logical_b
-#define l12 p1_logical_a
-#define l02 p0_logical_a
-#define iZ1 (size_t
-#define iY1 )e73
-#define iX1 TopLevel)
-#define iW1 .e33)
-#define iV1 {pow.CopyOnWrite
-#define iU1 nB OPCODE
-#define iT1 const yZ2
-#define iS1 (const
-#define iR1 iS1 yZ2&
-#define iQ1 ,PowiCache&iM,
-#define iP1 else if(
-#define iO1 iP1!nS3
-#define iN1 synth.DoDup(
-#define iM1 cache_needed
-#define iL1 e7 2,1,e7 2,
-#define iK1 [c72+
-#define iJ1 treelist
-#define iI1 IsDescendantOf(
-#define iH1 has_bad_balance
-#define iG1 )tN mulgroup)
-#define iF1 .SetParamsMove(
-#define iE1 cO3 xT2
-#define iD1 double)exponent
-#define iC1 {if(GetOpcode()
-#define iB1 cV2<<std::y11
-#define iA1 cV2<<"POP "
-#define i91 DelParam(
-#define i81 set(fp_ceil);tK
-#define i71 fp_abs(max.val))
-#define i61 fp_abs(min.val)
-#define i51 cNEqual
-#define i41 },0,0x0},{{
-#define i31 tJ 2 i41
-#define i21 Oneness_NotOne|
-#define i11 Value_IsInteger
-#define i01 Constness_Const
-#define tZ1 DumpHashesFrom(
-#define tY1 reltype
-#define tX1 const Value_t&i)
-#define tW1 const c02&
-#define tV1 const Value_t&v
-#define tU1 SequenceOpcodes
-#define tT1 sep_list[
-#define tS1 ;else_tree
-#define tR1 goto fail;}
-#define tQ1 l1 0x4 nH
-#define tP1 x73<
-#define tO1 n12);
-#define tN1 ){case iF2:
-#define tM1 grammar_rules[*r]
-#define tL1 x73 set_if<
-#define tK1 x73 lX
-#define tJ1 TreeCountType xF
-#define tI1 GetParamCount(nX
-#define tH1 >(e62 1),
-#define tG1 nL3)
-#define tF1 )lX3.second
-#define tE1 e62 0.0)){nU
-#define tD1 .IsImmed()
-#define tC1 a)tD1)
-#define tB1 nB2);
-#define tA1 stack[lB2-
-#define t91 stack c52
-#define t81 )eX3 iW1;
-#define t71 synth.PushImmed(
-#define t61 MaxChildDepth
-#define t51 repl_param_list,
-#define t41 const Rule&rule,
-#define t31 std::pair<It,It>
-#define t21 cPow,lA
-#define t11 ,l0 2,
-#define t01 ,l1 0x12
-#define eZ1 Sign_Negative
-#define eY1 Value_Logical
-#define eX1 yZ2&b
-#define eW1 new_factor_immed
-#define eV1 occurance_pos
-#define eU1 exponent_hash
-#define eT1 exponent_list
-#define eS1 CollectionSet xF
-#define eR1 CollectMulGroup(
-#define eQ1 source_set
-#define eP1 exponent,y63
-#define eO1 *const func)(
-#define eN1 ByteCode
-#define eM1 operator
-#define eL1 FindAndDup(tree);
-#define eK1 &*start_at
-#define eJ1 <<nJ2.
-#define eI1 xW 1)tD1&&
-#define eH1 retry_anyparams_3
-#define eG1 retry_anyparams_2
-#define eF1 e6(),eO3
-#define eE1 needlist_cached_t
-#define eD1 yH3 0x4 lR3
-#define eC1 eL2 0x4 lR3
-#define eB1 ),lM2(
-#define eA1 CodeTreeImmed xF(
-#define e91 GetParamCount()==
-#define e81 .back().thenbranch
-#define e71 eN1,size_t&IP,size_t limit,size_t y2
-#define e61 .cG3
-#define e51 (lR,xW i8));nD
-#define e41 ;flipped=!flipped;}
-#define e31 ,l1 0x0},{{3,
-#define e21 }xY3 case
-#define e11 for iZ1 b=0;b<
-#define e01 by_float_exponent
-#define cZ1 lJ3 exponent
-#define cY1 new_exp
-#define cX1 end()&&i->first==
-#define cW1 return BecomeZero;
-#define cV1 =comp.AddItem(atree
-#define cU1 return BecomeOne;
-#define cT1 if(lQ eJ3<=n1)
-#define cS1 addgroup
-#define cR1 found_log2by
-#define cQ1 nC==cC3)
-#define cP1 ParsePowiMuli(
-#define cO1 lL2)
-#define cN1 eL 529654 nT
-#define cM1 branch1_backup
-#define cL1 branch2_backup
-#define cK1 exponent_map
-#define cJ1 plain_set
-#define cI1 rangehalf
-#define cH1 LightWeight(
-#define cG1 xV3 1
-#define cF1 divgroup
-#define cE1 ,iM e63
-#define cD1 if(value
-#define cC1 tK1 c0
-#define cB1 tK1 static
-#define cA1 mulgroup.
-#define c91 .AddParamMove(
-#define c81 yB AddParamMove(
-#define c71 ;n81 cY op1 yB DelParams
-#define c61 should_regenerate=true;
-#define c51 should_regenerate,
-#define c41 Collection
-#define c31 RelationshipResult
-#define c21 Subdivide_Combine(
-#define c11 long value
-#define c01 )const yP
-#define yZ1 rhs c01 hash1
-#define yY1 for iZ1 a xY
-#define yX1 best_sep_factor
-#define yW1 SynthesizeParam
-#define yV1 needlist_cached
-#define yU1 inline x83
-#define yT1 opcode,bool pad
-#define yS1 changed=true;
-#define yR1 );xM iF1
-#define yQ1 NeedList
-#define yP1 tK1 bool
-#define yO1 ;tK1
-#define yN1 i91 a);}
-#define yM1 MakesInteger(
-#define yL1 const Value_t&value
-#define yK1 best_sep_cost
-#define yJ1 MultiplicationRange
-#define yI1 .min.set(fp_floor);
-#define yH1 pihalf_limits
-#define yG1 yR 2,cMul);lC
-#define yF1 n_stacked
-#define yE1 cK2.hash1
-#define yD1 AnyParams_Rec
-#define yC1 ;synth.StackTopIs(
-#define yB1 synth.AddOperation(
-#define yA1 continue;
-#define y91 Become(value l8 0))
-#define y81 }inline
-#define y71 PositionalParams,0}
-#define y61 always_sincostan
-#define y51 Recheck_RefCount_Div
-#define y41 Recheck_RefCount_Mul
-#define y31 MultiplyAndMakeLong(
-#define y21 covers_plus1
-#define y11 endl;DumpHashes(
-#define y01 if(synth.FindAndDup(
-#define xZ1 grammar_func
-#define xY1 tree tD1 cQ
-#define xX1 cOr l3 16,1,
-#define xW1 252421 nT 24830,
-#define xV1 l2 0,2,165888 nT
-#define xU1 Modulo_Radians},
-#define xT1 yB SetParam(
-#define xS1 PositionType
-#define xR1 CollectionResult
-#define xQ1 const_offset
-#define xP1 inline TriTruthValue
-#define xO1 stacktop_desired
-#define xN1 iU3);lC
-#define xM1 SetStackTop(
-#define xL1 tK1 void
-#define xK1 FPoptimizer_ByteCode
-#define xJ1 1)?(poly^(
-#define xI1 eP3&synth)
-#define xH1 e62 0)
-#define xG1 xH1)
-#define xF1 cond_type
-#define xE1 fphash_value_t
-#define xD1 Recheck_RefCount_RDiv
-#define xC1 cMul);tmp tY3 tmp.
-#define xB1 SwapLastTwoInStack();
-#define xA1 SetParams(lJ2)
-#define x91 fPExponentIsTooLarge(
-#define x81 CollectMulGroup_Item(
-#define x71 pair<Value_t,y63>
-#define x61 (x53 l8 1)nN2
-#define x51 for iZ1 a=0;a<yC++a)
-#define x41 .GetImmed()
-#define x31 {int mStackPtr=0;
-#define x21 nL xM1 xQ-1);
-#define x11 covers_full_cycle
-#define x01 AssembleSequence(
-#define nZ1 inverse_nominator
-#define nY1 252180 nT 281854,
-#define nX1 <<std::dec<<")";}
-#define nW1 {DataP slot_holder(y1[
-#define nV1 },{l5::MakeNotP1,l5::
-#define nU1 },{l5::MakeNotP0,l5::
-#define nT1 },{l5::MakeNotNotP1,l5::
-#define nS1 !=xJ)if(TestCase(
-#define nR1 AddFunctionOpcode
-#define nQ1 public e6,public eO3
-#define nP1 yZ2&tree,
-#define nO1 std::pair<T1,T2>&
-#define nN1 tP1 x93
-#define nM1 has_good_balance_found
-#define nL1 n_occurrences
-#define nK1 found_log2_on_exponent
-#define nJ1 covers_minus1
-#define nI1 needs_resynth
-#define nH1 immed_product
-#define nG1 l33 FPoptimizer_Optimize
-#define nF1 (ParamSpec_Extract xF(
-#define nE1 yV3 bitmask&
-#define nD1 Sign_Positive
-#define nC1 ::MakeTrue
-#define nB1 SetParamMove(
-#define nA1 CodeTreeImmed(e62
-#define n91 Suboptimal
-#define n81 changed_if
-#define n71 n_as_tanh_param
-#define n61 opposite=
-#define n51 xE1(
-#define n41 eN1 eJ3
-#define n31 MatchResultType
-#define n21 yP yZ2(
-#define n11 needs_sincos
-#define n01 resulting_exponent
-#define lZ1 Unknown:yF3;}
-#define lY1 GetLogicalValue(xW
-#define lX1 GetParam(a)
-#define lW1 cMul l3 0,1,
-#define lV1 IsImmed())l14
-#define lU1 void FunctionParserBase
-#define lT1 (x83
-#define lS1 lT1 a=0;a<xT;++a)
-#define lR1 o<<"("<<std::hex<<data.
-#define lQ1 (val);else*this=model;}
-#define lP1 IfBalanceGood(
-#define lO1 n_as_tan_param
-#define lN1 changed_exponent
-#define lM1 inverse_denominator
-#define lL1 ;cK2.hash2+=
-#define lK1 retry_positionalparams_2
-#define lJ1 x83 index
-#define lI1 situation_flags&
-#define lH1 518 nT 400412,
-#define lG1 data.subfunc_opcode
-#define lF1 },{l5::MakeNotNotP0,l5::
-#define lE1 (yO3 start_at
-#define lD1 CopyOnWrite();
-#define lC1 recursioncount
-#define lB1 PlanNtimesCache(
-#define lA1 FPoptimizer_Grammar
-#define l91 GetParamCount();
-#define l81 GetPositivityInfo iS3
-#define l71 ParamSpec_SubFunctionData
-#define l61 t43<e62
-#define l51 (tree.GetParamCount()
-#define l41 iZ1 a=yC a-->0;)
-#define l31 PositionalParams_Rec
-#define l21 DumpTreeWithIndent(*this);
-#define l11 e23 type){case cond_or:
-#define l01 tP1 x83 Compare>
-#define iZ tree.i91 a
-#define iY .l91 a-->0;)if(
-#define iX lA 0x4},{{
-#define iW lJ 2 i41 1,
-#define iV edited_powgroup
-#define iU has_unknown_max
-#define iT has_unknown_min
-#define iS static const yD3
-#define iR if(keep_powi
-#define iQ synthed_tree
-#define iP 7168 nT 401798,
-#define iO SelectedParams,0 i41
-#define iN collections
-#define iM cache
-#define iL ,cIf,l0 3,
-#define iK ,eN1,IP,limit,y2,stack);
-#define iJ by_exponent
-#define iI );p2.lT2 p2 yB eL3 iZ2 nC);cJ}
-#define iH .eL3
-#define iG mulgroup;mulgroup iH
-#define iF (p0 e61&&p0 nL3 i2
-#define iE cN3 p0 yM>=e62 0.0))
-#define iD goto ReplaceTreeWithOne t83
-#define iC !=xJ)return n02
-#define iB e01.data
-#define iA iX2 xK2(
-#define i9 needs_sinhcosh
-#define i8 1)x41
-#define i7 ,l4 2,1,
-#define i6 cAdd l3 0,
-#define i5 tG2 e62
-#define i4 tK1 n9
-#define i3 MakeFalse,l5::
-#define i2 <=fp_const_negativezero xF())
-#define i1 ;return
-#define i0 )i1 lH
-#define tZ CalculateResultBoundaries(xW
-#define tY p0=CalculateResultBoundaries(
-#define tX ;yZ2
-#define tW ,2,1 iM2.xR if(found[data.
-#define tV 408964 nT 24963,
-#define tU 528503 nT 24713,
-#define tT matched_params
-#define tS [n1 eH3=true;lQ[n1 eI3
-#define tR lA1::Grammar*
-#define tQ AddOperation(cInv,1,1 iM2.xR}
-#define tP int_exponent_t
-#define tO m.max.
-#define tN ;AddParamMove(
-#define tM nM nU2,e62 1));
-#define tL cG3 eW3
-#define tK return m;}case
-#define tJ x9 AnyParams,
-#define tI powgroup l8
-#define tH relationships
-#define tG ]!=~size_t(0)){synth.yT
-#define tF }},{ProduceNewTree,2,1,
-#define tE nA1(
-#define tD has_mulgroups_remaining
-#define tC MatchInfo xF&
-#define tB e33);i32 c52
-#define tA best_factor
-#define t9 RootPowerTable xF::RootPowers[
-#define t8 (c81
-#define t7 :goto ReplaceTreeWithZero t83
-#define t6 MatchPositionSpec_AnyParams xF
-#define t5 l33 FPoptimizer_CodeTree
-#define t4 n_as_sinh_param
-#define t3 n_as_cosh_param
-#define t2 ();pow iH cLog yB eL3 cMul
-#define t1 0,tU2 i91 1);
-#define t0 is_signed
-#define eZ result_positivity
-#define eY biggest_minimum
-#define eX const l71
-#define eW 122999 nT 139399,
-#define eV 142455 nT 141449,
-#define eU cond_tree
-#define eT then_tree
-#define eS (a);bool needs_cow=GetRefCount()>1;
-#define eR yZ2&tree)
-#define eQ sequencing
-#define eP string FP_GetOpcodeName(
-#define eO );eN1 c52 0x80000000u
-#define eN {if(needs_cow){lD1 goto
-#define eM (lJ2));cA1 e33);
-#define eL ,nQ2
-#define eK eO3 yZ2>
-#define eJ if_stack
-#define eI n_as_sin_param
-#define eH n_as_cos_param
-#define eG PowiResolver::
-#define eF cIf,tG3
-#define eE ].relationship
-#define eD .BalanceGood
-#define eC AddParamMove(yT2
-#define eB valueType
-#define eA back().endif_location
-#define e9 xE1 key
-#define e8 AddParamMove(mul);
-#define e7 130,1,
-#define e6 MatchPositionSpecBase
-#define e5 iX2 c02(
-#define e4 smallest_maximum
-#define e3 ]!=~size_t(0)&&found[data.
-#define e2 }PACKED_GRAMMAR_ATTRIBUTE;
-#define e1 ReplaceTreeWithParam0;
-#define e0 factor_needs_rehashing
-#define cZ MatchPositionSpecBaseP
-#define cY .e33 yB eL3
-#define cX x93 tJ1::y83
-#define cW ParamSpec_Extract xF(nN.param_list,
-#define cV }x32 x41==e62
-#define cU 243,244,245,246,249,250,251,253,255,256,257,258,259}};}
-#define cT ];};extern"C"{
-#define cS .AddParam(
-#define cR iL2 tree lE2"\n";
-#define cQ )return false;
-#define cP 79,122,123,160,161,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,
-#define cO 27,28,29,30,31,32,33,35,36,
-#define cN const ParamSpec_SubFunction
-#define cM const ParamSpec_ParamHolder
-#define cL otherhalf
-#define cK :{AdoptChildrenWithSameOpcode(tree);
-#define cJ goto redo;
-#define cI StackState
-#define cH l2 16,2,
-#define cG const SequenceOpCode xF
-#define cF MatchPositionSpec_PositionalParams xF
-#define cE const nP1 std::ostream&o
-#define cD e62 1.5)*fp_const_pi xF()
-#define cC CalculatePowiFactorCost(
-#define cB ImmedHashGenerator
-#define cA paramholder_matches
-#define c9 ::map<fphash_t,std::set<eM3> >
-#define c8 ComparisonSetBase::
-#define c7 AddParamMove(comp.cJ1[a].value);
-#define c6 T1,x93 T2>inline iD2()(
-#define c5 has_nonlogical_values
-#define c4 from_logical_context)
-#define c3 AnyParams,0}},{ProduceNewTree,
-#define c2 for iZ1 a=xV.l91 a-->0;)
-#define c1 POWI_CACHE_SIZE
-#define c0 static inline yZ2
-#define yZ ++IP;yA1}if(n13 c33.
-#define yY },{l5::xJ,l5::Never},{l5::xJ,l5::Never}}
-#define yX .FoundChild
-#define yW BalanceResultType
-#define yV {yZ2 tmp;tmp iH
-#define yU yB1 GetOpcode(),
-#define yT DoDup(found[data.
-#define yS xB3(0),Opcode(
-#define yR ;sim.Eat(
-#define yQ );void nR1 eZ2,c82<
-#define yP {return
-#define yO const yP data->
-#define yN +=fp_const_twopi xF();
-#define yM .min.val
-#define yL fp_sin(min),fp_sin(max))
-#define yK fp_const_twopi xF());if(
-#define yJ {yZ2 tmp,tmp2;tmp2 iH
-#define yI .min.known
-#define yH for iZ1 a=0;a<l91++a){if(
-#define yG MatchPositionSpec_AnyWhere
-#define yF if yZ3 data.match_type==
-#define yE void OutFloatHex(std::ostream&o,
-#define yD {static void lY3 nB fphash_t&cK2,
-#define yC tree.l91
-#define yB );tree.
-#define yA AddParam(CodeTreeImmed(
-#define y9 cGreaterOrEq,
-#define y8 ,x93 yZ2::
-#define y7 xF model=cI1 xF()){if(known
-#define y6 AssembleSequence_Subdivide(
-#define y5 ]=0x80000000u|x83(
-#define y4 branch2
-#define y3 x83 c;x83 short l[
-#define y2 factor_stack_base
-#define y1 data->Params
-#define y0 (lW3 r=range.first;r!=range.i63++r){
-#define xZ {nI2.erase(i);yA1}
-#define xY =0;a<y53.l91++a)if(
-#define xX ,t21 0x4 nH
-#define xW tree l8
-#define xV branch1
-#define xU ,nU2))eN
-#define xT nN y92
-#define xS =fp_cosh(m yM);tO val=fp_cosh(tO val);
-#define xR StackTopIs(*this)i1;}
-#define xQ StackTop
-#define xP FPOPT_autoptr
-#define xO +=nS3 i1 nS3;}tK1 inline Value_t
-#define xN int_exponent
-#define xM newnode
-#define xL lJ 1 i41
-#define xK has_highlevel_opcodes
-#define xJ Unchanged
-#define xI .IsIdenticalTo(
-#define xH GetStackTop()-
-#define xG sim.AddConst(
-#define xF <Value_t>
-#define xE cE=cV2
-#define xD best_selected_sep
-#define xC ->Recalculate_Hash_NoRecursion();}
-#define xB l91++a)if(ApplyGrammar(tK2,xW a),
-#define xA lU3 2,1,
-#define x9 ,cAdd,
-#define x8 position
-#define x7 x51{yD3
-#define x6 ;tmp2 tY3 tmp iH cInv);tmp c91 tmp2)i1
-#define x5 eO3 c02>
-#define x4 SetParam(0,iZ2 l8 0))tX p1;p1 iH
-#define x3 TestImmedConstraints yZ3 constraints cU3)cQ
-#define x2 SwapLastTwoInStack()yR
-#define x1 n23 1,cInv e02 xG-1 xN1
-#define x0 paramholder_index
-#define nZ lD2 case
-#define nY occurance_counts
-#define nX );a-->0;){iT1&powgroup=lX1;if(powgroup
-#define nW )){tree.tE3;}
-#define nV Value_t>p=tZ a));if(p.
-#define nU tree.ReplaceWithImmed(
-#define nT ,{2,
-#define nS ,l0 1,
-#define nR ,cAdd l3 2,1,
-#define nQ ){yZ2
-#define nP if(xW 0)tD1
-#define nO const FPoptimizer_CodeTree::yZ2&tree
-#define nN model_tree
-#define nM return yD3(
-#define nL ){using l33 FUNCTIONPARSERTYPES;
-#define nK eK&n12
-#define nJ AddParam(xW
-#define nI ConstantFolding_LogicCommon(tree,c8
-#define nH },{{2,
-#define nG nN1 Ref>inline void xP<Ref>::
-#define nF AnyParams,1 i41
-#define nE ):data(new xK2 xF(
-#define nD goto do_return;}
-#define nC .GetOpcode()
-#define nB FUNCTIONPARSERTYPES::
-#define nA b;}};tP1>e72 Comp<nB
-#define n9 xK2 xF::xK2(
-#define n8 lL2(),t53),Hash(),Depth(1 eB1 0){}
-#define n7 SynthesizeByteCode(c92
-#define n6 while(ApplyGrammar(cG2
-#define n5 GetIntegerInfo(xW 0))==iF2)n73
-#define n4 ;tree c91 n81 yQ2
-#define n3 tL1 cGreater>(e62
-#define n2 DumpParams xF yZ3 data.param_list,iH3 y92,o);
-#define n1 restholder_index
-#define n0 yZ2 exponent eX3 iH cMul)eX3 cS
-#define lZ lR);if(fp_nequal(tmp,xG1){nU e62 1)/tmp);nD}lC
-#define lY :if(ParamComparer xF()(t63 1],t63 0])){std::swap(t63 0],t63 1]);Opcode=
-#define lX <x93 Value_t>
-#define lW xF tmp;tmp iH cPow);tmp tY3 tmp.yA e62
-#define lV i01,0x0},
-#define lU AddParamMove(pow l8 1));pow.i91 1);pow.e33 yB nB1 0,pow);goto NowWeAreMulGroup;}
-#define lT GroupFunction,0},lV{{
-#define lS ,e62 1)/e62
-#define lR xW 0)x41
-#define lQ restholder_matches
-#define lP yE1|=key;xE1 crc=(key>>10)|(key<<(64-10))lL1((~n51 crc))*3)^1234567;}};
-#define lO n81;n81 nO2;n81 c91 xW 0));n81 cS xV l8
-#define lN tK1 yZ2::c02(
-#define lM tree.SetParam(0,xW 0)l8 0)xT1 1,CodeTreeImmed(
-#define lL lX void eP3::nR1 eZ2,c82<
-#define lK cMul,lT 2,
-#define lJ cMul,AnyParams,
-#define lI (xW 0)tD1&&xW 1)tD1){nU
-#define lH CalculateResultBoundaries(tmp);}case
-#define lG :cY3=comp.AddRelationship(atree l8 0),atree l8 1),c8
-#define lF cPow,l0 2
-#define lE x93 Value_t>inline iD2()iS1 Value_t&xC3 Value_t&b)yP a
-#define lD {yD3 m=tZ 0));
-#define lC break t83
-#define lB xL1 yZ2::
-#define lA y71,0,
-#define l9 l1 0x0 nH
-#define l8 .GetParam(
-#define l7 tX n81;n81 nO2;n81 iF1 tree.lJ2));n81 cY
-#define l6 SelectedParams,0},0,0x0 nH
-#define l5 RangeComparisonData
-#define l4 y71},{ProduceNewTree,
-#define l3 ,AnyParams,0}},{ReplaceParams,
-#define l2 y71},{ReplaceParams,
-#define l1 cMul,SelectedParams,0},0,
-#define l0 lA 0x0},{{
-#ifdef _MSC_VER
-typedef
-x83
-int
-lI2;
-#else
-typedef
-uint_least32_t
-lI2;
-#endif
-l33
-crc32{enum{startvalue=0xFFFFFFFFUL,poly=0xEDB88320UL}
-;tP1
-lI2
-crc>e72
-b8{enum{b1=(crc&xJ1
-crc
-xL2
-crc>>1),b2=(b1&xJ1
-b1
-xL2
-b1>>1),b3=(b2&xJ1
-b2
-xL2
-b2>>1),b4=(b3&xJ1
-b3
-xL2
-b3>>1),b5=(b4&xJ1
-b4
-xL2
-b4>>1),b6=(b5&xJ1
-b5
-xL2
-b5>>1),b7=(b6&xJ1
-b6
-xL2
-b6>>1),res=(b7&xJ1
-b7
-xL2
-b7>>1)}
-;}
-;inline
-lI2
-update(lI2
-crc,x83
-b){
-#define B4(n) b8<n>nP3 n+1>nP3 n+2>nP3 n+3>::res
-#define R(n) B4(n),B4(n+4),B4(n+8),B4(n+12)
-static
-const
-lI2
-table[256]={R(0x00),R(0x10),R(0x20),R(0x30),R(0x40),R(0x50),R(0x60),R(0x70),R(0x80),R(0x90),R(0xA0),R(0xB0),R(0xC0),R(0xD0),R(0xE0),R(0xF0)}
-;
-#undef R
-#undef B4
-return((crc>>8))^table[(crc^b)&0xFF];y81
-lI2
-calc_upd(lI2
-c,const
-x83
-char*buf,size_t
-size){lI2
-value=c
-eK3
-p=0;p<size;++p)value=update(value,buf[p])i1
-value;y81
-lI2
-calc
-iS1
-x83
-char*buf,size_t
-size)yP
-calc_upd(startvalue,buf,size);}
-}
-#ifndef FPOptimizerAutoPtrHH
-#define FPOptimizerAutoPtrHH
-nN1
-Ref>class
-xP{e43
-xP():p(0){}
-xP(Ref*b):p(b){xA3}
-xP
-iS1
-xP&b):p(b.p){xA3
-y81
-Ref&eM1*(c01*p;y81
-Ref*eM1->(c01
-p;}
-xP&eM1=(Ref*b){Set(b)i1*this;}
-xP&eM1=iS1
-xP&b){Set(b.p)i1*this;}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-xP(xP&&b):p(b.p){b.p=0;}
-xP&eM1=(xP&&b){if(p!=b.p){iC2;p=b.p;b.p=0;eE3*this;}
-#endif
-~xP(){Forget(cN2
-UnsafeSetP(Ref*newp){p=newp;}
-void
-swap(xP<Ref>&b){Ref*tmp=p;p=b.p;b.p=tmp;}
-private:inline
-static
-void
-Have(Ref*p2);inline
-void
-iC2;inline
-void
-xA3
-inline
-void
-Set(Ref*p2);private:Ref*p;}
-;nG
-iC2{if(!p)return;p->xB3-=1;if(!p->xB3)delete
-p;}
-nG
-Have(Ref*p2){if(p2)++(p2->xB3);}
-nG
-Birth(){Have(p);}
-nG
-Set(Ref*p2){Have(p2);iC2;p=p2;}
-#endif
-e72
-Compare2ndRev{nN1
-T>inline
-iD2()iS1
-T&xC3
-T&b
-c01
-a.second>b.i63}
-}
-;e72
-Compare1st{nN1
-c6
-const
-nO1
-xC3
-nO1
-b
-c01
-a.first<b.first;}
-nN1
-c6
-const
-nO1
-a,T1
-b
-c01
-a.first<b;}
-nN1
-c6
-T1
-xC3
-nO1
-b
-c01
-a<b.first;}
-}
-;
-#ifndef FPoptimizerHashHH
-#define FPoptimizerHashHH
-#ifdef _MSC_VER
-typedef
-x83
-long
-long
-xE1;
-#define FPHASH_CONST(x) x##ULL
-#else
-typedef
-uint_fast64_t
-xE1;
-#define FPHASH_CONST(x) x##ULL
-#endif
-l33
-FUNCTIONPARSERTYPES{e72
-fphash_t{xE1
-hash1,hash2;fphash_t():hash1(0),hash2(0){}
-fphash_t
-iS1
-xE1&xC3
-xE1&b):hash1(a),hash2(b){}
-iD2==iS1
-fphash_t&yZ1==e82&&hash2==e92
-iD2!=iS1
-fphash_t&yZ1!=e82||hash2!=e92
-iD2<iS1
-fphash_t&yZ1!=e82?hash1<e82:hash2<e92}
-;}
-#endif
-#ifndef FPOptimizer_CodeTreeHH
-#define FPOptimizer_CodeTreeHH
-#ifdef FP_SUPPORT_OPTIMIZER
-l33
-lA1{e72
-Grammar;}
-l33
-xK1{tK1
-class
-ByteCodeSynth;}
-t5{tK1
-class
-c02
-yO1
-e72
-xK2
-yO1
-class
-c02{typedef
-xP<xK2
-xF>DataP;DataP
-data;e43
-c02();~c02();e72
-OpcodeTag{}
-;e5
-iU1
-o,OpcodeTag);e72
-FuncOpcodeTag{}
-;e5
-iU1
-o,x83
-f,FuncOpcodeTag);e72
-xD3{}
-;e5
-tV1,xD3);
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-e5
-Value_t&&v,xD3);
-#endif
-e72
-VarTag{}
-;e5
-x83
-varno,VarTag);e72
-CloneTag{}
-;e5
-tW1
-b,CloneTag);void
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&data,bool
-keep_powi=false);void
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&data,const
-x5&xH2,bool
-keep_powi=false);void
-SynthesizeByteCode(eO3
-x83>&cT3,std
-xM3
-xF&immed,size_t&stacktop_max);void
-SynthesizeByteCode(xK1::eP3&synth,bool
-MustPopTemps=true)const;size_t
-SynthCommonSubExpressions(xK1::xI1
-const;void
-SetParams
-iS1
-x5&xE3
-SetParamsMove(x5&tO1
-c02
-GetUniqueRef();
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-void
-SetParams(x5&&tO1
-#endif
-void
-SetParam
-iZ1
-which,tW1
-b);void
-nB1
-size_t
-which,c02&b);void
-AddParam(tW1
-param);void
-AddParamMove(c02¶m);void
-AddParams
-iS1
-x5&xE3
-AddParamsMove(x5&xE3
-AddParamsMove(x5&n12,size_t
-n22);void
-i91
-size_t
-index);void
-DelParams();void
-Become(tW1
-b);inline
-size_t
-GetParamCount(c01
-lJ2)eJ3;y81
-c02&GetParam
-iZ1
-n)yP
-lJ2)[n];y81
-tW1
-GetParam
-iZ1
-n
-c01
-lJ2)[n];y81
-void
-eL3
-iU1
-o)iZ3
-Opcode=o;y81
-iU1
-GetOpcode()yO
-Opcode;y81
-nB
-fphash_t
-GetHash()yO
-Hash;y81
-const
-x5&lJ2
-c01
-y1;y81
-x5&lJ2)yP
-y1;y81
-size_t
-GetDepth()yO
-Depth;y81
-const
-Value_t&GetImmed()yO
-Value;y81
-x83
-GetVar()yO
-lK2
-y81
-x83
-GetFuncNo()yO
-lK2
-y81
-bool
-IsDefined(c01
-GetOpcode()!=nB
-cNop;y81
-bool
-IsImmed(c01
-GetOpcode()==nB
-cImmed;y81
-bool
-IsVar(c01
-GetOpcode()==nB
-iU2;y81
-x83
-GetRefCount()yO
-xB3;}
-void
-ReplaceWithImmed(tX1;void
-e33
-bool
-constantfolding=true);void
-Sort();inline
-void
-Mark_Incompletely_Hashed()iZ3
-Depth=0;y81
-bool
-Is_Incompletely_Hashed()yO
-Depth==0;y81
-const
-tR
-GetOptimizedUsing()yO
-lM2;y81
-void
-SetOptimizedUsing
-iS1
-tR
-g)iZ3
-lM2=g;}
-bool
-RecreateInversionsAndNegations(bool
-prefer_base2=false);void
-tE3;void
-swap(c02&b){data.swap(b.data);}
-bool
-IsIdenticalTo(tW1
-b)const;void
-lD1}
-yO1
-e72
-xK2{int
-xB3;iU1
-Opcode
-iK2
-Value;x83
-lK2
-eK
-Params;nB
-fphash_t
-Hash;size_t
-Depth;const
-tR
-lM2;xK2();xK2
-iS1
-xK2&b);iA
-iU1
-o);iA
-iU1
-o,x83
-f);iA
-tX1;
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-iA
-Value_t&&i);xK2(xK2&&b);
-#endif
-bool
-IsIdenticalTo
-iS1
-xK2&b)const;void
-Sort();void
-Recalculate_Hash_NoRecursion();private:void
-eM1=iS1
-xK2&b);}
-yO1
-c0
-CodeTreeImmed(tX1
-n21
-i
-y8
-xD3());}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-cC1
-CodeTreeImmed
-cX3&&i)n21
-tF2
-i)y8
-xD3());}
-#endif
-cC1
-CodeTreeOp(iU1
-opcode)n21
-opcode
-y8
-OpcodeTag());}
-cC1
-CodeTreeFuncOp(iU1
-opcode,x83
-f)n21
-opcode,f
-y8
-FuncOpcodeTag());}
-cC1
-CodeTreeVar
-lT1
-varno)n21
-varno
-y8
-VarTag());}
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-xL1
-DumpHashes(xE);xL1
-DumpTree(xE);xL1
-DumpTreeWithIndent(xE,const
-eM3&indent="\\"
-);
-#endif
-}
-#endif
-#endif
-#ifndef FPOptimizer_GrammarHH
-#define FPOptimizer_GrammarHH
-t5{tK1
-class
-c02;}
-l33
-lA1{enum
-ImmedConstraint_Value{ValueMask=0x07,Value_AnyNum=0x0,x62=0x1,Value_OddInt=0x2,i11=0x3,Value_NonInteger=0x4,eY1=0x5}
-;enum
-ImmedConstraint_Sign{SignMask=0x18,Sign_AnySign=0x00,nD1=0x08,eZ1=0x10,Sign_NoIdea=0x18}
-;enum
-ImmedConstraint_Oneness{OnenessMask=0x60,Oneness_Any=0x00,Oneness_One=0x20,Oneness_NotOne=0x40}
-;enum
-ImmedConstraint_Constness{ConstnessMask=0x180,Constness_Any=0x00,i01=0x80,Constness_NotConst=0x100}
-;enum
-Modulo_Mode{Modulo_None=0,Modulo_Radians=1}
-;enum
-Situation_Flags{LogicalContextOnly=0x01,NotForIntegers=0x02,OnlyForIntegers=0x04,OnlyForComplex=0x08,NotForComplex=0x10}
-;enum
-nZ2{NumConstant,ParamHolder,SubFunction}
-;enum
-ParamMatchingType{PositionalParams,SelectedParams,AnyParams,GroupFunction}
-;enum
-RuleType{ProduceNewTree,ReplaceParams}
-;
-#ifdef __GNUC__
-# define PACKED_GRAMMAR_ATTRIBUTE __attribute__((packed))
-#else
-# define PACKED_GRAMMAR_ATTRIBUTE
-#endif
-typedef
-std::pair<nZ2,const
-void*>eA2
-yO1
-eA2
-ParamSpec_Extract
-lT1
-paramlist,lJ1)yO1
-bool
-ParamSpec_Compare
-iS1
-void*xC3
-void*b,nZ2
-type);x83
-ParamSpec_GetDepCode
-iS1
-eA2&b);e72
-ParamSpec_ParamHolder{lJ1:8;x83
-constraints:9;x83
-depcode:15;e2
-tK1
-e72
-ParamSpec_NumConstant
-l14
-constvalue;x83
-modulo;}
-;e72
-l71{x83
-param_count:2;x83
-param_list:30;iU1
-subfunc_opcode:8;ParamMatchingType
-match_type:3;x83
-n1:5;e2
-e72
-ParamSpec_SubFunction{l71
-data;x83
-constraints:9;x83
-depcode:7;e2
-e72
-Rule{RuleType
-ruletype:2;x83
-situation_flags:5;x83
-repl_param_count:2+9;x83
-repl_param_list:30;l71
-match_tree;e2
-e72
-Grammar{x83
-rule_count;x83
-short
-rule_list[999
-cT
-extern
-const
-Rule
-grammar_rules[];}
-xL1
-DumpParam
-iS1
-eA2&p,std::ostream&o=cV2);xL1
-DumpParams
-lT1
-paramlist,x83
-count,std::ostream&o=cV2);}
-#endif
-#ifndef M_PI
-#define M_PI 3.1415926535897932384626433832795
-#endif
-#define CONSTANT_POS_INF HUGE_VAL
-#define CONSTANT_NEG_INF (-HUGE_VAL)
-l33
-FUNCTIONPARSERTYPES{tK1
-inline
-Value_t
-fp_const_pihalf()yP
-fp_const_pi
-xF()*yF2;}
-tK1
-inline
-Value_t
-fp_const_twopi()eQ3
-fp_const_pi
-xF());nS3
-xO
-fp_const_twoe()eQ3
-fp_const_e
-xF());nS3
-xO
-fp_const_twoeinv()eQ3
-fp_const_einv
-xF());nS3
-xO
-fp_const_negativezero()yP-Epsilon
-xF::value;}
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-nG1{using
-l33
-lA1;using
-t5;using
-l33
-FUNCTIONPARSERTYPES
-yO1
-class
-MatchInfo{e43
-eO3
-std::pair<bool,eK> >lQ;eK
-cA;eO3
-x83>tT;e43
-MatchInfo():lQ(),cA(),tT(){}
-e43
-bool
-SaveOrTestRestHolder
-lT1
-n1,eA3&iJ1){cT1{lQ
-xF3
-n1+1);lQ
-tS=iJ1
-l43
-if(lQ[n1
-eH3==false){lQ
-tS=iJ1
-l43
-eA3&found=lQ[n1
-eI3;if(iJ1
-eJ3!=found
-eJ3
-cQ
-for
-iZ1
-a=0;a<iJ1
-eJ3;++a)if(!iJ1[a]xI
-found[a])cQ
-lD2}
-void
-SaveRestHolder
-lT1
-n1,eK&iJ1){cT1
-lQ
-xF3
-n1+1);lQ
-tS.swap(iJ1);}
-bool
-SaveOrTestParamHolder
-lT1
-x0,iT1&xG3){if(cA
-eJ3<=x0){cA.xH3
-x0+1);cA
-xF3
-x0);cA
-c52
-xG3
-yQ2
-if(!cA[x0].nX2){cA[x0]=xG3
-l43
-return
-xG3
-xI
-cA[x0]cN2
-SaveMatchedParamIndex(lJ1){tT
-c52
-index);}
-iT1&GetParamHolderValueIfFound
-lT1
-x0)const{static
-iT1
-dummytree;if(cA
-eJ3<=x0)return
-dummytree
-i1
-cA[x0];}
-iT1&GetParamHolderValue
-lT1
-x0
-c01
-cA[x0];}
-bool
-HasRestHolder
-lT1
-n1
-c01
-lQ
-eJ3>n1&&lQ[n1
-eH3==true;}
-eA3&GetRestHolderValues
-lT1
-n1)const{static
-eA3
-empty_result;cT1
-return
-empty_result
-i1
-lQ[n1
-eI3;}
-const
-eO3
-x83>&GetMatchedParamIndexes(c01
-tT;}
-void
-swap(tC
-b){lQ.swap(b.lQ);cA.swap(b.cA);tT.swap(b.tT);}
-tC
-eM1=iS1
-tC
-b){lQ=b.lQ;cA=b.cA;tT=b.tT
-i1*this;}
-}
-;class
-e6;typedef
-xP<e6>cZ;class
-e6{e43
-int
-xB3;e43
-e6():xB3(0){}
-virtual~e6(){}
-}
-;e72
-n31{bool
-found;cZ
-specs;n31(bool
-f):found(f),specs(){}
-n31(bool
-f,const
-cZ&s):found(f),specs(s){}
-}
-;xL1
-SynthesizeRule(t41
-nP1
-tC
-info)yO1
-n31
-TestParam
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info)yO1
-n31
-TestParams(eX&nN,const
-nP1
-const
-cZ&start_at,tC
-info,bool
-iX1
-yO1
-bool
-ApplyGrammar
-iS1
-Grammar&tK2,FPoptimizer_CodeTree::nP1
-bool
-from_logical_context=false);xL1
-ApplyGrammars(FPoptimizer_CodeTree::eR
-yO1
-bool
-IsLogisticallyPlausibleParamsMatch(eX¶ms,const
-eR;}
-l33
-lA1{xL1
-DumpMatch(t41
-nO,const
-FPoptimizer_Optimize::tC
-info,bool
-DidMatch,std::ostream&o=cV2);xL1
-DumpMatch(t41
-nO,const
-FPoptimizer_Optimize::tC
-info,e32
-tO3,std::ostream&o=cV2);}
-#endif
-e42
-lA1::nZ2
-yT1=false);e42
-iU1
-yT1=false);
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;e42
-lA1::nZ2
-yT1){
-#if 1
-e32
-p=0;e23
-opcode){case
-NumConstant:p="NumConstant"
-;lC
-ParamHolder:p="ParamHolder"
-;lC
-SubFunction:p="SubFunction"
-;xY3
-std::ostringstream
-tmp;assert(p);tmp<<p;if(pad)while(tmp.str()eJ3<12)tmp<<' '
-i1
-tmp.str();
-#else
-std::ostringstream
-tmp;tmp<<opcode;if(pad)while(tmp.str()eJ3<5)tmp<<' '
-i1
-tmp.str();
-#endif
-}
-e42
-iU1
-yT1){
-#if 1
-e32
-p=0;e23
-opcode){case
-cAbs:p="cAbs"
-;lC
-cAcos:p="cAcos"
-;lC
-cAcosh:p="cAcosh"
-;lC
-cArg:p="cArg"
-;lC
-cAsin:p="cAsin"
-;lC
-cAsinh:p="cAsinh"
-;lC
-cAtan:p="cAtan"
-;lC
-cAtan2:p="cAtan2"
-;lC
-cAtanh:p="cAtanh"
-;lC
-cCbrt:p="cCbrt"
-;lC
-cCeil:p="cCeil"
-;lC
-cConj:p="cConj"
-;lC
-cCos:p="cCos"
-;lC
-cCosh:p="cCosh"
-;lC
-cCot:p="cCot"
-;lC
-cCsc:p="cCsc"
-;lC
-cExp:p="cExp"
-;lC
-cExp2:p="cExp2"
-;lC
-cFloor:p="cFloor"
-;lC
-cHypot:p="cHypot"
-;lC
-cIf:p="cIf"
-;lC
-cImag:p="cImag"
-;lC
-cInt:p="cInt"
-;lC
-cLog:p="cLog"
-;lC
-cLog2:p="cLog2"
-;lC
-cLog10:p="cLog10"
-;lC
-cMax:p="cMax"
-;lC
-cMin:p="cMin"
-;lC
-cPolar:p="cPolar"
-;lC
-cPow:p="cPow"
-;lC
-cReal:p="cReal"
-;lC
-cSec:p="cSec"
-;lC
-cSin:p="cSin"
-;lC
-cSinh:p="cSinh"
-;lC
-cSqrt:p="cSqrt"
-;lC
-cTan:p="cTan"
-;lC
-cTanh:p="cTanh"
-;lC
-cTrunc:p="cTrunc"
-;lC
-cImmed:p="cImmed"
-;lC
-cJump:p="cJump"
-;lC
-cNeg:p="cNeg"
-;lC
-cAdd:p="cAdd"
-;lC
-cSub:p="cSub"
-;lC
-cMul:p="cMul"
-;lC
-cDiv:p="cDiv"
-;lC
-cMod:p="cMod"
-;lC
-cEqual:p="cEqual"
-;lC
-i51:p="cNEqual"
-;lC
-cLess:p="cLess"
-;lC
-cLessOrEq:p="cLessOrEq"
-;lC
-cGreater:p="cGreater"
-;lC
-cGreaterOrEq:p="cGreaterOrEq"
-;lC
-cNot:p="cNot"
-;lC
-cAnd:p="cAnd"
-;lC
-cOr:p="cOr"
-;lC
-cDeg:p="cDeg"
-;lC
-cRad:p="cRad"
-;lC
-cFCall:p="cFCall"
-;lC
-cPCall:p="cPCall"
-;break;
-#ifdef FP_SUPPORT_OPTIMIZER
-case
-cFetch:p="cFetch"
-;lC
-cPopNMov:p="cPopNMov"
-;lC
-cQ3:p="cLog2by"
-;lC
-cNop:p="cNop"
-;break;
-#endif
-case
-cSinCos:p="cSinCos"
-;lC
-cSinhCosh:p="cSinhCosh"
-;lC
-cC3:p="cAbsNot"
-;lC
-cAbsNotNot:p="cAbsNotNot"
-;lC
-cAbsAnd:p="cAbsAnd"
-;lC
-cAbsOr:p="cAbsOr"
-;lC
-cAbsIf:p="cAbsIf"
-;lC
-cDup:p="cDup"
-;lC
-cInv:p="cInv"
-;lC
-cSqr:p="cSqr"
-;lC
-cRDiv:p="cRDiv"
-;lC
-cRSub:p="cRSub"
-;lC
-cNotNot:p="cNotNot"
-;lC
-cRSqrt:p="cRSqrt"
-;lC
-iU2:p="VarBegin"
-;xY3
-std::ostringstream
-tmp;assert(p);tmp<<p;if(pad)while(tmp.str()eJ3<12)tmp<<' '
-i1
-tmp.str();
-#else
-std::ostringstream
-tmp;tmp<<opcode;if(pad)while(tmp.str()eJ3<5)tmp<<' '
-i1
-tmp.str();
-#endif
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-#ifndef FP_GENERATING_POWI_TABLE
-enum{MAX_POWI_BYTECODE_LENGTH=20}
-;
-#else
-enum{MAX_POWI_BYTECODE_LENGTH=999}
-;
-#endif
-enum{MAX_MULI_BYTECODE_LENGTH=3}
-;l33
-xK1{tK1
-class
-ByteCodeSynth{e43
-ByteCodeSynth():eN1(),Immed(),cI(),xQ(0),StackMax(0){eN1.xH3
-64);Immed.xH3
-8);cI.xH3
-16
-cN2
-Pull(eO3
-x83>&bc,std
-xM3
-xF&imm,size_t&StackTop_max){for
-lT1
-a=0;a<n41;++a){eN1[a]&=~0x80000000u;}
-eN1.swap(bc);Immed.swap(imm);StackTop_max=StackMax;}
-size_t
-GetByteCodeSize(c01
-n41;}
-size_t
-GetStackTop(c01
-xQ;}
-void
-PushVar
-lT1
-varno){eN1
-c52
-varno);xI3
-1
-cN2
-PushImmed
-cX3
-immed
-nL
-eN1
-c52
-cImmed);Immed
-c52
-immed);xI3
-1
-cN2
-StackTopIs(nO,int
-offset=0){if((int)xQ>offset){cI[xQ
-nK2
-first=true;cI[xQ
-nK2
-second=tree;}
-}
-bool
-IsStackTop(nO,int
-offset=0
-c01(int)xQ>offset&&cI[xQ
-nK2
-first&&cI[xQ
-nK2
-second
-xI
-tree);y81
-void
-EatNParams
-lT1
-eat_count){xQ-=eat_count;}
-void
-ProducedNParams
-lT1
-produce_count){xI3
-produce_count
-cN2
-DoPopNMov
-iZ1
-eB2,size_t
-srcpos
-nL
-eN1
-c52
-cPopNMov
-e53
-eB2
-e53
-srcpos);xM1
-srcpos+1);cI[eB2]=cI[srcpos];xM1
-eB2+1
-cN2
-DoDup
-iZ1
-xJ3
-nL
-if(xJ3==xQ-1){eN1
-c52
-cDup);}
-else{eN1
-c52
-cFetch
-e53
-xJ3);}
-xI3
-1);cI[xQ-1]=cI[xJ3];}
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-tP1
-int>void
-Dump(){std::ostream&o=cV2;o<<"Stack state now("
-<<xQ<<"):\n"
-e73
-0;a<xQ;++a){o<<a<<": "
-;if(cI[a
-eH3){nO=cI[a
-eI3;o<<'['<<std::hex<<(void*)(&tree.lJ2))<<std::dec<<','<<tree.GetRefCount()<<']'
-iL2
-tree,o);}
-else
-o<<"?"
-iV3}
-o<<std::flush;}
-#endif
-size_t
-xK3
-nO)const{for
-iZ1
-a=xQ;a-->0;)if(cI[a
-eH3&&cI[a
-eI3
-xI
-tree
-y03
-a
-i1~size_t(0);}
-bool
-Find(nO
-c01
-xK3
-tree)!=~size_t(0);}
-bool
-FindAndDup(nO){size_t
-pos=xK3
-tree);if(pos!=~size_t(0)){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iX3"duplicate at ["
-<<pos<<"]: "
-iL2
-tree
-lE2" -- issuing cDup or cFetch\n"
-;
-#endif
-DoDup(pos
-yQ2
-return
-t23
-e72
-IfData{size_t
-ofs;}
-;void
-SynthIfStep1
-c62,iU1
-op
-x21
-c72=n41;eN1
-c52
-op
-eO
-eO
-cN2
-SynthIfStep2
-c62
-x21
-eN1
-iK1
-xL3+2);eN1
-iK1
-2
-y5
-lN2
-c72=n41;eN1
-c52
-cJump
-eO
-eO
-cN2
-SynthIfStep3
-c62
-x21
-eN1.back()|=0x80000000u;eN1
-iK1
-xL3-1);eN1
-iK1
-2
-y5
-lN2
-xI3
-1
-iY1
-0;a<c72;++a){if(eN1[a]==cJump&&eN1[a+1]==(0x80000000u|(c72-1))){eN1[a+xL3-1);eN1[a+2
-y5
-lN2
-c73(eN1[a]){case
-cAbsIf:case
-cIf:case
-cJump:case
-cPopNMov:a+=2;lC
-cFCall:case
-cPCall:case
-cFetch:a+=1;break;yF3
-xY3}
-}
-protected:void
-xM1
-size_t
-value){xQ=value;if(xQ>l53{StackMax=xQ;cI
-xF3
-l53;}
-}
-protected:eO3
-x83>eN1;std
-xM3
-xF
-Immed;eO3
-std::pair<bool,FPoptimizer_CodeTree::yZ2> >cI;size_t
-xQ;size_t
-StackMax;private:void
-incStackPtr(){if(xQ+2>l53
-cI
-xF3
-StackMax=xQ+2);}
-tP1
-bool
-IsIntType,bool
-IsComplexType>e72
-c82{}
-;e43
-void
-AddOperation
-eZ2,x83
-eat_count,x83
-produce_count=1){EatNParams(eat_count);nR1(opcode);ProducedNParams(produce_count
-cN2
-nR1
-eZ2,c82<false,false>yQ
-false,true>yQ
-true,false>yQ
-true,true>);inline
-void
-nR1
-eZ2){nR1(opcode,c82<bool(nB
-IsIntType
-xF::nS3),bool(nB
-IsComplexType
-xF::nS3)>());}
-}
-yO1
-e72
-SequenceOpCode
-yO1
-e72
-tU1{static
-cG
-AddSequence;static
-cG
-MulSequence;}
-;xL1
-x01
-long
-count,cG&eQ,xI1;}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33
-xK1{tK1
-e72
-SequenceOpCode
-l14
-basevalue;x83
-op_flip;x83
-op_normal,op_normal_flip;x83
-op_inverse,op_inverse_flip;}
-yO1
-cG
-tU1
-xF::AddSequence={xH1,cNeg
-x9
-cAdd,cSub,cRSub}
-yO1
-cG
-tU1
-xF::MulSequence={e62
-1),cInv,cMul,cMul,cDiv,cRDiv}
-;
-#define findName(a,b,c) "var"
-#define TryCompilePowi(o) false
-#define mData this
-#define mByteCode eN1
-#define mImmed Immed
-nL2
-false,false>)x31
-# define FP_FLOAT_VERSION 1
-# define FP_COMPLEX_VERSION 0
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-nL2
-true,false>)x31
-# define FP_FLOAT_VERSION 0
-# define FP_COMPLEX_VERSION 0
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-nL2
-false,true>)x31
-# define FP_FLOAT_VERSION 1
-# define FP_COMPLEX_VERSION 1
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-nL2
-true,true>)x31
-# define FP_FLOAT_VERSION 0
-# define FP_COMPLEX_VERSION 1
-# include "extrasrc/fp_opcode_add.inc"
-# undef FP_COMPLEX_VERSION
-# undef FP_FLOAT_VERSION
-}
-#endif
-#undef findName
-#undef mImmed
-#undef mByteCode
-#undef mData
-#undef TryCompilePowi
-}
-using
-l33
-xK1;
-#define POWI_TABLE_SIZE 256
-#define POWI_WINDOW_SIZE 3
-l33
-xK1{
-#ifndef FP_GENERATING_POWI_TABLE
-extern
-const
-x83
-char
-powi_table[POWI_TABLE_SIZE];const
-#endif
-x83
-char
-powi_table[POWI_TABLE_SIZE]={0,1,1,1,2,1,2,1,xN3
-4,1,2,xP3
-2,1,xN3
-8,cV3
-xQ3
-15,1,16,1,2,1,4,1,2,xP3
-2,1,4,cV3
-1,16,1,25,xQ3
-27,5,8,3,2,1,30,1,31,3,32,1,2,1,xN3
-8,1,2,xQ3
-39,1,16,137,2,1,4,cV3
-xP3
-45,135,4,31,2,5,32,1,2,131,50,1,51,1,8,3,2,1,54,1,55,3,16,1,57,133,4,137,2,135,60,1,61,3,62,133,63,1,iL1
-131,iL1
-139,lO2
-e7
-30,1,130,137,2,31,lO2
-e7
-e7
-130,cV3
-1,e7
-e7
-2,1,130,133,iL1
-61,130,133,62,139,130,137,e7
-lO2
-e7
-e7
-iL1
-131,e7
-e7
-130,131,2,133,lO2
-130,141,e7
-130,cV3
-1,e7
-5,135,e7
-lO2
-e7
-lO2
-130,133,130,141,130,131,e7
-e7
-2,131}
-;}
-static
-x03
-c1=256;
-#define FPO(x)
-l33{class
-PowiCache{private:int
-iM[c1];int
-iM1[c1];e43
-PowiCache():iM(),iM1(){iM[1]=1;}
-bool
-Plan_Add(c11,int
-count){cD1>=c1
-cQ
-iM1[t02+=count
-i1
-iM[t02!=0;}
-void
-l63
-c11){cD1<c1)iM[t02=1;}
-void
-Start
-iZ1
-value1_pos){for(int
-n=2;n<c1;++n)iM[n]=-1;Remember(1,value1_pos);DumpContents();}
-int
-Find(c11)const{cD1<c1){if(iM[t02>=0){FPO(iC3(iG3,"* I found %ld from cache (%u,%d)\n",value,(unsigned)cache[value],iD3 value]))i1
-iM[t02;}
-eE3-1;}
-void
-Remember(c11,size_t
-iQ3){cD1>=c1)return;FPO(iC3(iG3,"* Remembering that %ld can be found at %u (%d uses remain)\n",value,(unsigned)iQ3,iD3 value]));iM[t02=(int)iQ3;}
-void
-DumpContents()const{FPO(for(int a=1;a<POWI_CACHE_SIZE;++a)if(cache[a]>=0||iD3 a]>0){iC3(iG3,"== cache: sp=%d, val=%d, needs=%d\n",cache[a],a,iD3 a]);})}
-int
-UseGetNeeded(c11){cD1>=0&&value<c1)return--iM1[t02
-i1
-0;}
-}
-yO1
-size_t
-y6
-long
-count
-iQ1
-cG&eQ,xI1;xL1
-c21
-size_t
-apos,long
-aval,size_t
-bpos,long
-bval
-iQ1
-x83
-cumulation_opcode,x83
-cimulation_opcode_flip,xI1;void
-lB1
-c11
-iQ1
-int
-need_count,int
-lC1=0){cD1<1)return;
-#ifdef FP_GENERATING_POWI_TABLE
-if(lC1>32)throw
-false;
-#endif
-if(iM.Plan_Add(value,need_count
-y03;long
-xR3
-1;cD1<POWI_TABLE_SIZE){xR3
-powi_table[t02
-xZ3&128){half&=127
-xZ3&64)xR3-t12
-FPO(iC3(iG3,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,value/half));lB1
-half
-xO3
-iM.l63
-half)i1;}
-iP1
-half&64){xR3-t12}
-}
-else
-cD1&1)xR3
-value&((1<<POWI_WINDOW_SIZE)-1);else
-xR3
-value/2;long
-cL=value-half
-xZ3>cL||half<0)std::swap(half,cL);FPO(iC3(iG3,"value=%ld, half=%ld, otherhalf=%ld\n",value,half,otherhalf))xZ3==cL){lB1
-half,iM,2,lC1+1);}
-else{lB1
-half
-xO3
-lB1
-cL>0?cL:-cL
-xO3}
-iM.l63
-value);}
-tK1
-size_t
-y6
-c11
-iQ1
-cG&eQ,xI1{int
-xT3=iM.Find(value);if(xT3>=0)yP
-xT3;}
-long
-xR3
-1;cD1<POWI_TABLE_SIZE){xR3
-powi_table[t02
-xZ3&128){half&=127
-xZ3&64)xR3-t12
-FPO(iC3(iG3,"* I want %ld, my plan is %ld * %ld\n",value,half,value/half));size_t
-xM2=y6
-half
-cE1
-if(iM
-lP2
-half)>0||xM2!=cG1){iN1
-xM2)xP2
-half,cG1);}
-x01
-value/half
-e63
-size_t
-iQ3=cG1
-xP2
-value,iQ3);iM.DumpContents()i1
-iQ3;}
-iP1
-half&64){xR3-t12}
-}
-else
-cD1&1)xR3
-value&((1<<POWI_WINDOW_SIZE)-1);else
-xR3
-value/2;long
-cL=value-half
-xZ3>cL||half<0)std::swap(half,cL);FPO(iC3(iG3,"* I want %ld, my plan is %ld + %ld\n",value,half,value-half))xZ3==cL){size_t
-xM2=y6
-half
-cE1
-c21
-xM2,half,xM2,half,iM,eQ.op_normal,eQ.op_normal_flip,c92}
-else{long
-part1=half;long
-part2=cL>0?cL:-cL;size_t
-part1_pos=y6
-part1
-cE1
-size_t
-part2_pos=y6
-part2
-cE1
-FPO(iC3(iG3,"Subdivide(%ld: %ld, %ld)\n",value,half,otherhalf));c21
-part1_pos,part1,part2_pos,part2,iM,cL>0?eQ.op_normal:eQ.op_inverse,cL>0?eQ.op_normal_flip:eQ.op_inverse_flip,c92}
-size_t
-iQ3=cG1
-xP2
-value,iQ3);iM.DumpContents()i1
-iQ3;}
-xL1
-c21
-size_t
-apos,long
-aval,size_t
-bpos,long
-bval
-iQ1
-x83
-cumulation_opcode,x83
-cumulation_opcode_flip,xI1{int
-a_needed=iM
-lP2
-aval);int
-xU3=iM
-lP2
-bval);bool
-flipped
-eW3
-#define DUP_BOTH() do{if(apos<bpos){size_t tmp=apos;apos=bpos;bpos=tmp e41 FPO(iC3(iG3,"-> " iO3 iO3"op\n",(unsigned)apos,(unsigned)bpos));iN1 apos);iN1 apos==bpos?cG1:bpos);}while(0)
-#define DUP_ONE(p) do{FPO(iC3(iG3,"-> " iO3"op\n",(unsigned)p));iN1 p);}while(0)
-if(a_needed>0){if(xU3>0){nM2}
-cJ3
-bpos!=cG1)nM2
-else{x02
-e41}
-}
-iP1
-xU3>0){if(apos!=cG1)nM2
-else
-DUP_ONE(bpos);}
-cJ3
-apos==bpos&&apos==cG1)x02;iP1
-apos==cG1&&bpos==xV3
-2){FPO(iC3(iG3,"-> op\n"))e41
-iP1
-apos==xV3
-2&&bpos==cG1)FPO(iC3(iG3,"-> op\n"));iP1
-apos==cG1)DUP_ONE(bpos);iP1
-bpos==cG1){x02
-e41
-else
-nM2}
-yB1
-flipped?cumulation_opcode_flip:cumulation_opcode,2);}
-xL1
-cH1
-long
-count,cG&eQ,xI1{while
-cW3<256){int
-xR3
-xK1::powi_table[count]xZ3&128){half&=127;cH1
-half
-e63
-count/=half;}
-else
-xY3
-if
-cW3==1)return;if(!cW3&1)){yB1
-cSqr,1);cH1
-count/2
-e63}
-else{iN1
-cG1);cH1
-count-1
-e63
-yB1
-cMul,2);}
-}
-}
-l33
-xK1{xL1
-x01
-long
-count,cG&eQ,xI1{if
-cW3==0)t71
-eQ.basevalue);else{bool
-t22
-eW3
-if
-cW3<0){t22=true;count=-count;}
-if(false)cH1
-count
-e63
-iP1
-count>1){PowiCache
-iM;lB1
-count,iM,1);size_t
-xO1=synth.GetStackTop();iM.Start(cG1);FPO(iC3(iG3,"Calculating result for %ld...\n",count));size_t
-xN2=y6
-count
-cE1
-size_t
-n_excess=xV3
-xO1;if(n_excess>0||xN2!=xO1-1){synth.DoPopNMov(xO1-1,xN2);}
-}
-if(t22)yB1
-eQ.op_flip,1);}
-}
-}
-#endif
-#ifndef FPOptimizer_ValueRangeHH
-#define FPOptimizer_ValueRangeHH
-t5{l33
-l73{l01
-e72
-Comp{}
-;tP1>e72
-Comp<nB
-cLess>l83<nA
-cLessOrEq>l83<=nA
-cGreater>l83>nA
-cGreaterOrEq>l83>=nA
-cEqual>l83==nA
-i51>l83!=b;}
-}
-;}
-tK1
-e72
-cI1
-l14
-val;bool
-known;cI1():val(),known(false){}
-cI1(tV1):val(v),known(true){y81
-l93
-tV1){known=true;val=v;}
-l93
-xW3
-Value_t),cI1
-y7)val=iE2
-l93
-xW3
-const
-Value_t&),cI1
-y7)val=iE2
-l01
-void
-set_if
-cX3
-v,xW3
-Value_t),cI1
-y7&&l73::Comp<Compare>()(val,v))val=iE2
-l01
-void
-set_if(tV1,xW3
-const
-Value_t&),cI1
-y7&&l73::Comp<Compare>()(val,v))val=iE2}
-yO1
-e72
-range{cI1
-xF
-min,max;range():min(),max(){}
-range
-cX3
-mi,Value_t
-ma):min(mi),max(ma){}
-range(bool,Value_t
-ma):min(),max(ma){}
-range
-cX3
-mi,bool):min(mi),max(){}
-void
-set_abs();void
-set_neg();}
-yO1
-bool
-IsLogicalTrueValue
-iS1
-yD3&p,bool
-abs)yO1
-bool
-IsLogicalFalseValue
-iS1
-yD3&p,bool
-abs);}
-#endif
-#ifndef FPOptimizer_RangeEstimationHH
-#define FPOptimizer_RangeEstimationHH
-t5{enum
-TriTruthValue{iF2,xX3,Unknown}
-yO1
-yD3
-CalculateResultBoundaries
-iS1
-eR
-yO1
-bool
-IsLogicalValue
-iS1
-eR
-yO1
-TriTruthValue
-GetIntegerInfo
-iS1
-eR
-yO1
-xP1
-GetEvennessInfo
-iS1
-eR{if(!tree
-tD1)return
-Unknown;yL1=tree
-x41;if(nB
-isEvenInteger(value
-y13
-nB
-isOddInteger(value
-y23
-tK1
-xP1
-GetPositivityInfo
-iS1
-eR{yD3
-p=CalculateResultBoundaries(tree);if(p
-yI&&p
-yM>=e62
-y13
-p
-e61
-l61
-y23
-tK1
-xP1
-GetLogicalValue
-iS1
-nP1
-bool
-abs){yD3
-p=CalculateResultBoundaries(tree);if(IsLogicalTrueValue(p,abs
-y13
-IsLogicalFalseValue(p,abs
-y23}
-#endif
-#ifndef FPOptimizer_ConstantFoldingHH
-#define FPOptimizer_ConstantFoldingHH
-t5{xL1
-ConstantFolding(eR;}
-#endif
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-ComparisonSetBase{enum{eB3=0x1,Eq_Mask=0x2,Le_Mask=0x3,eC3=0x4,eD3=0x5,Ge_Mask=0x6}
-;static
-int
-Swap_Mask(int
-m)yP(m&Eq_Mask)|((m&eB3)?eC3:0)|((m&eC3)?eB3:0);}
-enum
-c31{Ok,BecomeZero,BecomeOne,n91}
-;enum
-x12{cond_or,iG2,iH2,iI2}
-;}
-yO1
-e72
-ComparisonSet:public
-ComparisonSetBase{e72
-t32{yZ2
-a
-tX
-b;int
-relationship;t32():a(),b(),relationship(){}
-}
-;eO3
-t32>tH;e72
-Item{yZ2
-value;bool
-cA2;Item():value(),cA2(false){}
-}
-;eO3
-Item>cJ1;int
-xQ1;ComparisonSet():tH(),cJ1(),xQ1(0){}
-c31
-AddItem
-iR1
-a,bool
-cA2,x12
-type){for
-iZ1
-c=0;c<cJ1
-eJ3;++c)if(cJ1[c].value
-xI
-a)){if(cA2!=cJ1[c].cA2){l11
-cU1
-case
-iI2:cJ1.erase(cJ1.begin()+c);xQ1
-cB2
-case
-iG2:case
-iH2:cW1}
-eE3
-n91;}
-Item
-pole;pole.value=a;pole.cA2=cA2;cJ1
-c52
-pole)i1
-Ok;}
-c31
-AddRelationship(yZ2
-a,yZ2
-b,int
-tY1,x12
-type){l11
-if(tY1==7)cU1
-lC
-iI2:if(tY1==7){xQ1
-cB2}
-lC
-iG2:case
-iH2:if(tY1==0)cW1
-xY3
-if(!(a.GetHash()<b.GetHash())){a.swap(b);tY1=Swap_Mask(tY1);}
-for
-iZ1
-c=0;c<tH
-eJ3;++c){if(tH[c].a
-xI
-a)&&tH[c].b
-xI
-b)){l11{int
-y33=xQ2|tY1;if(y33==7)cU1
-xQ2=y33;xY3
-case
-iG2:case
-iH2:{int
-y33=xQ2&tY1;if(y33==0)cW1
-xQ2=y33;xY3
-case
-iI2:{int
-newrel_or=xQ2|tY1;int
-xR2=xQ2&tY1;lQ2
-5&&xR2==0){xQ2=eD3
-i1
-n91;}
-lQ2
-7&&xR2==0){xQ1+=1;tH.erase(tH.begin()+c)i1
-n91;}
-lQ2
-7&&xR2==Eq_Mask){xQ2=Eq_Mask;xQ1
-cB2}
-yA1}
-eE3
-n91;}
-}
-t32
-comp;comp.a=a;comp.b=b;comp.relationship=tY1;tH
-c52
-comp)i1
-Ok;}
-}
-;nN1
-Value_t,x93
-CondType>bool
-ConstantFolding_LogicCommon(nP1
-CondType
-xF1,bool
-xS2){bool
-should_regenerate
-eW3
-ComparisonSet
-xF
-comp;x51{x93
-c8
-c31
-cY3=c8
-Ok;iT1&atree=xW
-a);e23
-atree
-nC){case
-cEqual
-lG
-Eq_Mask
-e12
-i51
-lG
-eD3
-e12
-cLess
-lG
-eB3
-e12
-cLessOrEq
-lG
-Le_Mask
-e12
-cGreater
-lG
-eC3
-e12
-cGreaterOrEq
-lG
-Ge_Mask
-e12
-cNot:cY3
-cV1
-l8
-0),true
-e12
-cNotNot:cY3
-cV1
-l8
-0),false,xF1);break;yF3
-if(xS2||IsLogicalValue(atree))cY3
-cV1,false,xF1);c73(cY3){ReplaceTreeWithZero:nU
-0)i1
-true;ReplaceTreeWithOne:nU
-1);nZ
-c8
-Ok:lC
-c8
-BecomeZero
-t7
-c8
-BecomeOne:iD
-c8
-n91:c61
-xY3}
-if(should_regenerate){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_LogicCommon: "
-cR
-#endif
-if(xS2){tree.DelParams();}
-else{for
-l41{iT1&atree=xW
-a);if(IsLogicalValue(atree))iZ);}
-}
-for
-iZ1
-a=0;a<comp.cJ1
-eJ3;++a){if(comp.cJ1[a].cA2
-lA3
-cNot);r.c7
-r.lR2
-iP1!xS2
-lA3
-cNotNot);r.c7
-r.lR2
-else
-tree.c7}
-for
-iZ1
-a=0;a<comp.tH
-eJ3;++a
-lA3
-cNop);e23
-comp.tH[a
-eE){case
-c8
-eB3:r
-iH
-cLess);lC
-c8
-Eq_Mask:r
-iH
-cEqual);lC
-c8
-eC3:r
-iH
-cGreater);lC
-c8
-Le_Mask:r
-iH
-cLessOrEq);lC
-c8
-eD3:r
-iH
-i51);lC
-c8
-Ge_Mask:r
-iH
-cGreaterOrEq
-e02
-r
-c91
-comp.tH[a].a);r
-c91
-comp.tH[a].b);r.lR2
-if(comp.xQ1!=0)tree.yA
-e62
-comp.xQ1)));
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_LogicCommon: "
-cR
-#endif
-lD2
-eE3
-t23
-yP1
-ConstantFolding_AndLogic(iM3(tree.GetOpcode()==cAnd||tree.GetOpcode()==cAbsAnd)i1
-nI
-iG2,true);}
-yP1
-ConstantFolding_OrLogic(iM3(tree.GetOpcode()==cOr||tree.GetOpcode()==cAbsOr)i1
-nI
-cond_or,true);}
-yP1
-ConstantFolding_AddLogicItems(iM3(tree.GetOpcode()==cAdd)i1
-nI
-iI2,false);}
-yP1
-ConstantFolding_MulLogicItems(iM3(tree.GetOpcode()==cMul)i1
-nI
-iH2,false);}
-}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-CollectionSetBase{enum
-xR1{Ok,n91}
-;}
-yO1
-e72
-CollectionSet:public
-CollectionSetBase{e72
-c41{yZ2
-value
-tX
-xT2;bool
-e0;c41():value(),xT2(),e0(false){}
-c41
-iR1
-v,iT1&f):value(v),xT2(f),e0(false){}
-}
-;std::multimap<fphash_t,c41>iN;typedef
-x93
-std::multimap<fphash_t,c41>::y83
-xS1;CollectionSet():iN(){}
-xS1
-FindIdenticalValueTo
-iR1
-value){fphash_t
-hash=value.GetHash();for(xS1
-i=iN.xU2
-hash);i!=iN.cX1
-hash;++i){cD1
-xI
-i
-eC2.value
-y03
-i;eE3
-iN.end();}
-bool
-Found
-iS1
-xS1&b)yP
-b!=iN.end();}
-xR1
-AddCollectionTo
-iR1
-xT2,const
-xS1&into_which){c41&c=into_which
-eC2;if(c.e0)c.xT2
-cS
-xT2);else{yZ2
-add;add
-iH
-cAdd);add
-c91
-c.xT2);add
-cS
-xT2);c.xT2.swap(add);c.e0=true;eE3
-n91;}
-xR1
-x22
-iR1
-value,iT1&xT2){const
-fphash_t
-hash=value.GetHash();xS1
-i=iN.xU2
-hash);for(;i!=iN.cX1
-hash;++i){if(i
-eC2.value
-xI
-value
-y03
-AddCollectionTo(xT2,i);}
-iN.y43,std::make_pair(hash,c41(value,xT2)))i1
-Ok;}
-xR1
-x22
-iR1
-a)yP
-x22(a,nA1
-1)));}
-}
-yO1
-e72
-ConstantExponentCollection{typedef
-eK
-y63;typedef
-std::x71
-xV2;eO3
-xV2>data;ConstantExponentCollection():data(){}
-void
-MoveToSet_Unique
-iS1
-Value_t&eP1&eQ1){data
-c52
-std::x71(eP1()));data.back().second.swap(eQ1
-cN2
-MoveToSet_NonUnique
-iS1
-Value_t&eP1&eQ1){x93
-eO3
-xV2>::y83
-i=std::xU2
-data.iJ2
-data.end(),exponent,Compare1st());if(i!=data.cX1
-exponent){i
-eC2.y43
-eC2.end(),eQ1.iJ2
-eQ1.end());}
-else{data.y43,std::x71(exponent,eQ1));}
-}
-bool
-iA2{bool
-changed
-eW3
-std::sort(data.iJ2
-data.end(),Compare1st());redo:for
-iZ1
-a=0;a
-eR3
-a)l14
-exp_a=data[a
-eH3;lG3
-exp_a,e62
-1)))yA1
-for
-iZ1
-b=a+1;b
-eR3
-b)l14
-exp_b=data[b
-eH3
-iK2
-xW2=exp_b-exp_a;if(xW2>=fp_abs(exp_a))break
-iK2
-exp_diff_still_probable_integer=xW2*e62
-16);if(t42
-exp_diff_still_probable_integer)&&!(t42
-exp_b)&&!t42
-xW2))){y63&a_set=lS2;y63&b_set=data[b
-eI3;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantExponentCollection iteration:\n"
-;Dump(cV2);
-#endif
-if(isEvenInteger(exp_b)&&!isEvenInteger(xW2+exp_a)nQ
-tmp2;tmp2
-iH
-cMul);tmp2
-iF1
-b_set);tmp2
-iW1
-tX
-tmp;tmp
-iH
-cAbs);tmp
-c91
-tmp2);tmp
-iW1;b_set
-xF3
-1);b_set[0
-tQ3
-tmp);}
-a_set.insert(a_set.end(),b_set.iJ2
-b_set.end());y63
-b_copy=b_set;data.erase(data.begin()+b);MoveToSet_NonUnique(xW2,b_copy);yS1
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantExponentCollection iteration:\n"
-;Dump(cV2);
-#endif
-cJ}
-}
-eE3
-changed;}
-#ifdef DEBUG_SUBSTITUTIONS
-void
-Dump(std::ostream&out){for
-iZ1
-a=0;a
-eR3
-a){out.precision(12);out<<data[a
-eH3<<": "
-;e11
-lS2
-eJ3;++b){if(b>0)out<<'*'
-iL2
-lS2[b],out);}
-out<<std::endl;}
-}
-#endif
-}
-yO1
-static
-yZ2
-x81
-yZ2&value,bool&xK
-yY3
-value
-nC){case
-cPow:{yZ2
-eD2
-value
-l8
-1);value.y91
-i1
-exponent;}
-case
-cRSqrt:value.y91;xK=true
-i1
-nA1-0.5))t83
-cInv:value.y91;xK=true
-i1
-nA1-1));yF3
-xY3
-return
-nA1
-1));}
-cB1
-void
-eR1
-eS1&mul,const
-nP1
-iT1&xT2,bool&c51
-bool&xK){for
-iZ1
-a=0;a<yC++a
-nQ
-value(xW
-a))tX
-exponent(x81
-value,xK));if(!xT2
-tD1||xT2
-x41!=e62
-1.0)nQ
-cY1;cY1
-iH
-cMul);cY1
-cS
-tU2
-cY1
-cS
-xT2);cY1
-iW1
-eX3.swap(cY1);}
-#if 0 /* FIXME: This does not work */
-cD1
-nC==cMul){if(1){bool
-exponent_is_even=exponent
-tD1&&isEvenInteger(exponent
-x41);e11
-value.eZ3{bool
-tmp=false
-tX
-val(value
-l8
-b))tX
-exp(x81
-val,tmp));if(exponent_is_even||(exp
-tD1&&isEvenInteger(exp
-x41))nQ
-cY1;cY1
-iH
-cMul);cY1
-cS
-tU2
-cY1
-c91
-exp);cY1.ConstantFolding();if(!cY1
-tD1||!isEvenInteger(cY1
-x41)){goto
-cannot_adopt_mul;}
-}
-}
-}
-eR1
-mul,value,exponent,c51
-xK);}
-else
-cannot_adopt_mul:
-#endif
-{if(mul.x22(value,exponent)==CollectionSetBase::n91)c61}
-}
-}
-yP1
-ConstantFolding_MulGrouping(eR{bool
-xK
-eW3
-bool
-should_regenerate
-eW3
-eS1
-mul;eR1
-mul
-cU3,nA1
-1)),c51
-xK);typedef
-std::pair<yZ2,eK>eT1;typedef
-std::multimap<fphash_t,eT1>cK1;cK1
-iJ;for(x93
-eS1::xS1
-j=mul.iN.y73
-j!=mul.iN.end();++j
-nQ&value=j
-eC2.value
-tX&eD2
-j
-eC2.xT2;if(j
-eC2.e0)exponent
-iW1;const
-fphash_t
-eU1=exponent.GetHash();x93
-cK1::y83
-i=iJ.xU2
-eU1);for(;i!=iJ.cX1
-eU1;++i)if(i
-eC2.first
-xI
-exponent)){if(!exponent
-tD1||!cZ1
-x41,e62
-1)))c61
-i
-eC2.second
-c52
-value);goto
-skip_b;}
-iJ.y43,std::make_pair(eU1,std::make_pair(exponent,eK
-iZ1(1),value))));skip_b:;}
-#ifdef FP_MUL_COMBINE_EXPONENTS
-ConstantExponentCollection
-xF
-e01;for(x93
-cK1::y83
-j,i=iJ.y73
-i!=iJ.end();i=j){j=i;++j;eT1&list=i
-eC2;x32.lV1
-eD2
-list.first
-x41;if(!(exponent==xG1)e01.MoveToSet_Unique(exponent,list
-iB2
-iJ.erase(i);}
-}
-if(e01.iA2)c61
-#endif
-if(should_regenerate
-nQ
-before=tree;before.lD1
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_MulGrouping: "
-iL2
-before
-lE2"\n"
-;
-#endif
-tree.DelParams();for(x93
-cK1::y83
-i=iJ.y73
-i!=iJ.end();++i){eT1&list=i
-eC2;
-#ifndef FP_MUL_COMBINE_EXPONENTS
-x32.lV1
-eD2
-list.first
-x41;if(exponent==xG1
-yA1
-if(cZ1
-nH2
-tree.AddParamsMove(list
-iB2
-yA1}
-}
-#endif
-yZ2
-mul;mul
-iH
-cMul);mul
-iF1
-list
-iB2
-mul
-iW1;if(xK&&list.first
-tD1){x32
-x41==e62
-1)/e62
-3)nQ
-cbrt;cbrt
-iH
-cCbrt);cbrt.e8
-cbrt.lT2
-cbrt);yA1
-cV
-0.5)nQ
-sqrt;sqrt
-iH
-cSqrt);sqrt.e8
-sqrt.lT2
-sqrt);yA1
-cV-0.5)nQ
-rsqrt;rsqrt
-iH
-cRSqrt);rsqrt.e8
-rsqrt.lT2
-rsqrt);yA1
-cV-1)nQ
-inv;inv
-iH
-cInv);inv.e8
-inv.lT2
-inv);yA1}
-}
-yZ2
-pow;pow
-iH
-cPow);pow.e8
-pow
-c91
-list.first);pow.lT2
-pow);}
-#ifdef FP_MUL_COMBINE_EXPONENTS
-iJ.clear(iY1
-0;a<iB
-eJ3;++a)l14
-eD2
-iB[a
-eH3;if(cZ1
-nH2
-tree.AddParamsMove(iB[a]iB2
-yA1}
-yZ2
-mul;mul
-iH
-cMul);mul
-iF1
-iB[a]iB2
-mul
-iW1
-tX
-pow;pow
-iH
-cPow);pow.e8
-pow.yA
-exponent));pow.lT2
-pow);}
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_MulGrouping: "
-cR
-#endif
-return!tree
-xI
-before);eE3
-t23
-yP1
-ConstantFolding_AddGrouping(eR{bool
-should_regenerate
-eW3
-eS1
-add;x51{if(xW
-a)nC==cMul)yA1
-if(add.x22(xW
-a))==CollectionSetBase::n91)c61}
-cY2
-lU2
-l51);size_t
-tD=0;x51{iT1&mulgroup=xW
-a);if
-eH2
-nC==cMul){e11
-cA1
-eZ3{if
-eH2
-l8
-b)tD1)yA1
-x93
-eS1::xS1
-c=add.FindIdenticalValueTo
-eH2
-l8
-b));if(add.Found(c)nQ
-tmp
-eH2
-y8
-CloneTag());tmp.i91
-b);tmp
-iW1;add.AddCollectionTo(tmp,c);c61
-goto
-done_a;}
-}
-lU2[a]=true;tD+=1;done_a:;}
-}
-if(tD>0){if(tD>1){eO3
-std::pair<yZ2,size_t> >nY;std::multimap<fphash_t,size_t>eV1;bool
-lB3
-eW3
-x51
-if(lU2[a]){e11
-xW
-a).eZ3{iT1&p=xW
-a)l8
-b);const
-fphash_t
-p_hash=p.GetHash();for(std::multimap<fphash_t,size_t>::const_iterator
-i=eV1.xU2
-p_hash);i!=eV1.cX1
-p_hash;++i){if(nY[i
-eC2
-eH3
-xI
-p)){nY[i
-eC2
-eI3+=1;lB3=true;goto
-found_mulgroup_item_dup;}
-}
-nY
-c52
-std::make_pair(p,size_t(1)));eV1.insert(std::make_pair(p_hash,nY
-eJ3-1));found_mulgroup_item_dup:;}
-}
-if(lB3
-nQ
-eE2;{size_t
-max=0
-eK3
-p=0;p<nY
-eJ3;++p)if(nY[p
-eI3<=1)nY[p
-eI3=0;else{nY[p
-eI3*=nY[p
-eH3
-nP2;if(nY[p
-eI3>max){eE2=nY[p
-eH3;max=nY[p
-eI3;}
-}
-}
-yZ2
-group_add;group_add
-iH
-cAdd);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Duplicate across some trees: "
-iL2
-eE2
-lE2" in "
-cR
-#endif
-x51
-if(lU2[a])e11
-xW
-a).eZ3
-if(eE2
-xI
-xW
-a)l8
-b))nQ
-tmp(xW
-a)y8
-CloneTag());tmp.i91
-b);tmp
-iW1;group_add
-c91
-tmp);lU2[a]eW3
-xY3
-group_add
-iW1
-tX
-group;group
-iH
-cMul);group
-c91
-eE2);group
-c91
-group_add);group
-iW1;add.x22(group);c61}
-}
-x51
-if(lU2[a]){if(add.x22(xW
-a))==CollectionSetBase::n91)c61}
-}
-if(should_regenerate){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before ConstantFolding_AddGrouping: "
-cR
-#endif
-tree.DelParams();for(x93
-eS1::xS1
-j=add.iN.y73
-j!=add.iN.end();++j
-nQ&value=j
-eC2.value
-tX&coeff=j
-eC2.xT2;if(j
-eC2.e0)coeff
-iW1;if(coeff
-tD1){lG3
-coeff
-x41,xG1)yA1
-lG3
-coeff
-x41
-nH2
-tree
-c91
-value);yA1}
-}
-yZ2
-mul;mul
-iH
-cMul);mul
-c91
-value);mul
-c91
-coeff);mul.e33
-yB
-e8}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After ConstantFolding_AddGrouping: "
-cR
-#endif
-lD2
-eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-bool
-ConstantFolding_IfOperations(iM3(tree.GetOpcode()==cIf||tree.GetOpcode()==cAbsIf);for(;;){if(c93==cNot){tD2
-cIf);xW
-0).eF2
-0)c43
-xW
-1).swap(xW
-2));}
-iP1
-xW
-0)cQ1{tD2
-t03;xW
-0).eF2
-0)c43
-xW
-1).swap(xW
-2));}
-else
-yV3
-lY1
-0),t72==t03
-tN1
-tree.eF2
-1));nZ
-l03
-tree.eF2
-2));nZ
-lZ1
-if(c93==cIf||c93==cAbsIf
-nQ
-cond=xW
-0)tX
-lC3;lC3
-tE2==cIf?cNotNot:cAbsNotNot);lC3
-xX2
-1));ConstantFolding(lC3)tX
-lD3;lD3
-tE2==cIf?cNotNot:cAbsNotNot);lD3
-xX2
-2));ConstantFolding(lD3);if(lC3
-tD1||lD3
-tD1
-nQ
-eT;eT
-tE2);eT
-xX2
-1));eT
-tX3
-eT.nJ
-2));eT
-iW1
-tX
-else_tree
-tS1
-tE2)tS1
-xX2
-2))tS1.nJ
-1))tS1.nJ
-2))tS1
-cY
-cond
-nC
-xT1
-0,cond
-l8
-0)yB
-nB1
-1,eT
-yB
-nB1
-2,else_tree
-yQ2}
-if(xW
-1)nC==xW
-2)nC&&(xW
-1)nC==cIf||xW
-1)nC==t03
-nQ&x53=xW
-1)tX&leaf2=xW
-2);if(x53
-l8
-0)nN2
-0))&&x61
-1))||x53
-l8
-2)nN2
-2)))nQ
-eT;eT
-nO2;eT
-tY3
-eT
-xY2
-1));eT
-xZ2
-1));eT
-iW1
-tX
-else_tree
-tS1
-nO2
-tS1.nJ
-0))tS1
-xY2
-2))tS1
-xZ2
-2))tS1
-cY
-x53
-nC
-xT1
-0
-cB3
-0)yB
-nB1
-1,eT
-yB
-nB1
-2,else_tree
-yQ2
-if
-x61
-1))&&x53
-l8
-2)nN2
-2))nQ
-eU;eU
-nO2;eU
-c91
-xW
-0));eU
-xY2
-0));eU
-xZ2
-0));eU
-cY
-x53
-nC
-yB
-nB1
-0,eU
-xT1
-2
-cB3
-2)xT1
-1
-cB3
-1)yQ2
-if
-x61
-2))&&x53
-l8
-2)nN2
-1))nQ
-eI2;eI2
-iH
-leaf2
-nC==cIf?cNot:cC3);eI2
-xZ2
-0));eI2
-iW1
-tX
-eU;eU
-nO2;eU
-c91
-xW
-0));eU
-xY2
-0));eU
-c91
-eI2);eU
-cY
-x53
-nC
-yB
-nB1
-0,eU
-xT1
-2
-cB3
-2)xT1
-1
-cB3
-1)yQ2}
-yZ2&xV=xW
-1)tX&y4=xW
-2);if(xV
-xI
-y4)){tree.eF2
-1)yQ2
-const
-OPCODE
-op1=xV
-nC;const
-OPCODE
-op2=y4
-nC;y93
-op2){if(xV.e91
-1
-nQ
-lO
-0));y02
-0))c71()n4
-if(xV.e91
-2&&y4.e91
-2){if(xV
-l8
-0)xI
-y4
-l8
-0))nQ
-param0=xV
-l8
-0)tX
-lO
-1));y02
-1))c71
-t8
-param0)n4
-if(xV
-l8
-1)xI
-y4
-l8
-1))nQ
-param1=xV
-l8
-1)tX
-lO
-0));y02
-0))c71
-t8
-n81
-c81
-param1
-yQ2}
-y93
-yA3
-cMul
-lV2
-cAnd
-lV2
-cOr
-lV2
-cAbsAnd
-lV2
-cAbsOr
-lV2
-cMin
-lV2
-cMax){eK
-lE3;c2{for
-iZ1
-b=y4.l91
-b-->0;){if(xV
-lF3
-y4
-l8
-b))){if(lE3
-eU3){xV.t13
-lD1}
-lE3
-c52
-xV
-n93
-y4.i91
-b);xV.i91
-a
-e02}
-}
-if(!lE3
-eU3){xV
-iW1;y4
-iW1
-l7
-op1
-yB
-SetParamsMove(lE3)n4}
-}
-y93
-yA3
-cMul||(op1==cAnd&&IsLogicalValue(y4))||(op1==cOr&&IsLogicalValue(y4))){c2
-if(xV
-lF3
-y4)){xV.lD1
-xV.i91
-a);xV
-iW1
-tX
-cL1=y4;y4=tE
-op1==yA3
-cOr
-t52
-op1
-c81
-cL1)n4}
-if((op1==cAnd
-lV2
-cOr)&&op2==cNotNot
-nQ&lH3=y4
-l8
-0);c2
-if(xV
-lF3
-lH3)){xV.lD1
-xV.i91
-a);xV
-iW1
-tX
-cL1=lH3;y4=tE
-op1==cOr
-t52
-op1
-c81
-cL1)n4}
-if(op2==cAdd||op2==cMul||(op2==cAnd&&IsLogicalValue(xV))||(op2==cOr&&IsLogicalValue(xV))){for
-iZ1
-a=y4
-iY
-y4
-lF3
-xV)){y4.t13
-i91
-a);y4
-iW1
-tX
-cM1=xV;xV=tE
-op2==cAdd||op2==cOr
-t52
-op2
-c81
-cM1)n4}
-if((op2==cAnd||op2==cOr)&&op1==cNotNot
-nQ&lI3=xV
-l8
-0
-iY1
-y4
-iY
-y4
-lF3
-lI3)){y4.t13
-i91
-a);y4
-iW1
-tX
-cM1=lI3;xV=tE
-op2==cOr
-t52
-op2
-c81
-cM1)n4
-eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-int
-maxFPExponent()yP
-std::numeric_limits
-xF::max_exponent;}
-yP1
-x91
-Value_t
-base,Value_t
-exponent){if(base<xG1
-lD2
-lG3
-base,xG1||lJ3
-base,e62
-1))cQ
-return
-exponent>=e62
-maxFPExponent
-xF())/fp_log2(base);}
-yP1
-ConstantFolding_PowOperations(iM3(tree.GetOpcode()==cPow);nP&&xW
-1).lV1
-const_value=t33
-lR,xW
-i8);nU
-const_value)i1
-t23
-if(eI1
-lJ3
-xW
-i8
-nH2
-tree.eF2
-0)yQ2
-nP&&lJ3
-lR
-nH2
-nU
-1)i1
-t23
-nP&&xW
-1)nC==cMul){bool
-y12=false
-iK2
-lW2=lR
-tX
-mulgroup=xW
-1
-iY1
-mulgroup
-iY
-mulgroup
-l8
-a).lV1
-imm=mulgroup
-l8
-a)x41;{if(x91
-lW2,imm))break
-iK2
-lX2=t33
-lW2,imm);lG3
-lX2,xG1)break;if(!y12){y12=true;cA1
-lD1}
-lW2=lX2;cA1
-i91
-a
-e02}
-if(y12){cA1
-e33);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before pow-mul change: "
-cR
-#endif
-xW
-0).Become(eA1
-lW2));xW
-1).Become
-eH2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After pow-mul change: "
-cR
-#endif
-}
-}
-if(eI1
-c93==cMul)l14
-lY2=xW
-i8
-iK2
-y22=1.0;bool
-y12=false
-tX&mulgroup=xW
-0
-iY1
-mulgroup
-iY
-mulgroup
-l8
-a).lV1
-imm=mulgroup
-l8
-a)x41;{if(x91
-imm,lY2))break
-iK2
-eW1=t33
-imm,lY2);lG3
-eW1,xG1)break;if(!y12){y12=true;cA1
-lD1}
-y22*=eW1;cA1
-i91
-a
-e02}
-if(y12){cA1
-e33)tX
-cZ3;cZ3
-iH
-cPow);cZ3
-iF1
-tree.lJ2));cZ3.yC2
-yB
-eL3
-cMul
-c81
-cZ3
-yB
-AddParam(eA1
-y22)yQ2}
-if(xW
-0)i12
-eI1
-xW
-0)l8
-1).lV1
-a=xW
-0)l8
-i8
-iK2
-b=xW
-i8
-iK2
-c=a*b;if(isEvenInteger(a)&&!isEvenInteger(c)nQ
-lK3;lK3
-iH
-cAbs);lK3.nJ
-0)c43
-lK3.e33
-yB
-nB1
-0,lK3);}
-else
-tree.SetParam(0,xW
-0)l8
-0)xT1
-1,eA1
-c));eE3
-t23}
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5;e72
-l5{enum
-eJ2{MakeFalse=0,MakeTrue=1,t62=2,lN3=3,MakeNotNotP0=4,MakeNotNotP1=5,MakeNotP0=6,MakeNotP1=7,xJ=8}
-;enum
-lZ2{Never=0,Eq0=1,Eq1=2,yB3=3,yC3=4}
-;eJ2
-if_identical;eJ2
-n02
-4];e72{eJ2
-what:4;lZ2
-when:4;}
-l02,l12,l22,l32
-yO1
-eJ2
-Analyze
-iR1
-xC3
-eX1)const{if(a
-xI
-b
-y03
-if_identical;yD3
-tY
-a);yD3
-p1=CalculateResultBoundaries(b);if(p0
-e61&&p1
-yI){if(p0
-nL3<p1
-yM&&n02
-0]iC
-0];if(p0
-nL3<=p1
-yM&&n02
-1]iC
-1];}
-if
-cN3
-p1
-e61){if(p0
-yM>p1
-nL3&&n02
-2]iC
-2];if(p0
-yM>=p1
-nL3&&n02
-3]iC
-3];}
-if(IsLogicalValue(a)){if(l02
-nN3
-l02.when,p1
-y03
-l02.what;if(l22
-nN3
-l22.when,p1
-y03
-l22.what;}
-if(IsLogicalValue(b)){if(l12
-nN3
-l12.when,p0
-y03
-l12.what;if(l32
-nN3
-l32.when,p0
-y03
-l32.what;eE3
-xJ;}
-cB1
-bool
-TestCase(lZ2
-when,const
-yD3&p){if(!p
-yI||!p
-e61
-cQ
-e23
-when){case
-Eq0:nO3==e62
-0.0)t43==p
-yM
-t83
-Eq1:nO3==e62
-1.0)t43==p
-nL3
-t83
-yB3:nO3>xH1
-t43<=e62
-1)t83
-yC3:nO3>=xH1
-l61
-1);yF3;eE3
-t23}
-;l33
-RangeComparisonsData{static
-const
-l5
-Data[6]={{l5
-lL3
-i3
-xJ,l5::i3
-xJ
-lF1
-Eq1
-nT1
-Eq1
-nU1
-Eq0
-nV1
-Eq0}
-}
-,{l5::x42
-lM3
-xJ,l5
-lM3
-xJ
-lF1
-Eq0
-nT1
-Eq0
-nU1
-Eq1
-nV1
-Eq1}
-}
-,{l5::x42
-lM3
-t62,l5::i3
-MakeFalse
-nU1
-yB3
-nT1
-yC3
-yY,{l5
-lL3
-xJ,l5
-lM3
-i3
-lN3
-nU1
-yC3
-nT1
-yB3
-yY,{l5::x42::i3
-i3
-MakeTrue,l5::t62
-lF1
-yC3
-nV1
-yB3
-yY,{l5
-lL3
-i3
-lN3,l5::xJ,l5
-nC1
-lF1
-yB3
-nV1
-yC3
-yY}
-;}
-yP1
-ConstantFolding_Comparison(eR{using
-l33
-RangeComparisonsData;assert(tree.GetOpcode()>=cEqual&&tree.GetOpcode()<=cGreaterOrEq);e23
-Data[t72-cEqual].Analyze(xW
-0),xW
-1))){case
-l5::MakeFalse:nU
-0);nZ
-l5
-nC1:nU
-1
-nY3
-lN3:tD2
-cEqual
-nY3
-t62:tD2
-i51
-nY3
-MakeNotNotP0:tD2
-cNotNot
-yB
-i91
-1
-nY3
-MakeNotNotP1:tD2
-cNotNot
-yB
-i91
-0
-nY3
-MakeNotP0:tD2
-cNot
-yB
-i91
-1
-nY3
-MakeNotP1:tD2
-cNot
-yB
-i91
-0
-nY3
-xJ:;}
-if(xW
-1)tD1)e23
-c93){case
-cAsin:lM
-fp_sin(xW
-iP2
-cAcos:lM
-fp_cos(xW
-i8))yB
-eL3
-t72==cLess?cGreater:t72==cLessOrEq?cGreaterOrEq:t72==cGreater?cLess:t72==cGreaterOrEq?cLessOrEq:t72);nZ
-cAtan:lM
-fp_tan(xW
-iP2
-cLog:lM
-fp_exp(xW
-iP2
-cSinh:lM
-fp_asinh(xW
-iP2
-cTanh:if(fp_less(fp_abs(xW
-i8)nH2
-lM
-fp_atanh(xW
-i8))yQ2
-break;yF3
-xY3
-return
-t23}
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{
-#ifdef DEBUG_SUBSTITUTIONS
-yE
-double
-d){union{double
-d;uint_least64_t
-h
-c42
-d=d;lR1
-h
-nX1
-#ifdef FP_SUPPORT_FLOAT_TYPE
-yE
-float
-f){union{float
-f;uint_least32_t
-h
-c42
-f=f;lR1
-h
-nX1
-#endif
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-yE
-long
-double
-ld){union{long
-double
-ld;e72{uint_least64_t
-a;x83
-short
-b;}
-s
-c42
-ld=ld;lR1
-s.b<<data.s.a
-nX1
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-yE
-long
-ld){o<<"("
-<<std::hex<<ld
-nX1
-#endif
-#endif
-}
-t5{lN
-nE)){}
-lN
-const
-Value_t&i
-y8
-xD3
-nE
-i
-x52
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-lN
-Value_t&&i
-y8
-xD3
-nE
-tF2
-i)x52
-#endif
-lN
-x83
-v
-y8
-VarTag
-nE
-iU2,v
-x52
-lN
-iU1
-o
-y8
-OpcodeTag
-nE
-o
-x52
-lN
-iU1
-o,x83
-f
-y8
-FuncOpcodeTag
-nE
-o,f
-x52
-lN
-const
-eX1
-y8
-CloneTag
-nE*b.data)){}
-tK1
-yZ2::~c02(){}
-lB
-ReplaceWithImmed(tX1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Replacing "
-iL2*this);if(IsImmed())OutFloatHex(cV2,GetImmed()lE2" with const value "
-<<i;OutFloatHex(cV2,i
-lE2"\n"
-;
-#endif
-data=new
-xK2
-xF(i);}
-tK1
-e72
-ParamComparer{iD2()iR1
-xC3
-eX1)const{if(a
-nP2!=b
-nP2)return
-a
-nP2<b
-nP2
-i1
-a.GetHash()<b.GetHash();}
-}
-;xL1
-xK2
-xF::Sort(yY3
-Opcode){case
-cAdd:case
-cMul:case
-cMin:case
-cMax:case
-cAnd:case
-cAbsAnd:case
-cOr:case
-cAbsOr:case
-cHypot:case
-cEqual:case
-i51:std::sort(iR2
-iJ2
-iR2
-end(),ParamComparer
-xF());lC
-cLess
-lY
-cGreater;}
-lC
-cLessOrEq
-lY
-cGreaterOrEq;}
-lC
-cGreater
-lY
-cLess;}
-lC
-cGreaterOrEq
-lY
-cLessOrEq;}
-break;yF3
-xY3}
-lB
-AddParam
-iR1
-param){y1
-c52
-param);}
-lB
-AddParamMove(yZ2¶m){y1
-c52
-yZ2());y1.back().swap(param);}
-lB
-SetParam
-iZ1
-which,const
-eX1)nW1
-which
-iQ2
-y1[which]=b;}
-lB
-nB1
-size_t
-which,eX1)nW1
-which
-iQ2
-y1[which
-tQ3
-b);}
-lB
-AddParams
-iS1
-nK){y1.insert(y1.end(),n12.iJ2
-n12.end());}
-lB
-AddParamsMove(nK){size_t
-endpos=y1
-eJ3,added=n12
-eJ3;y1
-xF3
-endpos+added,yZ2())eK3
-p=0;p<added;++p)y1[endpos+p
-tQ3
-n12[p]);}
-lB
-AddParamsMove(nK,size_t
-n22)nW1
-n22
-iQ2
-i91
-n22);AddParamsMove(tO1}
-lB
-SetParams
-iS1
-nK){eK
-tmp(tO1
-y1.swap(tmp);}
-lB
-SetParamsMove(nK){y1.swap(tO1
-n12.clear();}
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-lB
-SetParams(eK&&n12){SetParamsMove(tO1}
-#endif
-lB
-i91
-size_t
-index){eK&Params=y1;
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-iR2
-erase(iR2
-begin()+index);
-#else
-t63
-index].data=0
-eK3
-p=index;p+1<iS2;++p)t63
-p].data.UnsafeSetP(&*t63
-p+1
-iQ2
-t63
-iS2-1].data.UnsafeSetP(0);iR2
-resize(iS2-1);
-#endif
-}
-lB
-DelParams(){y1.clear();}
-yP1
-yZ2::IsIdenticalTo
-iS1
-eX1)const{if(&*data==&*b.data)return
-true
-i1
-data->IsIdenticalTo(*b.data);}
-yP1
-xK2
-xF::IsIdenticalTo
-iS1
-xK2
-xF&b)const{if(Hash!=b.Hash
-cQ
-if(Opcode!=b.Opcode
-cQ
-e23
-Opcode){case
-cImmed:return
-lJ3
-Value,b.Value)t83
-iU2:return
-lL2==b.lK2
-case
-cFCall:case
-cPCall:if(lL2!=b.lL2
-cQ
-break;yF3
-xY3
-if(iS2!=b.iS2
-cQ
-for
-iZ1
-a=0;a<iS2;++a){if(!iT2
-xI
-b.iT2)cQ}
-lD2}
-lB
-Become
-iS1
-eX1){if(&b!=this&&&*data!=&*b.data){DataP
-tmp=b.data;lD1
-data.swap(tmp);}
-}
-lB
-CopyOnWrite(){if(GetRefCount()>1)data=new
-xK2
-xF(*data);}
-tK1
-yZ2
-yZ2::GetUniqueRef(){if(GetRefCount()>1)return
-yZ2(*this,CloneTag())i1*this;}
-i4):yS
-cNop
-iR3),n8
-i4
-const
-xK2&b):yS
-b.Opcode
-iR3
-b.Value),lL2(b.cO1,t53
-b.Params),Hash(b.Hash),Depth(b.Depth
-eB1
-b.lM2){}
-i4
-tX1:yS
-cImmed
-iR3
-i),n8
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
-i4
-xK2
-xF&&b):yS
-b.Opcode
-iR3
-tF2
-b.Value)),lL2(b.cO1,t53
-tF2
-b.Params)),Hash(b.Hash),Depth(b.Depth
-eB1
-b.lM2){}
-i4
-Value_t&&i):yS
-cImmed
-iR3
-tF2
-i)),n8
-#endif
-i4
-iU1
-o):yS
-o
-iR3),n8
-i4
-iU1
-o,x83
-f):yS
-o
-iR3),lL2(f),t53),Hash(),Depth(1
-eB1
-0){}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-l33{xL1
-tZ1
-nO,std
-c9&done,std::ostream&o){x51
-tZ1
-xW
-a),done,o);std::ostringstream
-buf
-iL2
-tree,buf);done[nJ2].insert(buf.str());}
-}
-#endif
-t5{
-#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
-xL1
-DumpHashes(cE){std
-c9
-done;tZ1
-tree,done,o);for(std
-c9::const_iterator
-i=done.y73
-i!=done.end();++i){const
-std::set<eM3>&flist=i
-eC2;if(flist
-eJ3!=1)o<<"ERROR - HASH COLLISION?\n"
-;for(std::set<eM3>::const_iterator
-j=flist.y73
-j!=flist.end();++j){o<<'['<<std::hex<<i->first.hash1<<','<<i->first.hash2<<']'<<std::dec;o<<": "
-<<*j<<"\n"
-;}
-}
-}
-xL1
-DumpTree(cE){e32
-iF3;e23
-t72){case
-cImmed:o<<tree
-x41
-t73
-iU2:o<<"Var"
-<<(tree.GetVar()-iU2)t73
-cAdd:iF3"+"
-;lC
-cMul:iF3"*"
-;lC
-cAnd:iF3"&"
-;lC
-cOr:iF3"|"
-;lC
-cPow:iF3"^"
-;break;yF3
-iF3;o<<FP_GetOpcodeName(t72);cZ2
-cFCall||t72==cPCall)o<<':'<<tree.GetFuncNo();}
-o<<'(';if
-l51<=1&&sep2[1])o<<(sep2+1)<<' ';x51{if(a>0)o<<' '
-iL2
-xW
-a),o);if(a+1<tree.GetParamCount())o<<sep2;}
-o<<')';}
-xL1
-DumpTreeWithIndent(cE,const
-eM3&indent){o<<'['<<std::hex<<(void*)(&tree.lJ2))<<std::dec<<','<<tree.GetRefCount()<<']';o<<indent<<'_';e23
-t72){case
-cImmed:o<<"cImmed "
-<<tree
-x41;o<<'\n'
-t73
-iU2:o<<"VarBegin "
-<<(tree.GetVar()-iU2);o<<'\n'
-i1;yF3
-o<<FP_GetOpcodeName(t72);cZ2
-cFCall||t72==cPCall)o<<':'<<tree.GetFuncNo();o<<'\n';}
-x51{eM3
-ind=indent
-eK3
-p=0;p<ind
-eJ3;p+=2)if(ind[p]=='\\')ind[p]=' ';ind+=(a+1<tree.GetParamCount())?" |"
-:" \\"
-;DumpTreeWithIndent(xW
-a),o,ind);}
-o<<std::flush;}
-#endif
-}
-#endif
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;
-l33
-lA1{x83
-ParamSpec_GetDepCode
-iS1
-eA2&b
-yY3
-b.first){case
-ParamHolder:{cM*s=(cM*)b.second
-i1
-s->depcode;}
-case
-SubFunction:{cN*s=(cN*)b.second
-i1
-s->depcode;}
-yF3
-xY3
-return
-0;}
-xL1
-DumpParam
-iS1
-eA2&yA2
-std::ostream&o){static
-const
-char
-ParamHolderNames[][2]={"%"
-,"&"
-,"x"
-,"y"
-,"z"
-,"a"
-,"b"
-,"c"
-}
-;x83
-y32
-0;e23
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1;using
-l33
-FUNCTIONPARSERTYPES;o.precision(12);o<<param.constvalue;xY3
-case
-ParamHolder:{cM&yU3
-cM*tF1;o<<ParamHolderNames[param.index];y32
-param.constraints;xY3
-case
-SubFunction:{cN&yU3
-cN*tF1;y32
-param.constraints;yF
-GroupFunction){if
-yZ3
-lG1==cNeg){o<<"-"
-;n2}
-iP1
-param.lG1==cInv){o<<"/"
-;n2}
-else{eM3
-opcode=FP_GetOpcodeName((iU1)param.lG1).substr(1
-iY1
-0;a<opcode
-eJ3;++a)opcode[a]=(char)std::toupper(opcode[a]);o<<opcode<<"( "
-;n2
-o<<" )"
-;}
-}
-else{o<<'('<<FP_GetOpcodeName((iU1)param.lG1)<<' ';yF
-PositionalParams)o<<'[';yF
-SelectedParams)o<<'{';n2
-if
-yZ3
-data.n1!=0)o<<" <"
-<<iH3.n1<<'>';yF
-PositionalParams)o<<"]"
-;yF
-SelectedParams)o<<"}"
-;o<<')';}
-xY3
-c73(ImmedConstraint_Value(constraints&ValueMask)){case
-ValueMask:lC
-Value_AnyNum:lC
-x62:o<<"@E"
-;lC
-Value_OddInt:o<<"@O"
-;lC
-i11:o<<"@I"
-;lC
-Value_NonInteger:o<<"@F"
-;lC
-eY1:o<<"@L"
-;yV3
-ImmedConstraint_Sign(constraints&SignMask)){case
-SignMask:lC
-Sign_AnySign:lC
-nD1:o<<"@P"
-;lC
-eZ1:o<<"@N"
-;yV3
-ImmedConstraint_Oneness(constraints&OnenessMask)){case
-OnenessMask:lC
-Oneness_Any:lC
-Oneness_One:o<<"@1"
-;lC
-Oneness_NotOne:o<<"@M"
-;yV3
-ImmedConstraint_Constness(constraints&ConstnessMask)){case
-ConstnessMask:lC
-i01:if(lX3.first==ParamHolder){cM&yU3
-cM*tF1;if
-yZ3
-index<2)xY3
-o<<"@C"
-;lC
-Constness_NotConst:o<<"@V"
-;lC
-Oneness_Any:xY3}
-xL1
-DumpParams
-lT1
-paramlist,x83
-count,std::ostream&o){for
-lT1
-a=0;a<count;++a){if(a>0)o<<' ';const
-eA2¶m=ParamSpec_Extract
-xF(paramlist,a);DumpParam
-xF(param,o);x83
-depcode=ParamSpec_GetDepCode(param);if(depcode!=0)o<<"@D"
-<<depcode;}
-}
-}
-using
-l33
-lA1;using
-l33
-FUNCTIONPARSERTYPES;l33{cM
-plist_p[37]={{2,0,0x0}
-nT
-0,0x4}
-nT
-nD1,0x0}
-nT
-eZ1|Constness_NotConst,0x0}
-nT
-Sign_NoIdea,0x0}
-nT
-eY1,0x0}
-,{3,Sign_NoIdea,0x0}
-,{3,0,0x0}
-,{3,eY1,0x0}
-,{3,0,0x8}
-,{3,Value_OddInt,0x0}
-,{3,Value_NonInteger,0x0}
-,{3,x62,0x0}
-,{3,nD1,0x0}
-,{0,eZ1|lV{0,lV{0,nD1|lV{0,x62|lV{0,i01,0x1}
-,{0,i11|nD1|lV{0,i21
-i01,0x1}
-,{0,i21
-lV{0,Oneness_One|lV{0,eY1|lV{1,lV{1,x62|lV{1,i21
-lV{1,i11|lV{1,nD1|lV{1,eZ1|lV{6,0,0x0}
-,{4,0,0x0}
-,{4,i11,0x0}
-,{4,lV{4,0,0x16}
-,{5,0,0x0}
-,{5,lV}
-yO1
-e72
-plist_n_container{static
-const
-ParamSpec_NumConstant
-xF
-plist_n[20];}
-yO1
-const
-ParamSpec_NumConstant
-xF
-plist_n_container
-xF::plist_n[20]={{e62-2
-i5-1
-i5-0.5
-i5-0.25
-i5
-0
-tG2
-fp_const_deg_to_rad
-xF(tG2
-fp_const_einv
-xF(tG2
-fp_const_log10inv
-xF(i5
-0.5
-tG2
-fp_const_log2
-xF(i5
-1
-tG2
-fp_const_log2inv
-xF(i5
-2
-tG2
-fp_const_log10
-xF(tG2
-fp_const_e
-xF(tG2
-fp_const_rad_to_deg
-xF(tG2-fp_const_pihalf
-xF(),xU1{xH1,xU1{fp_const_pihalf
-xF(),xU1{fp_const_pi
-xF(),xU1}
-;cN
-plist_s[517]={{{1,15,tH2
-398,tH2
-477,tH2
-15,cNeg,GroupFunction,0}
-,i01,0x1
-lR3
-15,y42
-24,y42
-465,y42
-466,y42
-498,cInv,lT
-2,327995
-x9
-l0
-2,48276
-x9
-l6
-260151
-x9
-l6
-470171
-x9
-l6
-169126
-x9
-l6
-48418
-x9
-l6
-1328
-x9
-l6
-283962
-x9
-l6
-169275
-x9
-l6
-39202
-x9
-l6
-283964
-x9
-l6
-283973
-x9
-l6
-476619
-x9
-l6
-296998
-x9
-l6
-47
-x9
-SelectedParams,0}
-,0,0x4
-nH
-161839
-x9
-l6
-25036
-x9
-l6
-35847
-x9
-l6
-60440
-x9
-l6
-30751
-x9
-l6
-270599
-x9
-l6
-60431
-x9
-l6
-259119
-x9
-l6
-183474
-x9
-l6
-332066
-x9
-l6
-7168
-x9
-l6
-197632
-x9
-l6
-291840
-x9
-l6
-283648
-x9
-l6
-238866
-x9
-l6
-239902
-x9
-l6
-31751
-x9
-l6
-244743
-x9
-l6
-384022
-x9
-SelectedParams,0}
-,0,0x4
-nH
-385262
-x9
-l6
-386086
-x9
-l6
-393254
-x9
-SelectedParams,0}
-,0,0x5
-nH
-393254
-x9
-l6
-386095
-x9
-l6
-387312
-x9
-l6
-18662
-x9
-l6
-61670
-x9
-l6
-387397
-x9
-l6
-247855
-x9
-SelectedParams,0}
-,0,0x1
-nH
-342063
-x9
-l6
-297007
-x9
-l6
-15820
-x9
-l6
-393263
-x9
-l6
-393263
-x9
-SelectedParams,0}
-,0,0x5
-nH
-161847
-x9
-l6
-258103
-x9
-l6
-249073
-x9
-l6
-249076
-x9
-iO
-0,0
-x9
-nF
-0,0
-i31
-1,45
-x9
-nF
-1,53
-x9
-nF
-1,54
-x9
-nF
-1,55
-x9
-nF
-1,56
-x9
-nF
-1,26
-x9
-nF
-1,259
-eK2
-0x16
-lR3
-253
-x9
-nF
-1,272
-i31
-1,323
-eK2
-0x16
-lR3
-0
-x9
-nF
-1,21
-x9
-nF
-1,447
-eK2
-0x4
-lR3
-449
-eK2
-0x4
-lR3
-0
-eK2
-0x4
-lR3
-0
-tJ
-2}
-,0,0x4
-lR3
-15
-x9
-nF
-1,24
-tJ
-2}
-,0,0x0
-nH
-58392
-i31
-0,0
-tJ
-1}
-,nD1,0x0
-nH
-24591
-lS3
-33807
-lS3
-48143
-lS3
-285720
-lS3
-290840
-lS3
-305152,l9
-312400,l9
-39202,l9
-121894,l9
-421926,l9
-429094,l9
-443430,l9
-317834,l9
-329098,l9
-7633,l9
-7706,l9
-7730,l9
-38,l9
-50587,l9
-406528,l9
-24583,l9
-31751,l9
-405511,l9
-321551
-iV2
-327713,l9
-322596,l9
-88361,l9
-335174,l9
-327050,l9
-493606,l9
-496678,l9
-503846,l9
-516134,l9
-7217,l9
-333875,l9
-336896,l9
-524326,l9
-509952,l9
-286727,l9
-90127,l9
-131087,l9
-296976,tQ1
-324623,l1
-0x14
-nH
-332815,l1
-0x10}
-,{{3,7340056,tQ1
-289092,l9
-92176
-iV2
-337935
-e31
-7340060
-lO3
-7340176,l9
-338959
-e31
-7340061
-iV2
-7206,l9
-x63
-l9
-357414,l9
-368678,l9
-370745,l1
-0x7}
-,{{3,7340177,l9
-39277,tQ1
-426398
-lO3
-40272286
-iV2
-490910
-lO3
-40336798
-iV2
-50600,l9
-426462
-iV2
-490974
-iV2
-370726,l1
-0x6
-nH
-371750,l1
-0x6
-nH
-428070
-e31
-40336862
-iV2
-38378,l9
-50671
-e31
-47662080,l9
-477184,l9
-568320,l9
-371727,l1
-0x7}
-,{{3,15779306,l9
-370703,l1
-0x7
-nH
-39277,l9
-39279,l1
-0x4}
-,{{3,15779238,l9
-39338,tQ1
-436262,l9
-508966,l9
-39409,tQ1
-296998,tQ1
-35847,l9
-15,tQ1
-377894,l9
-386063,l1
-0x1
-nH
-15,l9
-7192,l9
-122904,l9
-121880,l9
-30751,l9
-57,l9
-7456,l9
-15674
-e31
-67579935,l9
-39237,l9
-58768,l9
-62924,l9
-121856,l9
-15760
-e31
-64009216,l1
-0x0}
-,{{0,0,xL
-0,0,iW
-2,eC1
-2,eD1
-3,eC1
-3,eD1
-38,xL
-1,38,iW
-14,xL
-1,57,xL
-1,16,eL2
-0x0
-nH
-471103,eL2
-0x1
-lR3
-303,xL
-1,323,yH3
-0x0
-nH
-471363,eL2
-0x16
-lR3
-293,eC1
-294,eD1
-295,xL
-1,296,iW
-400,xL
-1,0,xL
-1,460,xL
-1,465,xL
-1,16,eL2
-0x1
-lR3
-57,yH3
-0x1
-lR3
-0,iW
-21,xL
-1,15,eL2
-0x0
-nH
-24591,xL
-1,24,iW
-517,yH3
-0x0
-nH
-46095,lK
-46104,lK
-15397,lK
-287789,lK
-66584,lK
-404763,lK
-62504,lK
-15409,lK
-39951,lK
-24591,lK
-33807,lK
-50200,lK
-62509,lK
-50176,lF,178176,t21
-tF3
-283648,lF,19456,lF,27648,lF,89088,lF,86016,lF,488448,lF,14342,lF,58375,lF,46147
-xX
-46151,lF,284679,lF,7183,lF,46159
-xX
-38993
-xX
-50265,lF,50249,lF,283808,lF,284835,lF,24822,lF,10240,lF,11264,lF,7170,lF,x63
-lF,17408,lF,164864,lF,237568,lF,242688,t21
-0x14
-nH
-476160,lF,25607,lF,121871,lF,50252,lF,39374,lF,50183,lF,7192,lF,121887,lF,252979,lF,46155,lF,38919,lF,50267,lF,50268,lF,50253,lF,46190,lF,50295,lF,7563,t21
-0x10
-nH
-416811,lF,416819,lF,40046,lF,46191
-xX
-415795,lF,40047
-xX
-415787,lF,39015,t21
-0x5
-nH
-39326
-xX
-39326,lF,39332,t21
-0x5
-nH
-39333
-cC2
-50590
-xX
-50590,lF,39338
-xX
-39338,lF,39335,t21
-0x5
-nH
-15786
-xX
-146858,lF,39372,lF,39379,lF,39380,lF,39390
-xX
-50654
-xX
-50654,lF,24,t21
-0x6
-nH
-62,lF,24,lF,62,t21
-0x6
-nH
-43,lF,43
-xX
-51,lF,51
-xX
-50269,lF,50176
-xX
-50270,lF,39159,lF,39183
-xX
-7168
-xX
-31744,lF,99328,lF,31746,lF,100376,lF,39409
-xX
-39411
-xX
-39411,lF,39420,lF,39420
-xX
-15,lF,39025,t21
-0x5
-nH
-39422,lF,16384,lF,62853,lF,15360,lF,15
-cC2
-16,lF,7183
-cC2
-7172
-tW2
-y71,nD1,0x0
-nH
-24591
-tW2
-lT
-2,50200
-tW2
-lT
-2,63521
-tW2
-lT
-2,62500
-tW2
-lT
-2,50453
-tW2
-lT
-2,62488
-tW2
-lT
-1,0,t93
-7,t93
-194,t93
-0,cAcos
-tA3
-cAcosh
-tA3
-cAsin
-tA3
-cAsinh
-nS
-119,cAsinh
-tA3
-cAtan
-t11
-306176,cAtan2
-t11
-x63
-cAtan2
-tA3
-cAtanh
-nS
-246,cCeil
-tA3
-cCeil
-tB3
-0,cD2
-0,cCos
-tB3
-7,cD2
-91,cD2
-92,cD2
-119,cD2
-236,cD2
-255,cD2
-214,iW2
-236,iW2
-464,iW2
-0,cCosh
-tB3
-0,iW2
-0,cExp
-nS
-7,cExp
-nS
-91,cExp
-tA3
-yI3
-7,yI3
-91,yI3
-246,cFloor
-tA3
-cFloor,lA
-0x4
-nH
-309540,cHypot
-t11
-316708,cHypot
-t11
-316724,cHypot,l0
-3,32513024,eM2
-34627584
-iL
-31493120,eM2
-89213952
-iL
-149042176
-iL
-246647808
-iL
-301234176
-iL
-494360576
-iL
-498558976
-iL
-62933520
-iL
-62933520,eM2
-62933526
-iL
-62933526,eM2
-24670208
-iL
-579378176
-iL
-573578240
-iL
-32513024
-iL
-566254592
-iL
-7900160
-iL
-588822528,cIf
-nS
-119,cInt
-nS
-246,tI2
-0,tI2
-7,tI2
-31,tI2
-194,tI2
-363,tI2
-15,cLog,lT
-1,24,cLog,lT
-1,0,cLog10
-tA3
-cLog2
-t11
-x63
-cMax
-t11
-35847,cMax
-t11
-30751,cMax
-tA3
-cMax,AnyParams,1}
-,0,0x4
-nH
-x63
-cMin
-t11
-35847,cMin
-t11
-30751,cMin
-tA3
-cMin,AnyParams,1}
-,0,0x4
-nH
-24591,cMin,lT
-1,0,x72
-7,x72
-91,x72
-92,x72
-119,x72
-149,x72
-231,cSin,lA
-0x5
-lR3
-246,x72
-255,x72
-254,x72
-0,cSin
-tB3
-273,cSin,lA
-0x1
-lR3
-214,y52
-231,tD3
-lA
-0x5
-lR3
-246,y52
-254,y52
-255,y52
-464,y52
-0,cSinh
-tB3
-0,y52
-15,cSqrt,lT
-1,0,cTan
-tA3
-cTan
-tB3
-115,cTan
-tB3
-116
-tC3
-231
-tC3
-246
-tC3
-273
-tC3
-254
-tC3
-255,cTan
-tA3
-y62
-0,cTanh
-tB3
-213,y62
-231,y62
-246,y62
-254,y62
-255,y62
-0,cTrunc
-t11
-15384,cSub,lT
-2,15384,cDiv,lT
-2,476626,cDiv,lT
-2,121913,tJ2
-x63
-lP3
-tF3
-x63
-tJ2
-31744,lP3
-0x20
-nH
-31751,lP3
-0x24
-nH
-31751,tJ2
-121913,i51
-t11
-x63
-cLess,lA
-tF3
-41984,cLess,lA
-0x4
-nH
-41984,cLess
-t11
-7,cLess
-t11
-x63
-cLessOrEq
-t11
-296182,cLessOrEq
-t11
-7168
-tV2,lA
-tF3
-41984
-tV2,lA
-0x4
-nH
-41984
-tV2
-t11
-7
-tV2
-t11
-x63
-y9
-l0
-2,296182,cGreaterOrEq
-tA3
-n32
-245,n32
-7,n32
-550,n32
-553,n32
-554,n32
-556,n32
-31,n32
-559,n32
-15,n32
-560,cNot
-t11
-7706,lT3
-x63
-lT3
-35847,lT3
-30751,lT3
-463903,lT3
-466975,cAnd,iO
-0,0,cAnd,nF
-2,x63
-e03
-7706,e03
-35847,e03
-463903,e03
-466975,e03
-30751,cOr,iO
-1,0,n42
-91,n42
-131,n42
-245,n42
-215,n42
-246,cDeg
-nS
-246,cRad
-t11
-x63
-cAbsAnd,l6
-x63
-cAbsOr,iO
-1,0,cC3
-tA3
-cAbsNotNot,l0
-3,32513024,yT3
-lA
-0x0}
-,}
-;}
-l33
-lA1{const
-Rule
-grammar_rules[262]={{ProduceNewTree,17,1,0,{1,0,cAbs,eN2
-409,{1,146,cAtan,eN2
-403
-nT
-1324,cAtan2,eN2
-405
-nT
-307201,cAtan2
-eL
-253174
-nT
-255224,cAtan2
-eL
-259324
-nT
-257274,cAtan2,eN2
-152,{1,252,cCeil
-i7
-486,{1,68
-yH2
-482,{1,122
-yH2
-483,{1,124
-yH2
-151,{1,125
-yH2
-419,{1,123
-yH2
-0,{1,403,cCos,l2
-2,1,246,{1,252,cCos,l2
-18,1,0,{1,400
-yH2
-301,{1,406,cCosh,l2
-2,1,246,{1,252,cCosh,l2
-18,1,0,{1,400,cCosh
-i7
-458,{1,121,cFloor,eN2
-150,{1,252,cFloor,tG3
-156,{3,7382016,eF
-549,{3,8430592,eF
-556,{3,8436736,eF
-157,{3,42998784,eF
-550,{3,42999808,eF
-562,{3,43039744,eF
-557,{3,49291264,eF
-538,{3,49325056,eF
-469,{3,1058318,eF
-473,{3,1058324,eF
-473,{3,9438734,eF
-469,{3,9438740,cIf,l2
-0,3,32542225,{3,36732434,cIf,l2
-0,3,32542231,{3,36732440,cIf,yR3
-573,{3,32513026,cIf,yR3
-515,{3,455505423,cIf,yR3
-515,{3,433506837,cIf
-i7
-78,{1,256,cLog
-i7
-69,{1,258,cLog
-i7
-404,{1,72,cLog
-i7
-159,{1,147,cLog,l2
-0,1,0
-nT
-487425,cMax
-l3
-16,1,445
-nT
-yJ3
-cMax
-l3
-0,1,0
-nT
-483329,cMin
-l3
-16,1,446
-nT
-yJ3
-cMin,c3
-0,1,153
-nT
-24832
-tW2
-tG3
-153
-nT
-25854
-tW2
-tG3
-154
-nT
-129039
-tW2
-xV1
-32055
-tW2
-xV1
-32056
-tW2
-xV1
-32057
-tW2
-l2
-0,2,166288
-nT
-32137
-tW2
-xV1
-33082
-tW2
-l2
-0,2,7168
-nT
-12688
-tW2
-l2
-0,2,7434
-nT
-12553,tX2
-435
-nT
-46146,tX2
-436
-nT
-46154,tX2
-437
-nT
-46150,tX2
-169
-nT
-83983,tX2
-168
-nT
-130082,tX2
-175
-nT
-133154
-tW2
-tI3
-476160
-nT
-471055
-tW2
-tI3
-274432
-nT
-273423
-tW2
-tI3
-251904
-nT
-266274
-tW2
-tI3
-251904
-nT
-263186,tX2
-171,{1,252,cE2
-421,{1,68,cE2
-151,{1,122,cE2
-419,{1,124,cE2
-170,{1,125,cE2
-482,{1,123,cE2
-0,{1,405,cE2
-172,{1,252,cSinh
-i7
-328,{1,404,cSinh
-i7
-173,{1,252,tJ3
-0,{1,408,tJ3
-176,{1,410,tJ3
-177,{1,252,cTanh,l2
-0,1,442
-nT
-449551,i6
-1,441
-nT
-yJ3
-i6
-1,167
-nT
-268549,i6
-1,181
-nT
-276749,i6
-1,180
-nT
-276500,i6
-2,190770
-nT
-189622,i6
-2,194748
-nT
-193723,i6
-2,202943
-nT
-196795,i6
-2,59699
-nT
-298148,i6
-2,59714
-nT
-325815,i6
-2,59724
-nT
-343224
-x9
-c3
-2,1,337,{1,333
-tJ
-1
-tF
-336,{1,338
-tJ
-1}
-}
-,{ReplaceParams,2,1,340
-nT
-1363
-nR
-342
-nT
-1365
-nR
-463
-nT
-472524
-nR
-47
-nT
-356711
-nR
-349
-nT
-200751
-nR
-360
-nT
-199727
-nR
-480
-nT
-207053
-nR
-481
-nT
-208077
-nR
-417
-nT
-211144
-nR
-209
-nT
-211145
-nR
-418
-nT
-215240
-nR
-212
-nT
-212329
-nR
-204
-nT
-373097
-nR
-211
-nT
-372944
-nR
-217
-nT
-201944
-nR
-221
-nT
-223448
-nR
-367
-nT
-508329
-nR
-219
-nT
-508126
-nR
-224
-nT
-225705
-nR
-223
-nT
-225776
-nR
-365
-nT
-230825
-nR
-426
-nT
-377057
-nR
-497
-nT
-377054
-nR
-497
-nT
-204201
-nR
-426
-nT
-375280
-nR
-224
-nT
-375006,cAdd
-l3
-2,2,407781
-nT
-233698,cAdd
-l3
-2,2,59763
-nT
-233842,i6
-1,372
-nT
-1397,lW1
-95
-nT
-24705,lW1
-96
-nT
-24708,lW1
-444
-nT
-449551,lW1
-443
-nT
-yJ3
-lW1
-100
-nT
-101750,lW1
-108
-nT
-106821,lW1
-105
-nT
-103749
-lU3
-0,2,110607
-nT
-108869
-lU3
-0,2,107535
-nT
-109893,lJ
-0
-tF
-112
-nT
-111634,cMul,SelectedParams,0
-tF
-567,{1,52,lJ
-1
-tF
-568,{1,42,lJ
-1}
-}
-,{ReplaceParams,2,1,467
-nT
-45516
-xA
-356
-nT
-51555
-xA
-468
-nT
-49612
-xA
-357
-nT
-47459
-xA
-429
-nT
-438699
-xA
-432
-nT
-441774
-xA
-486
-nT
-498726
-xA
-494
-nT
-504870
-xA
-382
-nT
-435579
-xA
-497
-nT
-435709
-xA
-426
-nT
-508287
-xA
-414
-nT
-500092
-xA
-499
-nT
-352744
-xA
-345
-nT
-367092
-xA
-381
-nT
-425318
-xA
-478
-nT
-425460
-xA
-47
-nT
-512501
-xA
-505
-nT
-355817
-xA
-47
-nT
-516598
-xA
-507
-nT
-518182
-xA
-508
-nT
-358896
-xA
-351
-nT
-388605
-xA
-511
-nT
-360939
-xA
-503
-nT
-354788
-xA
-514
-nT
-525350
-xA
-510
-nT
-394342
-xA
-386
-nT
-351346
-lU3
-2,2,363004
-nT
-361968
-lU3
-16,1,117
-nT
-1157
-lU3
-16,1,118
-nT
-1158
-lU3
-16,1,402
-nT
-411024
-lU3
-16,2,58768
-nT
-1472
-lU3
-16,2,15760
-nT
-1474
-lU3
-17,1,0,{1,400
-lU3
-17,1,57,{1,14,lJ
-0}
-}
-,{ProduceNewTree,4,1,538
-nT
-41,lQ3
-yK3
-0
-nT
-5167,lQ3
-cH
-41984
-e22
-lQ3
-cH
-tU
-lQ3
-cH
-eV
-lQ3
-cH
-eW
-cEqual
-cN1
-24849,cEqual
-eL
-tV
-cEqual
-eL
-n52
-281873,cEqual
-eL
-iP
-cEqual
-eL
-lH1
-lQ3
-yK3
-562
-nT
-41,i51,yK3
-538
-nT
-5167,i51,cH
-41984
-e22
-i51,cH
-tU
-i51,cH
-eV
-i51,cH
-eW
-i51
-cN1
-24849,i51
-eL
-tV
-i51
-eL
-n52
-281873,i51
-eL
-iP
-i51
-eL
-lH1
-i51,cH
-tU
-yN3
-eV
-yN3
-eW
-cLess,eN2
-571
-nT
-46080,cLess
-cN1
-24832,cLess
-eL
-xW1
-cLess
-eL
-tV
-cLess
-eL
-n52
-tK3
-cLess
-eL
-nY1
-cLess
-eL
-iP
-cLess
-eL
-lH1
-cLess,yL3
-562
-e22
-yN3
-tU
-n62
-cH
-eV
-n62
-cH
-eW
-n62
-eN2
-565
-nT
-409615,cLessOrEq
-cN1
-24832,cLessOrEq
-eL
-xW1
-cLessOrEq
-eL
-tV
-cLessOrEq
-eL
-n52
-tK3
-cLessOrEq
-eL
-nY1
-cLessOrEq
-eL
-iP
-cLessOrEq
-eL
-lH1
-n62
-yL3
-562
-nT
-409647,n62
-cH
-tU
-cF2
-eV
-cF2
-eW
-cGreater,eN2
-539
-nT
-409615
-tV2
-cN1
-24832
-tV2
-eL
-xW1
-cGreater
-eL
-tV
-cGreater
-eL
-n52
-281856
-tV2
-eL
-nY1
-cGreater
-eL
-iP
-cGreater
-eL
-lH1
-cGreater,yL3
-538
-nT
-409647,cF2
-tU
-y9
-cH
-eV
-y9
-cH
-eW
-y9
-eN2
-572
-nT
-46080,y9
-nQ2
-529654
-nT
-24832,y9
-nQ2
-xW1
-y9
-nQ2
-tV
-y9
-nQ2
-n52
-tK3
-y9
-nQ2
-nY1
-y9
-nQ2
-iP
-y9
-nQ2
-lH1
-y9
-yL3
-538
-e22
-y9
-yK3
-519,{1,137,cNot,yR3
-571,{1,2,cNot,l2
-0,1,452
-nT
-yJ3
-lV3
-0,2,537097,{3,547892744,cAnd,c3
-16,1,566,{1,5,cAnd,AnyParams,1}
-}
-,{ReplaceParams,16,1,569
-nT
-13314,lV3
-16,1,544
-nT
-553498,lV3
-16,1,546
-nT
-462369,lV3
-16,1,548
-nT
-466465,lV3
-0,1,457
-nT
-yJ3
-xX1
-570
-nT
-13314,xX1
-563
-nT
-8197,xX1
-541
-nT
-553498,xX1
-542
-nT
-462369,xX1
-543
-nT
-466465,xX1
-564
-nT
-143365,cOr,c3
-4,1,525,{1,137,yS3
-yR3
-572,{1,2,yS3
-l4
-17,1,0,{1,0,yS3
-eN2
-537,{1,256,cAbsNotNot,c3
-18,1,531,{1,254,cAbsNotNot,c3
-0,1,572,{3,43039744,yT3
-tG3
-571,{3,49325056,yT3
-yR3
-454,{3,32513586,yT3
-l2
-16,3,32542225,{3,36732434,yT3
-y71}
-,}
-;e72
-grammar_optimize_abslogical_type{y3
-9
-cT
-grammar_optimize_abslogical_type
-grammar_optimize_abslogical={9,{34,192,228,238,242,247,254,260,261}
-}
-;}
-e72
-grammar_optimize_ignore_if_sideeffects_type{y3
-59
-cT
-grammar_optimize_ignore_if_sideeffects_type
-grammar_optimize_ignore_if_sideeffects={59,{0,20,21,22,23,24,25,26,cO
-l42
-78,cP
-cU
-e72
-grammar_optimize_nonshortcut_logical_evaluation_type{y3
-56
-cT
-grammar_optimize_nonshortcut_logical_evaluation_type
-grammar_optimize_nonshortcut_logical_evaluation={56,{0,25,cO
-l42
-78,cP
-241,243,244,245,246,248,249,250,251,252,253,255,256,257,258,259}
-}
-;}
-e72
-grammar_optimize_recreate_type{y3
-22
-cT
-grammar_optimize_recreate_type
-grammar_optimize_recreate={22,{18,55,56,57,80,81,82,83,84,85,117,118,120,121,130,131,132,133,134,135,136,137}
-}
-;}
-e72
-grammar_optimize_round1_type{y3
-125
-cT
-grammar_optimize_round1_type
-grammar_optimize_round1={125,{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,19,25,cO
-37,38,l42
-45,46,47,48,49,50,51,52,53,54,58,59,60,61,62,63,64,65,66,67,68,69,70,71,78,79,80,81,82,83,84,85,86,87,88,93,94,95,96,97,98,99,100,101,117,118,119,120,121,122,123,124,125,126,127,128,129,138,160,161,162,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,cU
-e72
-grammar_optimize_round2_type{y3
-103
-cT
-grammar_optimize_round2_type
-grammar_optimize_round2={103,{0,15,16,17,25,cO
-39,40,l42
-45,46,47,48,49,50,51,52,53,54,59,60,72,73,78,79,86,87,88,89,90,91,92,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,119,122,123,124,125,126,127,128,139,159,160,161,162,163,164,165,166,167,168,169,178,179,180,200,204,212,216,224,236,237,239,240,cU
-e72
-grammar_optimize_round3_type{y3
-79
-cT
-grammar_optimize_round3_type
-grammar_optimize_round3={79,{74,75,76,77,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,170,171,172,173,174,175,176,177,181,182,183,184,185,186,187,188,189,190,191,193,194,195,196,197,198,199,201,202,203,205,206,207,208,209,210,211,213,214,215,217,218,219,220,221,222,223,225,226,227,229,230,231,232,233,234,235}
-}
-;}
-e72
-grammar_optimize_round4_type{y3
-12
-cT
-grammar_optimize_round4_type
-grammar_optimize_round4={12,{18,55,56,57,130,131,132,133,134,135,136,137}
-}
-;}
-e72
-grammar_optimize_shortcut_logical_evaluation_type{y3
-53
-cT
-grammar_optimize_shortcut_logical_evaluation_type
-grammar_optimize_shortcut_logical_evaluation={53,{0,25,cO
-l42
-78,cP
-cU}
-l33
-lA1{tK1
-eA2
-ParamSpec_Extract
-lT1
-paramlist,lJ1){index=(paramlist>>(index*10))&1023;if(index>=57)return
-eA2(SubFunction,cG2
-plist_s[index-57]);if(index>=37)return
-eA2(NumConstant,cG2
-plist_n_container
-xF::plist_n[index-37])i1
-eA2(ParamHolder,cG2
-plist_p[index]);}
-}
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <stdio.h>
-#include <algorithm>
-#include <map>
-#include <sstream>
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33{nN1
-It,x93
-T,x93
-Comp>t31
-MyEqualRange(It
-first,It
-last,const
-T&val,Comp
-comp){size_t
-len=last-first;while(len>0){size_t
-xR3
-len/2;It
-x23(first);x23+=half;if(comp(*x23,val)){first=x23;++first;len=len-half-1;}
-iP1
-comp(val,*x23)){len=half;}
-else{It
-left(first);{It&eO2=left;It
-last2(x23);size_t
-len2=last2-eO2;while(len2>0){size_t
-half2=len2/2;It
-eN3(eO2);eN3+=half2;if(comp(*eN3,val)){eO2=eN3;++eO2;len2=len2-half2-1;}
-else
-len2=half2;}
-}
-first+=len;It
-right(++x23);{It&eO2=right;It&last2=first;size_t
-len2=last2-eO2;while(len2>0){size_t
-half2=len2/2;It
-eN3(eO2);eN3+=half2;if(comp(val,*eN3))len2=half2;else{eO2=eN3;++eO2;len2=len2-half2-1;}
-}
-eE3
-t31(left,right);}
-eE3
-t31(first,first);}
-tK1
-e72
-OpcodeRuleCompare{iD2()iS1
-nP1
-x83
-y72)const{const
-Rule&rule=grammar_rules[y72]i1
-t72<rule
-yR2.subfunc_opcode;}
-iD2()lT1
-y72,const
-eR
-const{const
-Rule&rule=grammar_rules[y72]i1
-rule
-yR2.subfunc_opcode<t72;}
-}
-yO1
-bool
-TestRuleAndApplyIfMatch(t41
-nP1
-bool
-c4{MatchInfo
-xF
-info;n31
-found(false,cZ());if((rule.lI1
-LogicalContextOnly)&&!c4{tR1
-if(nB
-IsIntType
-xF::nS3){if(rule.lI1
-NotForIntegers)tR1
-cJ3
-rule.lI1
-OnlyForIntegers)tR1
-if(nB
-IsComplexType
-xF::nS3){if(rule.lI1
-NotForComplex)tR1
-cJ3
-rule.lI1
-OnlyForComplex)tR1
-for(;;){
-#ifdef DEBUG_SUBSTITUTIONS
-#endif
-found=TestParams(rule
-yR2
-cU3,found.specs,info,true);if(found.found)break;if(!&*found.specs){fail:;
-#ifdef DEBUG_SUBSTITUTIONS
-DumpMatch
-yG2,false);
-#endif
-return
-t23}
-#ifdef DEBUG_SUBSTITUTIONS
-DumpMatch
-yG2,true);
-#endif
-SynthesizeRule
-yG2
-yQ2}
-nG1{yP1
-ApplyGrammar
-iS1
-Grammar&tK2,nP1
-bool
-c4{if(tree.GetOptimizedUsing()==&tK2){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Already optimized: "
-iL2
-tree
-lE2"\n"
-<<std::flush;
-#endif
-return
-t23
-if(true){bool
-changed
-eW3
-e23
-t72){case
-cNot:case
-cNotNot:case
-cAnd:case
-cOr:for
-iZ1
-a=0
-tV3
-true))yS1
-lC
-cIf:case
-cAbsIf:if(ApplyGrammar(tK2,xW
-0),t72==cIf))yS1
-for
-iZ1
-a=1
-tV3
-c4)yS1
-break;yF3
-for
-iZ1
-a=0
-tV3
-false))yS1}
-if(changed){tree.Mark_Incompletely_Hashed(yQ2}
-typedef
-const
-x83
-short*lW3;std::pair<lW3,lW3>range=MyEqualRange(tK2.rule_list,tK2.rule_list+tK2.rule_count
-cU3,OpcodeRuleCompare
-xF());eO3
-x83
-short>rules;rules.xH3
-range.second-range.first);for
-y0
-if(IsLogisticallyPlausibleParamsMatch(tM1
-yR2
-cU3))rules
-c52*r);}
-range.first=!rules
-eU3?&rules[0]:0;range.second=!rules
-eU3?&rules[rules
-eJ3-1]+1:0;if(range.first!=range.second){
-#ifdef DEBUG_SUBSTITUTIONS
-if(range.first!=range.second)cH2"Input ("
-<<FP_GetOpcodeName(t72)<<")["
-<<tree.GetParamCount()<<"]"
-;if(c4
-cV2<<"(Logical)"
-;x83
-first=l52,prev=l52;e32
-sep=", rules "
-;for
-y0
-if(first==l52)first=prev=*r;iP1*r==prev+1)prev=*r;else
-cH2
-sep<<first;sep=","
-;if(prev!=first)cV2<<'-'<<prev;first=prev=*r;}
-}
-if(first!=l52)cH2
-sep<<first;if(prev!=first)cV2<<'-'<<prev;}
-cV2<<": "
-iL2
-tree
-lE2"\n"
-<<std::flush;}
-#endif
-bool
-changed
-eW3
-for
-y0
-#ifndef DEBUG_SUBSTITUTIONS
-if(!IsLogisticallyPlausibleParamsMatch(tM1
-yR2
-cU3))yA1
-#endif
-if(TestRuleAndApplyIfMatch(tM1
-cU3,c4){yS1
-xY3}
-if(changed){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Changed."
-<<std::endl;cV2<<"Output: "
-iL2
-tree
-lE2"\n"
-<<std::flush;
-#endif
-tree.Mark_Incompletely_Hashed(yQ2}
-tree.SetOptimizedUsing(&tK2)i1
-t23
-yP1
-ApplyGrammar
-iS1
-void*p,FPoptimizer_CodeTree::eR
-yP
-ApplyGrammar(*iS1
-Grammar*)p
-cU3);}
-xL1
-ApplyGrammars(FPoptimizer_CodeTree::eR{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round1\n"
-;
-#endif
-n6
-grammar_optimize_round1
-cU3
-nW
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round2\n"
-;
-#endif
-n6
-grammar_optimize_round2
-cU3
-nW
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round3\n"
-;
-#endif
-n6
-grammar_optimize_round3
-cU3
-nW
-#ifndef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_nonshortcut_logical_evaluation\n"
-;
-#endif
-n6
-grammar_optimize_nonshortcut_logical_evaluation
-cU3
-nW
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_round4\n"
-;
-#endif
-n6
-grammar_optimize_round4
-cU3
-nW
-#ifdef FP_ENABLE_SHORTCUT_LOGICAL_EVALUATION
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_shortcut_logical_evaluation\n"
-;
-#endif
-n6
-grammar_optimize_shortcut_logical_evaluation
-cU3
-nW
-#endif
-#ifdef FP_ENABLE_IGNORE_IF_SIDEEFFECTS
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_ignore_if_sideeffects\n"
-;
-#endif
-n6
-grammar_optimize_ignore_if_sideeffects
-cU3
-nW
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iB3"grammar_optimize_abslogical\n"
-;
-#endif
-n6
-grammar_optimize_abslogical
-cU3
-nW
-#undef C
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <algorithm>
-#include <assert.h>
-#include <cstring>
-#include <cmath>
-#include <memory> /* for auto_ptr */
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33{yP1
-TestImmedConstraints
-lT1
-bitmask,const
-eR{e23
-bitmask&ValueMask){case
-Value_AnyNum:case
-ValueMask:lC
-x62:if(GetEvennessInfo
-iS3
-n72
-Value_OddInt:if(GetEvennessInfo
-iS3
-x82
-i11:if(GetIntegerInfo
-iS3
-n72
-Value_NonInteger:if(GetIntegerInfo
-iS3
-x82
-eY1:if(!IsLogicalValue(tree)cQ
-nE1
-SignMask){case
-Sign_AnySign:lC
-nD1:if(l81
-n72
-eZ1:if(l81
-x82
-Sign_NoIdea:if(l81
-Unknown
-cQ
-nE1
-OnenessMask){case
-Oneness_Any:case
-OnenessMask:lC
-Oneness_One:if(!xY1
-if(!lJ3
-fp_abs(tree
-x41),e62
-1))cQ
-lC
-Oneness_NotOne:if(!xY1
-lG3
-fp_abs(tree
-x41),e62
-1))cQ
-nE1
-ConstnessMask){case
-Constness_Any:lC
-i01:if(!xY1
-lC
-Constness_NotConst:if(xY1
-xY3
-lD2}
-tP1
-x83
-extent,x83
-nbits,x93
-eP2=x83
-int>e72
-nbitmap{private:static
-const
-x83
-bits_in_char=8;static
-const
-x83
-eQ2=(sizeof(eP2)*bits_in_char)/nbits;eP2
-data[(extent+eQ2-1)/eQ2];e43
-void
-inc(lJ1,int
-by=1){data[pos(index)]+=by*eP2(1<<y82);y81
-void
-dec(lJ1){inc(index,-1);}
-int
-get(lJ1
-c01(data[pos(index)]>>y82)&mask()iT3
-pos(lJ1)yP
-index/eQ2
-iT3
-shift(lJ1)yP
-nbits*(index%eQ2)iT3
-mask()yP(1<<nbits)-1
-iT3
-mask(lJ1)yP
-mask()<<y82;}
-}
-;e72
-Needs{int
-SubTrees:8;int
-Others:8;int
-l62:8;int
-Immeds:8;nbitmap<iU2,2>SubTreesDetail;Needs(){std::memset(this,0,sizeof(*this));}
-Needs
-iS1
-Needs&b){std::memcpy(this,&b,sizeof(b));}
-Needs&eM1=iS1
-Needs&b){std::memcpy(this,&b,sizeof(b))i1*this;}
-}
-yO1
-Needs
-CreateNeedList_uncached(eX&tL2{Needs
-yQ1;for
-lT1
-a=0;a<params
-y92;++a){const
-eA2&lX3=ParamSpec_Extract
-xF(params.param_list,a);e23
-lX3.first){case
-SubFunction:{cN&yU3
-cN*tF1;yF
-GroupFunction)++yQ1.Immeds;else{++iO2;assert(iH3.subfunc_opcode<VarBegin);yQ1.SubTreesDetail.inc
-yZ3
-lG1);}
-++yQ1.l62;xY3
-case
-NumConstant:case
-ParamHolder:++iN2;++yQ1.l62;xY3
-eE3
-yQ1;}
-tK1
-Needs&CreateNeedList(eX&tL2{typedef
-std::map<eX*,Needs>eE1;static
-eE1
-yV1;eE1::y83
-i=yV1.xU2&tL2;if(i!=yV1.cX1&tL2
-return
-i
-eC2
-i1
-yV1.y43,std::make_pair(¶ms,CreateNeedList_uncached
-xF(tL2))eC2;}
-tK1
-yZ2
-CalculateGroupFunction
-iS1
-eA2&yA2
-const
-tC
-info
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1
-i1
-CodeTreeImmed
-yZ3
-constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1
-i1
-info.GetParamHolderValueIfFound
-yZ3
-index);}
-case
-SubFunction:{cN&yU3
-cN*tF1
-tX
-nS3;nS3
-iH
-param.lG1);nS3.lJ2).xH3
-iH3
-y92);for
-lT1
-a=0;a<iH3
-y92;++a
-nQ
-tmp(CalculateGroupFunction
-nF1
-iH3.param_list,a),info));nS3
-c91
-tmp);}
-nS3
-iW1
-i1
-nS3;}
-eE3
-yZ2();}
-}
-nG1{yP1
-IsLogisticallyPlausibleParamsMatch(eX¶ms,const
-eR{Needs
-yQ1(CreateNeedList
-xF(tL2);size_t
-tL3=yC
-if(tL3<size_t(yQ1.l62))tM2
-for
-iZ1
-a=0;a<tL3;++a){x83
-opcode=xW
-a)nC;e23
-opcode){case
-cImmed:if(yQ1.Immeds>0)--yQ1.Immeds;else--iN2;lC
-iU2:case
-cFCall:case
-cPCall:--iN2;break;yF3
-assert(opcode<VarBegin);if(iO2>0&&yQ1.SubTreesDetail.get(opcode)>0){--iO2;yQ1.SubTreesDetail.dec(opcode);}
-else--iN2;}
-}
-if(yQ1.Immeds>0||iO2>0||iN2>0)tM2
-if(params.match_type!=AnyParams){if(0||iO2<0||iN2<0)tM2}
-lD2}
-tK1
-n31
-TestParam
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1;if(!xY1
-Value_t
-imm=tree
-x41;switch
-yZ3
-modulo){case
-Modulo_None:lC
-Modulo_Radians:imm=cK3
-imm,yK
-imm<xG1
-imm
-yN
-if(imm>fp_const_pi
-xF())imm-=fp_const_twopi
-xF(e02
-return
-lJ3
-imm,param.constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1;if(!x3
-return
-info.SaveOrTestParamHolder
-yZ3
-index
-cU3);}
-case
-SubFunction:{cN&yU3
-cN*tF1;yF
-GroupFunction){if(!x3
-yZ2
-xZ1=CalculateGroupFunction(yA2
-info);
-#ifdef DEBUG_SUBSTITUTIONS
-DumpHashes(xZ1
-lE2*iS1
-void**)&xZ1
-x41;cV2<<"\n"
-;cV2<<*iS1
-void**)&tree
-x41;cV2<<"\n"
-;DumpHashes(tree
-lE2"Comparing "
-iL2
-xZ1
-lE2" and "
-iL2
-tree
-lE2": "
-;cV2<<(xZ1
-xI
-tree)?"true"
-:"false"
-lE2"\n"
-;
-#endif
-return
-xZ1
-xI
-tree);}
-cJ3!eK1){if(!x3
-if(t72!=param.lG1
-cQ
-eE3
-TestParams
-yZ3
-data
-cU3,start_at,info,false);}
-}
-eE3
-t23
-tK1
-e72
-l31
-x92
-MatchInfo
-xF
-info;l31():start_at(),info(){}
-}
-yO1
-class
-MatchPositionSpec_PositionalParams:nQ1
-l31
-xF>{e43
-iX2
-MatchPositionSpec_PositionalParams
-iZ1
-n):eF1
-l31
-xF>(n){}
-}
-;e72
-l72
-x92
-l72():start_at(){}
-}
-;class
-yG:nQ1
-l72>{e43
-x83
-trypos;iX2
-yG
-iZ1
-n):eF1
-l72>(n),trypos(0){}
-}
-yO1
-n31
-TestParam_AnyWhere
-iS1
-eA2&yA2
-const
-nP1
-const
-cZ&start_at,tC
-info,cY2&used,bool
-iX1{xP<yG>x8;x83
-xA2(yG*)eK1;a=x8->trypos;goto
-retry_anywhere_2;cO2
-yG
-l51);a=0;}
-tM3
-yC++a){if(used[a])yA1
-retry_anywhere
-yW3
-TestParam(yA2
-xW
-a)xS3);yP3
-used[a]=true;if(iX1
-info.SaveMatchedParamIndex(a);x8->trypos=a
-i1
-n31(true,&*x8);}
-}
-retry_anywhere_2
-yX3
-goto
-retry_anywhere;}
-eE3
-t23
-tK1
-e72
-yD1
-x92
-MatchInfo
-xF
-info;cY2
-used;iX2
-yD1
-iZ1
-tL3):start_at(),info(),used(tL3){}
-}
-yO1
-class
-MatchPositionSpec_AnyParams:nQ1
-yD1
-xF>{e43
-iX2
-MatchPositionSpec_AnyParams
-iZ1
-n,size_t
-m):eF1
-yD1
-xF>(n,yD1
-xF(m)){}
-}
-yO1
-n31
-TestParams(eX&nN,const
-nP1
-const
-cZ&start_at,tC
-info,bool
-iX1{if(nN.match_type!=AnyParams){if(xT!=tree.GetParamCount()cQ}
-if(!IsLogisticallyPlausibleParamsMatch(nN
-cU3))tM2
-e23
-nN.match_type){case
-PositionalParams:{xP<cF>x8;x83
-xA2(cF*)eK1;a=xT-1;goto
-lK1;cO2
-cF(xT);a=0;}
-tM3
-xT;++a){(yQ3=info;retry_positionalparams
-yW3
-TestParam(cW
-a),xW
-a)xS3);yP3
-yA1}
-}
-lK1
-yX3
-info=(yQ3;goto
-retry_positionalparams;}
-if(a>0){--a;goto
-lK1;}
-info=c12
-i1
-t23
-if(iX1
-tN3
-info.SaveMatchedParamIndex(a)i1
-n31(true,&*x8);}
-case
-SelectedParams:case
-AnyParams:{xP<t6>x8;cY2
-used
-l51);eO3
-x83>iY2(xT);eO3
-x83>yB2(xT);tN3{const
-eA2
-lX3=cW
-a);iY2[a]=ParamSpec_GetDepCode(lX3);}
-{x83
-b=0;tN3
-if(iY2[a]!=0)yB2[b++]=a;tN3
-if(iY2[a]==0)yB2[b++]=a;}
-x83
-xA2(t6*)eK1;if(xT==0){a=0;goto
-retry_anyparams_4;}
-a=xT-1;goto
-eG1;cO2
-t6(xT
-cU3.GetParamCount());a=0;if(xT!=0){c12=info;(*x8)[0].used=used;}
-}
-tM3
-xT;++a){if(a>0){(yQ3=info;(yO3
-used=used;}
-retry_anyparams
-yW3
-TestParam_AnyWhere
-xF(cW
-yB2[a])cU3
-xS3,used,iX1;yP3
-yA1}
-}
-eG1
-yX3
-info=(yQ3;used=(yO3
-used;goto
-retry_anyparams;}
-eH1:if(a>0){--a;goto
-eG1;}
-info=c12
-i1
-t23
-retry_anyparams_4:if(nN.n1!=0){if(!TopLevel||!info.HasRestHolder(nN.n1)){eK
-cI2;cI2.reserve
-l51);for
-lT1
-b=0;b<yC++b){if(used[b])yA1
-cI2
-c52
-xW
-b));used[b]=true;if(iX1
-info.SaveMatchedParamIndex(b);}
-if(!info.SaveOrTestRestHolder(nN.n1,cI2)){goto
-eH1;}
-}
-else{eA3&cI2=info.GetRestHolderValues(nN.n1
-iY1
-0;a<cI2
-eJ3;++a){bool
-found
-eW3
-for
-lT1
-b=0;b<yC++b){if(used[b])yA1
-if(cI2[a]xI
-xW
-b))){used[b]=true;if(iX1
-info.SaveMatchedParamIndex(b);found=true;xY3}
-if(!found){goto
-eH1;}
-}
-}
-eE3
-n31(true,xT?&*x8:0);}
-case
-GroupFunction:xY3
-return
-t23}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <algorithm>
-#include <assert.h>
-using
-t5;using
-nG1;l33{tK1
-yZ2
-yW1
-iS1
-eA2&yA2
-tC
-info,bool
-inner=true
-yY3
-lX3.first){case
-NumConstant:{const
-ParamSpec_NumConstant
-xF¶m=*iS1
-ParamSpec_NumConstant
-xF*tF1
-i1
-CodeTreeImmed
-yZ3
-constvalue);}
-case
-ParamHolder:{cM&yU3
-cM*tF1
-i1
-info.GetParamHolderValue
-yZ3
-index);}
-case
-SubFunction:{cN&yU3
-cN*tF1
-tX
-tree;tD2
-param.lG1);for
-lT1
-a=0;a<iH3
-y92;++a
-nQ
-nparam=yW1
-nF1
-iH3.param_list,a
-l04
-true
-c81
-nparam);}
-if
-yZ3
-data.n1!=0){eK
-trees(info.GetRestHolderValues
-yZ3
-data.n1)yB
-AddParamsMove(trees);if
-l51==1){assert(tree.GetOpcode()==cAdd||tree.GetOpcode()==cMul||tree.GetOpcode()==cMin||tree.GetOpcode()==cMax||tree.GetOpcode()==cAnd||tree.GetOpcode()==cOr||tree.GetOpcode()==cAbsAnd||tree.GetOpcode()==cAbsOr);tree.eF2
-0));}
-else
-if
-l51==0
-yY3
-t72){case
-cAdd:case
-cOr:tree=nA1
-0));lC
-cMul:case
-cAnd:tree=nA1
-1));yF3
-xY3}
-}
-if(inner)tree
-iW1
-i1
-tree;}
-eE3
-yZ2();}
-}
-nG1{xL1
-SynthesizeRule(t41
-nP1
-tC
-info
-yY3
-rule.ruletype){case
-ProduceNewTree:{tree.Become(yW1
-nF1
-rule.t51
-0
-l04
-false)e02
-case
-ReplaceParams:yF3{eO3
-x83>list=info.GetMatchedParamIndexes();std::sort(list.iJ2
-list.end()iY1
-list
-eJ3;a-->0;)tree.i91
-list[a]);for
-lT1
-a=0;a<rule.repl_param_count;++a
-nQ
-nparam=yW1
-nF1
-rule.t51
-a
-l04
-true
-c81
-nparam);}
-xY3}
-}
-}
-#endif
-#ifdef DEBUG_SUBSTITUTIONS
-#include <sstream>
-#include <cstring>
-using
-l33
-FUNCTIONPARSERTYPES;using
-l33
-lA1;using
-t5;using
-nG1;l33
-lA1{xL1
-DumpMatch(t41
-const
-nP1
-const
-tC
-info,bool
-DidMatch,std::ostream&o){DumpMatch
-yG2,DidMatch?iX3"match"
-:iX3"mismatch"
-,o);}
-xL1
-DumpMatch(t41
-const
-nP1
-const
-tC
-info,e32
-tO3,std::ostream&o){static
-const
-char
-ParamHolderNames[][2]={"%"
-,"&"
-,"x"
-,"y"
-,"z"
-,"a"
-,"b"
-,"c"
-}
-;o<<tO3<<" (rule "
-<<(&rule-grammar_rules)<<")"
-<<":\n Pattern : "
-;{eA2
-tmp;tmp.first=SubFunction;ParamSpec_SubFunction
-tmp2;tmp2.data=rule
-yR2;tmp.second=cG2
-tmp2;DumpParam
-xF(tmp,o);}
-o<<"\n Replacement: "
-;DumpParams
-xF(rule.t51
-rule.repl_param_count,o)iV3
-o<<" Tree : "
-iL2
-tree,o)iV3
-if(!std::strcmp(tO3,iX3"match"
-))DumpHashes(tree,o
-iY1
-0;a<info.cA
-eJ3;++a){if(!info.cA[a].nX2)yA1
-o<<" "
-<<ParamHolderNames[a]<<" = "
-iL2
-info.cA[a],o)iV3}
-e11
-info.lQ
-eJ3;++b){if(!iW3
-eH3)yA1
-for
-iZ1
-a=0;a<iW3
-eI3
-eJ3;++a){o<<" <"
-<<b<<"> = "
-iL2
-iW3
-eI3[a],o);o<<std::endl;}
-}
-o<<std::flush;}
-}
-#endif
-#include <list>
-#include <algorithm>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{yP1
-MarkIncompletes(FPoptimizer_CodeTree::eR{if(tree.Is_Incompletely_Hashed())lD2
-bool
-l82
-eW3
-x51
-l82|=MarkIncompletes(xW
-a));if(l82)tree.Mark_Incompletely_Hashed()i1
-l82;}
-xL1
-FixIncompletes(FPoptimizer_CodeTree::eR{if(tree.Is_Incompletely_Hashed()){x51
-FixIncompletes(xW
-a)yB
-e33);}
-}
-}
-t5{lB
-Sort()iZ3
-Sort();}
-lB
-e33
-bool
-constantfolding){if(constantfolding)ConstantFolding(*this);else
-Sort();data
-xC
-tK1
-e72
-cB
-c03
-Value_t
-c13
-yE1=0;
-#if 0
-long
-double
-value=Value;e9=crc32::calc(iS1
-x83
-char*)&value,sizeof(value));key^=(key<<24);
-#elif 0
-union{e72{x83
-char
-filler1[16]iK2
-v;x83
-char
-filler2[16];}
-buf2;e72{x83
-char
-filler3[sizeof
-cX3)+16-sizeof(xE1)];e9;}
-buf1;}
-data;memset(&data,0,sizeof(data));data.buf2.v=Value;e9=data.buf1.key;
-#else
-int
-exponent
-iK2
-nR2=std::frexp(Value,&tU2
-e9=lT1(exponent+0x8000)&0xFFFF);if(nR2<0){nR2=-nR2;key=key^0xFFFF;}
-else
-key+=0x10000;nR2-=yF2;key<<=39;key|=n51(nR2+nR2)*e62
-1u<<31))<<8;
-#endif
-lP
-#ifdef FP_SUPPORT_COMPLEX_NUMBERS
-nN1
-T
-cJ2
-std::complex<T> >c03
-std::complex<T>c13
-cB<T>::lY3
-cK2,Value.real());nB
-fphash_t
-temp;cB<T>::lY3
-temp,Value.imag());yE1^=temp.hash2;cK2.hash2^=temp.hash1;}
-}
-;
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-tP1
-cJ2
-long>yD
-long
-Value){e9=Value;lP
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-tP1
-cJ2
-GmpInt>c03
-GmpInt
-c13
-e9=Value.toInt();lP
-#endif
-xL1
-xK2
-xF::Recalculate_Hash_NoRecursion(){fphash_t
-cK2(n51
-Opcode)<<56,Opcode*iE3(0x1131462E270012B));Depth=1;e23
-Opcode){case
-cImmed:{cB
-xF::lY3
-cK2,Value
-e02
-case
-iU2:{yE1|=n51
-cO1<<48
-lL1((n51
-cO1)*11)^iE3(0x3A83A83A83A83A0);xY3
-case
-cFCall:case
-cPCall:{yE1|=n51
-cO1<<48
-lL1((~n51
-cO1)*7)^3456789;}
-yF3{size_t
-t61=0
-e73
-0;a<iS2;++a){if(iT2
-nP2>t61)t61=iT2
-nP2;yE1+=((iT2.tN2
-hash1*(a+1))>>12)lL1
-iT2.tN2
-hash1
-lL1(3)*iE3(0x9ABCD801357);cK2.hash2*=iE3(0xECADB912345)lL1(~iT2.tN2
-hash2)^4567890;}
-Depth+=t61;}
-}
-if(Hash!=cK2){Hash=cK2;lM2=0;}
-}
-lB
-tE3{MarkIncompletes(*this);FixIncompletes(*this);}
-}
-#endif
-#include <cmath>
-#include <list>
-#include <cassert>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5
-yO1
-bool
-x01
-const
-nP1
-long
-count,const
-xK1::SequenceOpCode
-xF&eQ,xK1::eP3&synth,size_t
-max_bytecode_grow_length);static
-const
-e72
-SinCosTanDataType{OPCODE
-whichopcode;OPCODE
-inverse_opcode;enum{eR2,nS2,nZ1,lM1}
-;OPCODE
-codes[4];}
-SinCosTanData[12]={{cTan,cCot,{cSin,cCos,cCsc,cSec}
-}
-,{cCot,cCot,{cCos,cSin,cSec,cCsc}
-}
-,{cCos,cSec,{cSin,cTan,cCsc,cCot}
-}
-,{cSec,cCos,{cTan,cSin,cCot,cCsc}
-}
-,{cSin,cCsc,{cCos,cCot,cSec,cTan}
-}
-,{cCsc,cSin,{cCot,cCos,cTan,cSec}
-}
-,{cL2{tD3
-cCosh,cM2,{tD3
-cNop,{cL2
-cNop,cCosh}
-}
-,{cCosh,cNop,{tD3
-cL2
-cNop}
-}
-,{cNop,cTanh,{cCosh,tD3
-cM2,{cNop,tD3{cNop,cTanh,cCosh,cNop}
-}
-,{cNop,cCosh,{cTanh,tD3
-cM2}
-;}
-t5{lB
-SynthesizeByteCode(eO3
-x83>&eN1,std
-xM3
-xF&Immed,size_t&stacktop_max){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Making bytecode for:\n"
-;l21
-#endif
-while(RecreateInversionsAndNegations()){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"One change issued, produced:\n"
-;l21
-#endif
-tE3;using
-nG1;using
-l33
-lA1;const
-void*g=cG2
-grammar_optimize_recreate;while(ApplyGrammar(*iS1
-Grammar*)g,*this)){tE3;}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Actually synthesizing, after recreating inv/neg:\n"
-;l21
-#endif
-xK1::eP3
-synth;SynthesizeByteCode(synth,false
-iM2.Pull(eN1,Immed,stacktop_max);}
-lB
-SynthesizeByteCode(xK1::eP3&synth,bool
-MustPopTemps)const{y01*this))yP;}
-for
-iZ1
-a=0;a<12;++a){const
-SinCosTanDataType&data=SinCosTanData[a];if(data.whichopcode!=cNop)iC1!=data.whichopcode)yA1
-c02
-lZ3;lZ3.xA1);lZ3
-iH
-data.inverse_opcode);lZ3.yC2);y01
-lZ3)){synth.tQ
-else
-iC1!=cInv)yA1
-if(GetParam(0)nC!=data.inverse_opcode)yA1
-y01
-GetParam(0))){synth.tQ
-size_t
-found[4];e11
-4;++b){c02
-tree;if(data.tP3]==cNop){tD2
-cInv);c02
-n03;n03.xA1);n03
-iH
-data.tP3^2]);n03.yC2
-c81
-n03);}
-else{tree.xA1
-yB
-eL3
-data.tP3]);}
-tree.yC2);found[b]=synth.xK3
-tree);}
-if(found[data.eR2
-e3
-nS2
-tG
-eR2]iM2.yT
-nS2]);yB1
-cDiv
-tW
-eR2
-e3
-lM1
-tG
-eR2]iM2.yT
-lM1]);yB1
-cMul
-tW
-nZ1
-e3
-lM1
-tG
-nZ1]iM2.yT
-lM1]);yB1
-cRDiv
-tW
-nZ1
-e3
-nS2
-tG
-nZ1]iM2.yT
-nS2]);yB1
-cMul,2,1
-iM2.tQ
-size_t
-n_subexpressions_synthesized=SynthCommonSubExpressions(c92
-e23
-l92{case
-iU2:synth.PushVar(GetVar());lC
-cImmed:t71
-GetImmed());lC
-cAdd:case
-cMul:case
-cMin:case
-cMax:case
-cAnd:case
-cOr:case
-cAbsAnd:case
-cAbsOr:iC1==cMul){bool
-c23
-eW3
-yH
-lX1
-tD1&&isLongInteger(lX1
-x41)){c11=makeLongInteger(lX1
-x41);c02
-tmp(*this,x93
-c02::CloneTag());tmp.i91
-a);tmp
-iW1;if(x01
-tmp,value,xK1::tU1
-xF::AddSequence,synth,MAX_MULI_BYTECODE_LENGTH)){c23=true;xY3}
-}
-if(c23)xY3
-int
-yF1=0;cY2
-done(GetParamCount(),false);c02
-iQ;iQ
-iH
-l92;for(;;){bool
-found
-eW3
-yH
-done[a])yA1
-if(synth.IsStackTop(lX1)){found=true;done[a]=true;lX1.n7
-iQ
-cS
-lX1);if(++yF1>1){yU
-2);iQ.yC2)yC1
-iQ);yF1=yF1-2+1;}
-}
-}
-if(!found)xY3
-yH
-done[a])yA1
-lX1.n7
-iQ
-cS
-lX1);if(++yF1>1){yU
-2);iQ.yC2)yC1
-iQ);yF1=yF1-2+1;}
-}
-if(yF1==0
-yY3
-l92{case
-cAdd:case
-cOr:case
-cAbsOr:t71
-0);lC
-cMul:case
-cAnd:case
-cAbsAnd:t71
-1);lC
-cMin:case
-cMax:t71
-0);break;yF3
-xY3++yF1;}
-assert(n_stacked==1);xY3
-case
-cPow:{tW1
-p0
-i42
-0);tW1
-p1
-i42
-1);if(!p1
-tD1||!isLongInteger
-cR3||!x01
-p0,makeLongInteger
-cR3,xK1::tU1
-xF::MulSequence,synth,MAX_POWI_BYTECODE_LENGTH)){p0.n7
-p1.n7
-yU
-2);e21
-cIf:case
-cAbsIf:{x93
-xK1::eP3::IfData
-ifdata;GetParam(0)e93
-SynthIfStep1(ifdata,l92;GetParam(1)e93
-SynthIfStep2(ifdata);GetParam(2)e93
-SynthIfStep3(ifdata
-e02
-case
-cFCall:case
-cPCall:{for
-iZ1
-a=0;a<l91++a)lX1.n7
-yU
-lT1)GetParamCount());yB1
-0x80000000u|GetFuncNo(),0,0
-e02
-yF3{for
-iZ1
-a=0;a<l91++a)lX1.n7
-yU
-lT1)GetParamCount()e02}
-synth.StackTopIs(*this);if(MustPopTemps&&n_subexpressions_synthesized>0){size_t
-top=synth.GetStackTop(iM2.DoPopNMov(top-1-n_subexpressions_synthesized,top-1);}
-}
-}
-l33{yP1
-x01
-const
-nP1
-long
-count,const
-xK1::SequenceOpCode
-xF&eQ,xK1::eP3&synth,size_t
-max_bytecode_grow_length){if
-cW3!=0){xK1::eP3
-backup=synth;tree.n7
-size_t
-bytecodesize_backup=synth.GetByteCodeSize();xK1::x01
-count
-e63
-size_t
-bytecode_grow_amount=synth.GetByteCodeSize()-bytecodesize_backup;if(bytecode_grow_amount>max_bytecode_grow_length){synth=backup
-i1
-t23
-lD2}
-else{xK1::x01
-count,eQ,synth
-yQ2}
-}
-#endif
-#include <cmath>
-#include <cassert>
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5;
-#define FactorStack std xM3
-const
-e72
-PowiMuliType{x83
-opcode_square;x83
-opcode_cumulate;x83
-opcode_invert;x83
-opcode_half;x83
-opcode_invhalf;}
-iseq_powi={cSqr,cMul,cInv,cSqrt,cRSqrt}
-,iseq_muli={l52
-x9
-cNeg,l52,l52}
-yO1
-Value_t
-cP1
-const
-PowiMuliType&c33,const
-std
-nA3,n82&stack)eQ3
-1);while(IP<limit){if(n13
-c33.opcode_square){if(!t42
-eT3
-2;yZ
-opcode_invert){nS3=-nS3;yZ
-opcode_half){if(nS3>xH1&&isEvenInteger(eT3
-yF2;yZ
-opcode_invhalf){if(nS3>xH1&&isEvenInteger(eT3
-e62-0.5);++IP;yA1}
-size_t
-xB2=IP
-iK2
-lhs(1);if(n13
-cFetch){lJ1=n43;if(index<y2||size_t(index-y2)>=lB2){IP=xB2;xY3
-lhs=stack[index-y2];goto
-yD2;}
-if(n13
-cDup){lhs=nS3;goto
-yD2;yD2:t91
-nS3);++IP
-iK2
-subexponent=cP1
-c33
-iK
-if(IP>=limit||eN1[IP]!=c33.opcode_cumulate){IP=xB2;xY3++IP;stack.pop_back();nS3+=lhs*subexponent;yA1}
-xY3
-return
-nS3;}
-tK1
-Value_t
-ParsePowiSequence
-iS1
-std
-nA3){n82
-stack;t91
-e62
-1))i1
-cP1
-iseq_powi
-iK}
-tK1
-Value_t
-ParseMuliSequence
-iS1
-std
-nA3){n82
-stack;t91
-e62
-1))i1
-cP1
-iseq_muli
-iK}
-tK1
-class
-CodeTreeParserData{e43
-iX2
-CodeTreeParserData(bool
-k_powi):stack(),clones(),keep_powi(k_powi){}
-void
-Eat
-iZ1
-tL3,OPCODE
-opcode
-nQ
-xM;xM
-iH
-opcode);eK
-params=Pop(tL3
-yR1
-tL2;if(!keep_powi)e23
-opcode){case
-cTanh:{yZ2
-sinh,cosh;sinh
-iH
-cSinh);sinh
-cS
-xM
-c43
-sinh
-iW1;cosh
-iH
-cCosh);cosh
-c91
-xM
-c43
-cosh
-iW1
-tX
-pow;pow
-iH
-cPow);pow
-c91
-cosh);pow.yA
-nU2));pow
-iW1;xM
-iH
-cMul);xM.nB1
-0,sinh);xM
-c91
-pow
-e02
-case
-cTan:{yZ2
-sin,cos;sin
-iH
-cSin);sin
-cS
-xM
-c43
-sin
-iW1;cos
-iH
-cCos);cos
-c91
-xM
-c43
-cos
-iW1
-tX
-pow;pow
-iH
-cPow);pow
-c91
-cos);pow.yA
-nU2));pow
-iW1;xM
-iH
-cMul);xM.nB1
-0,sin);xM
-c91
-pow
-e02
-case
-cPow:{iT1&p0=xM
-l8
-0);iT1&p1=xM
-l8
-1);if(p1
-nC==cAdd){eK
-mulgroup(p1.GetParamCount()iY1
-0;a<p1.l91++a
-nQ
-pow;pow
-iH
-cPow);pow
-cS
-p0);pow
-cS
-p1
-n93
-pow
-iW1;mulgroup[a
-tQ3
-pow);}
-xM
-iH
-cMul
-yR1
-mulgroup);}
-xY3
-yF3
-xY3
-xM.e33!keep_powi);lA2,false);
-#ifdef DEBUG_SUBSTITUTIONS
-iA1<<tL3<<", "
-<<FP_GetOpcodeName(opcode)<<"->"
-<<FP_GetOpcodeName(xM
-nC)<<": "
-iK3
-xM);iB1
-xM);
-#endif
-t91
-xM
-cN2
-EatFunc
-iZ1
-tL3,OPCODE
-opcode,x83
-funcno
-nQ
-xM=CodeTreeFuncOp
-xF(opcode,funcno);eK
-params=Pop(tL3
-yR1
-tL2;xM.yC2);
-#ifdef DEBUG_SUBSTITUTIONS
-iA1<<tL3<<", "
-iK3
-xM);iB1
-xM);
-#endif
-lA2);t91
-xM
-cN2
-AddConst(yL1
-nQ
-xM=CodeTreeImmed(value);lA2);Push(xM
-cN2
-AddVar
-lT1
-varno
-nQ
-xM=CodeTreeVar
-xF(varno);lA2);Push(xM
-cN2
-SwapLastTwoInStack(){tA1
-1
-tQ3
-tA1
-2]cN2
-Dup(){Fetch(lB2-1
-cN2
-Fetch
-iZ1
-which){Push(stack[which]);}
-nN1
-T>void
-Push(T
-tree){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<iK3
-tree);iB1
-tree);
-#endif
-t91
-tree
-cN2
-PopNMov
-iZ1
-target,size_t
-source){stack[target]=stack[source];stack
-xF3
-target+1);}
-yZ2
-yE2{clones.clear()tX
-nS3(stack.back());stack
-xF3
-lB2-1)i1
-nS3;}
-eK
-Pop
-iZ1
-n_pop){eK
-nS3(n_pop);for
-lT1
-n=0;n<n_pop;++n)nS3[n
-tQ3
-tA1
-n_pop+n]);
-#ifdef DEBUG_SUBSTITUTIONS
-for
-iZ1
-n=n_pop;n-->0;){iA1
-iL2
-nS3[n]);iB1
-nS3[n]);}
-#endif
-stack
-xF3
-lB2-n_pop)i1
-nS3;}
-size_t
-GetStackTop(c01
-lB2;}
-private:void
-FindClone(yZ2&,bool=true)yP;}
-private:eK
-stack;std::multimap<fphash_t,yZ2>clones;bool
-keep_powi;private:CodeTreeParserData
-iS1
-CodeTreeParserData&);CodeTreeParserData&eM1=iS1
-CodeTreeParserData&);}
-yO1
-e72
-IfInfo{yZ2
-eS2
-tX
-thenbranch;size_t
-endif_location;IfInfo():eS2(),thenbranch(),endif_location(){}
-}
-;}
-t5{lB
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&x33,bool
-keep_powi){eK
-xH2;xH2.xH3
-x33.mVariablesAmount);for
-lT1
-n=0;n<x33.mVariablesAmount;++n){xH2
-c52
-CodeTreeVar
-xF(n+iU2));}
-GenerateFrom(x33,xH2,keep_powi);}
-lB
-GenerateFrom
-iS1
-x93
-FunctionParserBase
-xF::Data&x33,const
-x5&xH2,bool
-keep_powi){const
-eO3
-x83>&eN1=x33.mByteCode;const
-std
-xM3
-xF&Immed=x33.mImmed;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"ENTERS GenerateFrom()\n"
-;
-#endif
-CodeTreeParserData
-xF
-sim(keep_powi);eO3
-IfInfo
-xF>eJ
-eK3
-IP=0,DP=0;;++IP){tO2:while(!eJ
-eU3&&(eJ.eA==IP||(IP<n41&&n13
-cJump&&eJ
-e81.nX2))){c02
-elsebranch=sim.yE2
-nA2
-eJ.back().eS2)nA2
-eJ
-e81)nA2
-elsebranch)yR
-3,cIf);eJ.pop_back();}
-if(IP>=n41)break;x83
-opcode=eN1[IP];if(eS3
-cSqr||opcode==cDup||eS3
-cInv&&!IsIntType
-xF::nS3)||opcode==cNeg||opcode==cSqrt||opcode==cRSqrt||opcode==cFetch)){size_t
-was_ip=IP
-iK2
-eD2
-ParsePowiSequence
-xF(eN1,IP,eJ
-eU3?n41:eJ.eA,sim.xH
-1);if(exponent!=e62
-1.0)){xG
-exponent
-iU3);goto
-tO2;}
-if
-eS3
-cDup||opcode==cFetch||opcode==cNeg)l14
-xT2=ParseMuliSequence
-xF(eN1,IP,eJ
-eU3?n41:eJ.eA,sim.xH
-1);if(xT2!=e62
-1.0)){xG
-xT2)yR
-2,cMul);goto
-tO2;}
-}
-IP=was_ip;}
-if(nB2>=iU2){lJ1=opcode-iU2
-nA2
-xH2[index]);}
-else{e23
-nB2){case
-cIf:case
-cAbsIf:{eJ
-xF3
-eJ
-eJ3+1);c02
-res(sim.yE2);eJ.back().eS2.swap(res);eJ.eA=n41;IP+=2;yA1}
-case
-cJump:{c02
-res(sim.yE2);eJ
-e81.swap(res);eJ.eA=eN1[IP+1]+1;IP+=2;yA1}
-case
-cImmed:xG
-Immed[DP++]);lC
-cDup:sim.Dup();lC
-cNop:lC
-cFCall:{x83
-funcno=n43;assert(funcno<fpdata.mFuncPtrs.size());x83
-params=x33.mFuncPtrs
-n53
-mParams;sim.EatFunc(params,nB2,funcno
-e02
-case
-cPCall:{x83
-funcno=n43;assert(funcno<fpdata.iI3.size());const
-FunctionParserBase
-xF&p=*x33.iI3
-n53
-mParserPtr;x83
-params=x33.iI3
-n53
-mParams;x5
-paramlist=sim.Pop(tL2;c02
-tP2;tP2.GenerateFrom(*p.mData,paramlist)nA2
-tP2
-e02
-case
-cInv:xG
-1
-c32
-cDiv);lC
-cNeg
-nC2
-cNeg);break;xG
-0
-c32
-cSub);lC
-cSqr:xG
-2
-xN1
-cSqrt:xG
-yF2
-xN1
-cRSqrt:xG
-e62-0.5)xN1
-cCbrt:xG
-e62
-1)/e62
-3)xN1
-cDeg:xG
-fp_const_rad_to_deg
-xF())yG1
-cRad:xG
-fp_const_deg_to_rad
-xF())yG1
-cExp:iR)goto
-yM3;xG
-fp_const_e
-xF()c32
-cPow);lC
-cExp2:iR)goto
-yM3;xG
-2.0
-c32
-cPow);lC
-cCot
-nC2
-cTan);iR)x1
-cCsc
-nC2
-cSin);iR)x1
-cSec
-nC2
-cCos);iR)x1
-cInt:
-#ifndef __x86_64
-iR)n23
-1,cInt
-e02
-#endif
-xG
-yF2)tQ2
-yR
-1,cFloor);lC
-cLog10
-nC2
-c53
-fp_const_log10inv
-xF())yG1
-cLog2
-nC2
-c53
-fp_const_log2inv
-xF())yG1
-cQ3:n33
-c53
-fp_const_log2inv
-xF())yR
-3,cMul);lC
-cHypot:xG
-2
-iU3);tS3
-xG
-2
-iU3)tQ2;xG
-yF2
-xN1
-cSinCos:sim.Dup()yR
-1,cSin);n33
-cCos);lC
-cSinhCosh:sim.Dup()yR
-1,cSinh);n33
-cCosh);lC
-cRSub:tS3
-case
-cSub:iR)n23
-2,cSub
-e02
-xG-1)yR
-2,cMul)tQ2;lC
-cRDiv:tS3
-case
-cDiv:iR||IsIntType
-xF::nS3)n23
-2,cDiv
-e02
-xG-1
-iU3)yG1
-cAdd:case
-cMul:case
-cMod:case
-cPow:case
-cEqual:case
-cLess:case
-cGreater:case
-i51:case
-cLessOrEq:case
-cGreaterOrEq:case
-cAnd:case
-cOr:case
-cAbsAnd:case
-cAbsOr:sim.Eat(2,tB1
-lC
-cNot:case
-cNotNot:case
-cC3:case
-cAbsNotNot
-nC2
-tB1
-lC
-cFetch:sim.Fetch(n43);lC
-cPopNMov:{x83
-stackOffs_target=n43;x83
-stackOffs_source=n43;sim.PopNMov(stackOffs_target,stackOffs_source
-e02
-yF3
-yM3:;x83
-funcno=opcode-cAbs;assert(funcno<FUNC_AMOUNT);const
-FuncDefinition&func=Functions[funcno]yR
-func.params,tB1
-xY3}
-}
-Become(sim.yE2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Produced tree:\n"
-;l21
-#endif
-}
-}
-#endif
-#include <algorithm>
-#ifdef FP_SUPPORT_OPTIMIZER
-#include <assert.h>
-#define FP_MUL_COMBINE_EXPONENTS
-l33{using
-l33
-FUNCTIONPARSERTYPES;using
-t5
-yO1
-static
-void
-AdoptChildrenWithSameOpcode(eR{
-#ifdef DEBUG_SUBSTITUTIONS
-bool
-nT2
-eW3
-#endif
-for
-l41
-if(xW
-a)nC==t72){
-#ifdef DEBUG_SUBSTITUTIONS
-if(!nT2)cH2"Before assimilation: "
-cR
-nT2=true;}
-#endif
-tree.AddParamsMove(xW
-a).GetUniqueRef().lJ2),a);}
-#ifdef DEBUG_SUBSTITUTIONS
-if(nT2)cH2"After assimilation: "
-cR}
-#endif
-}
-}
-t5{xL1
-ConstantFolding(eR{tree.Sort();
-#ifdef DEBUG_SUBSTITUTIONS
-void*c63=0;cV2<<"["
-<<(&c63)<<"]Runs ConstantFolding for: "
-cR
-DumpHashes(tree
-lE2
-std::flush;
-#endif
-if(false){redo:;tree.Sort();
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"["
-<<(&c63)<<"]Re-runs ConstantFolding: "
-cR
-DumpHashes(tree);
-#endif
-}
-if(t72!=cImmed){yD3
-p=CalculateResultBoundaries(tree);if(p
-yI&&p
-e61&&p
-yM==p
-tG1{nU
-p
-yM);nD}
-if(false){ReplaceTreeWithOne:nU
-e62
-1));goto
-do_return;ReplaceTreeWithZero:nU
-xG1;goto
-do_return;ReplaceTreeWithParam0:
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Before replace: "
-;cV2<<std::hex<<'['
-eJ1
-hash1<<','
-eJ1
-hash2<<']'<<std::dec
-cR
-#endif
-tree.eF2
-0));
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"After replace: "
-;cV2<<std::hex<<'['
-eJ1
-hash1<<','
-eJ1
-hash2<<']'<<std::dec
-cR
-#endif
-cJ
-c73(t72){case
-cImmed:lC
-iU2:lC
-cAnd:case
-cAbsAnd
-cK
-bool
-c5
-eW3
-for
-l41{if(!c83
-a)))c5=true;cA3
-a),t72==cAbsAnd)){case
-xX3
-t7
-iF2:iZ);lC
-lZ1
-c73
-l51){case
-0:iD
-1:tD2
-t72==cAnd?cNotNot:cAbsNotNot);cJ
-yF3
-cZ2
-cAnd||!c5)if(ConstantFolding_AndLogic(tB2
-e21
-cOr:case
-cAbsOr
-cK
-bool
-c5
-eW3
-for
-l41{if(!c83
-a)))c5=true;cA3
-a),t72==cAbsOr)tN1
-iD
-l03
-iZ);lC
-lZ1
-c73
-l51){case
-0
-t7
-1:tD2
-t72==cOr?cNotNot:cAbsNotNot);cJ
-yF3
-cZ2
-cOr||!c5)if(ConstantFolding_OrLogic(tB2
-e21
-cNot:case
-cC3:{x83
-n61
-0;e23
-c93){case
-cEqual:n61
-i51;lC
-i51:n61
-cEqual;lC
-cLess:n61
-cGreaterOrEq;lC
-cGreater:n61
-cLessOrEq;lC
-cLessOrEq:n61
-cGreater;lC
-cGreaterOrEq:n61
-cLess;lC
-cNotNot:n61
-cNot;lC
-cNot:n61
-cNotNot;lC
-cC3:n61
-cAbsNotNot;lC
-cAbsNotNot:n61
-cC3;break;yF3
-xY3
-if(opposite){tD2
-OPCODE(opposite)yB
-SetParamsMove(xW
-0).GetUniqueRef().lJ2));cJ
-c73(lY1
-0)cU3
-cQ1){case
-iF2
-t7
-l03
-iD
-lZ1
-cZ2
-cNot&&GetPositivityInfo(xW
-0))==iF2)tD2
-cC3);if(c93==cIf||c93==cAbsIf
-nQ
-iZ2=xW
-0);iT1&ifp1=iZ2
-l8
-1);iT1&ifp2=iZ2
-l8
-2);if(ifp1
-nC
-iY3
-ifp1
-cQ1
-cD3
-ifp1
-nC==cNot?cNotNot:cAbsNotNot);tR2
-c43
-n63)cE3
-nO2;p2
-tT3
-iI
-if(ifp2
-nC
-iY3
-ifp2
-cQ1
-cD3
-t72);tR2);n63)cE3
-iH
-ifp2
-nC==cNot?cNotNot:cAbsNotNot);p2
-tT3
-l8
-0)iI
-e21
-cNotNot:case
-cAbsNotNot:{if(c83
-0)))n73
-cA3
-0),t72==cAbsNotNot)){case
-xX3
-t7
-iF2:iD
-lZ1
-cZ2
-cNotNot&&GetPositivityInfo(xW
-0))==iF2)tD2
-cAbsNotNot);if(c93==cIf||c93==cAbsIf
-nQ
-iZ2=xW
-0);iT1&ifp1=iZ2
-l8
-1);iT1&ifp2=iZ2
-l8
-2);if(ifp1
-nC
-iY3
-ifp1
-cQ1{tree.SetParam(0,iZ2
-l8
-0)yB
-AddParam(ifp1)cE3
-nO2;p2
-tT3
-iI
-if(ifp2
-nC
-iY3
-ifp2
-cQ1
-cD3
-t72);tR2);n63
-yB
-AddParam(ifp2
-yB
-eL3
-iZ2
-nC);cJ}
-e21
-cIf:case
-cAbsIf:{if(ConstantFolding_IfOperations(tB2
-xY3
-case
-cMul:{NowWeAreMulGroup:;AdoptChildrenWithSameOpcode(tree)iK2
-nH1=e62
-1);size_t
-lC2=0;bool
-nI1
-eW3
-x51{if(!xW
-tC1
-yA1
-Value_t
-immed=xW
-a)x41;if(immed==xG1
-goto
-ReplaceTreeWithZero;nH1*=immed;++lC2;}
-if(lC2>1||(lC2==1&&lJ3
-nH1,e62
-1))))nI1=true;if(nI1){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"cMul: Will add new "
-iJ3
-nH1<<"\n"
-;
-#endif
-for
-l41
-if(xW
-tC1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<" - For that, deleting "
-iJ3
-xW
-a)x41;cV2<<"\n"
-;
-#endif
-tU3(!lJ3
-nH1,e62
-1)))tree
-cS
-eA1
-nH1));c73
-l51){case
-0:iD
-1:n73
-yF3
-if(ConstantFolding_MulGrouping(tB2
-if(ConstantFolding_MulLogicItems(tB2
-e21
-cAdd
-cK
-Value_t
-nD2=0.0;size_t
-lC2=0;bool
-nI1
-eW3
-x51{if(!xW
-tC1
-yA1
-Value_t
-immed=xW
-a)x41;nD2+=immed;++lC2;}
-if(lC2>1||(lC2==1&&nD2==xG1)nI1=true;if(nI1){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"cAdd: Will add new "
-iJ3
-nD2<<"\n"
-;cV2<<"In: "
-cR
-#endif
-for
-l41
-if(xW
-tC1{
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<" - For that, deleting "
-iJ3
-xW
-a)x41;cV2<<"\n"
-;
-#endif
-tU3(!(nD2==e62
-0.0)))tree
-cS
-eA1
-nD2));c73
-l51){case
-0
-t7
-1:n73
-yF3
-if(ConstantFolding_AddGrouping(tB2
-if(ConstantFolding_AddLogicItems(tB2
-e21
-cMin
-cK
-size_t
-yI2=0;yD3
-e4;x51{while(a+1<tree.GetParamCount()&&xW
-a)xI
-xW
-a+1)))iZ+1);yE3
-max.cF3(!e4
-e61||(p
-tG1<e4
-tG1){e4
-nL3=p
-nL3;e4
-e61=true;yI2=a;}
-}
-if(e4
-e61)for
-l41{yE3
-min.cF3
-a!=yI2&&p
-yM>=e4
-tG1
-tU3
-l51==1){n73
-e21
-cMax
-cK
-size_t
-yI2=0;yD3
-eY;x51{while(a+1<tree.GetParamCount()&&xW
-a)xI
-xW
-a+1)))iZ+1);yE3
-min.cF3(!eY
-yI||p
-yM>eY
-yM)){eY
-yM=p
-yM;eY
-yI=true;yI2=a;}
-}
-if(eY
-yI){for
-l41{yE3
-max.cF3
-a!=yI2&&(p
-tG1<eY
-yM){iZ);}
-}
-}
-if
-l51==1){n73
-e21
-cEqual:case
-i51:case
-cLess:case
-cGreater:case
-cLessOrEq:case
-cGreaterOrEq:if(ConstantFolding_Comparison(tB2
-lC
-cAbs:{yD3
-tY
-xW
-0));if
-iE
-n73
-if
-iF{tD2
-cMul
-yB
-yA
-e62
-1)));goto
-NowWeAreMulGroup;}
-if(c93==cMul){iT1&p=xW
-0);eK
-n83;eK
-cP2
-e73
-0;a<p.l91++a){tY
-p
-n93
-if
-iE{n83
-c52
-p
-n93}
-if
-iF{cP2
-c52
-p
-n93}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"Abs: mul group has "
-<<n83
-eJ3<<" pos, "
-<<cP2
-eJ3<<"neg\n"
-;
-#endif
-if(!n83
-eU3||!cP2
-eU3){
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"AbsReplace-Before: "
-iL2
-tree
-lE2"\n"
-<<std::flush;DumpHashes
-nV2);
-#endif
-yZ2
-e13;e13
-iH
-cMul
-iY1
-0;a<p.l91++a){tY
-p
-n93
-if(iE||iF){}
-else
-e13
-cS
-p
-n93}
-e13
-iW1
-tX
-nB3;nB3
-iH
-cAbs);nB3
-c91
-e13);nB3
-iW1
-tX
-iG
-cMul);mulgroup
-c91
-nB3);cA1
-AddParamsMove(n83);if(!cP2
-eU3){if(cP2
-eJ3%2)cA1
-yA
-nU2));cA1
-AddParamsMove(cP2);}
-tree.Become
-eH2);
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"AbsReplace-After: "
-;DumpTree
-nV2
-lE2"\n"
-<<std::flush;DumpHashes
-nV2);
-#endif
-goto
-NowWeAreMulGroup;}
-}
-xY3
-#define HANDLE_UNARY_CONST_FUNC(funcname) nP){nU funcname(lR));nD
-case
-cLog:i83(fp_log);if(c93==cPow
-nQ
-pow=xW
-0);if(GetPositivityInfo(pow
-l8
-0))==iF2)iV1
-t2
-yB
-lU
-if(GetEvennessInfo(pow
-l8
-1))==iF2)iV1()tX
-abs;abs
-iH
-cAbs);abs
-c91
-pow
-c43
-abs.Rehash
-t2);pow.nB1
-0,abs
-yB
-lU}
-iP1
-c93==cAbs
-nQ
-pow=xW
-0)l8
-0);if(pow
-nC==cPow)iV1()tX
-abs;abs
-iH
-cAbs);abs
-c91
-pow
-c43
-abs.Rehash
-t2);pow.nB1
-0,abs
-yB
-lU}
-lC
-cAcosh:i83(fp_acosh);lC
-cAsinh:i83(fp_asinh);lC
-cAtanh:i83(fp_atanh);lC
-cAcos:i83(fp_acos);lC
-cAsin:i83(fp_asin);lC
-cAtan:i83(fp_atan);lC
-cCosh:i83(fp_cosh);lC
-cSinh:i83(fp_sinh);lC
-cTanh:i83(fp_tanh);lC
-cSin:i83(fp_sin);lC
-cCos:i83(fp_cos);lC
-cTan:i83(fp_tan);lC
-cCeil:if(n5
-i83(fp_ceil);lC
-cTrunc:if(n5
-i83(fp_trunc);lC
-cFloor:if(n5
-i83(fp_floor);lC
-cInt:if(n5
-i83(fp_int);lC
-cCbrt:i83(fp_cbrt);lC
-cSqrt:i83(fp_sqrt);lC
-cExp:i83(fp_exp);lC
-cLog2:i83(fp_log2);lC
-cLog10:i83(fp_log10);lC
-cQ3:if
-lI
-fp_log2(lR)*xW
-nC3
-cArg:i83(fp_arg);lC
-cConj:i83(fp_conj);lC
-cImag:i83(fp_imag);lC
-cReal:i83(fp_real);lC
-cPolar:if
-lI
-fp_polar
-e51
-lC
-cMod:if
-lI
-fp_mod
-e51
-lC
-cAtan2:{yD3
-tY
-xW
-yP2
-p1=tZ
-1));nP&&lJ3
-lR,xG1){if(p1
-e61&&(p1
-tG1<xG1{nU
-fp_const_pi
-cH3
-if(p1
-yI&&p1
-yM>=tE1
-xG1;nD}
-if(eI1
-lJ3
-xW
-i8,xG1){if(p0
-e61&&(p0
-tG1<xG1{nU-fp_const_pihalf
-cH3
-if
-cN3
-p0
-yM>xG1{nU
-fp_const_pihalf
-cH3}
-if
-lI
-fp_atan2
-e51
-if((p1
-yI&&p1
-yM>xG1||(p1
-e61&&(p1
-tG1<fp_const_negativezero
-xF())nQ
-yJ2;yJ2
-iH
-cPow);yJ2
-c91
-xW
-1));yJ2.yA
-nU2));yJ2
-iW1
-tX
-yK2;yK2
-iH
-cMul);yK2
-c91
-xW
-0));yK2
-c91
-yJ2);yK2
-cY
-cAtan
-yB
-nB1
-0,yK2
-yB
-i91
-1);e21
-cPow:{if(ConstantFolding_PowOperations(tB2
-xY3
-case
-cDiv:nP&&eI1
-xW
-i8!=tE1
-lR/xW
-nC3
-cInv:nP&&lR!=tE1
-e62
-1)/lR);nD
-lC
-cSub:if
-lI
-lR-xW
-nC3
-cNeg:nP){nU-lR);nD
-lC
-cRad:nP){nU
-RadiansToDegrees
-eG2
-cDeg:nP){nU
-DegreesToRadians
-eG2
-cSqr:nP){nU
-lR*lR);nD
-lC
-cExp2:i83(fp_exp2);lC
-cRSqrt:nP){nU
-e62
-1)/fp_sqrt
-eG2
-cCot:c22
-fp_tan(lZ
-cSec:c22
-fp_cos(lZ
-cCsc:c22
-fp_sin(lZ
-cHypot:if
-lI
-fp_hypot
-e51
-lC
-cRDiv:case
-cRSub:case
-cDup:case
-cFetch:case
-cPopNMov:case
-cSinCos:case
-cSinhCosh:case
-cNop:case
-cJump:lC
-cPCall:case
-cFCall:xY3
-do_return:;
-#ifdef DEBUG_SUBSTITUTIONS
-cV2<<"["
-<<(&c63)<<"]Done ConstantFolding, result: "
-cR
-DumpHashes(tree);
-#endif
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-t5{xL1
-yD3::set_abs(nL
-bool
-has_negative=!min.known||min.val<e62);bool
-has_positive=!cG3||max.val>e62);bool
-crosses_axis=has_negative&&has_positive;cI1
-xF
-newmax;if(min.cF3
-cG3)newmax.set(fp_max(i61,i71);if(crosses_axis
-cI3
-e62));cJ3
-min.cF3
-cG3
-cI3
-fp_min(i61,i71);iP1
-min.known
-cI3
-i61);else
-min.set(i71;}
-max=newmax;}
-xL1
-yD3::set_neg(){std::swap(min,max);min.val=-min.val;max.val=-max.val;}
-yP1
-IsLogicalTrueValue
-iS1
-yD3&p,bool
-abs){if(nB
-IsIntType
-xF::nS3){if(p
-yI&&p
-yM>=e62
-1))lD2
-if(!abs&&p
-e61
-t43<=nU2)lD2}
-cJ3
-p
-yI&&p
-yM>=yF2)lD2
-if(!abs&&p
-e61
-t43<=e62-0.5))lD2
-eE3
-t23
-yP1
-IsLogicalFalseValue
-iS1
-yD3&p,bool
-abs){if(nB
-IsIntType
-xF::nS3){if(abs)eG3
-e61
-l61
-1);else
-eG3
-yI&&p
-e61&&p
-yM>nU2
-l61
-1);}
-cJ3
-abs)eG3
-e61
-l61
-0.5);else
-eG3
-yI&&p
-e61&&p
-yM>e62-0.5)l61
-0.5);}
-}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;using
-t5;t5{tK1
-yD3
-CalculateResultBoundaries
-iS1
-eR
-#ifdef DEBUG_SUBSTITUTIONS_extra_verbose
-{using
-l33
-FUNCTIONPARSERTYPES;yD3
-tmp=CalculateResultBoundaries_do(tree
-lE2"Estimated boundaries: "
-;if(tmp
-yI)cV2<<tmp
-yM;else
-cV2<<"-inf"
-;cV2<<" .. "
-;if(tmp
-e61)cV2<<tmp
-nL3;else
-cV2<<"+inf"
-;cV2<<": "
-iL2
-tree
-lE2
-std::endl
-i1
-tmp;}
-tK1
-yD3
-yZ2::CalculateResultBoundaries_do
-iS1
-eR
-#endif
-{iS
-yH1(-fp_const_pihalf
-xF(),fp_const_pihalf
-xF());iS
-pi_limits(-fp_const_pi
-xF(),fp_const_pi
-xF());iS
-abs_pi_limits(xH1,fp_const_pi
-xF());iS
-plusminus1_limits(nU2,e62
-1));using
-l33
-std;e23
-t72){case
-cImmed:nM
-tree
-x41
-cU3
-x41)t83
-cAnd:case
-cAbsAnd:case
-cOr:case
-cAbsOr:case
-cNot:case
-cC3:case
-cNotNot:case
-cAbsNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:{nM
-xH1,e62
-1));}
-case
-cAbs:tW3
-set_abs();tK
-cLog:tW3
-tS2
-fp_log);nD3
-fp_log);tK
-cLog2:tW3
-tS2
-fp_log2);nD3
-fp_log2);tK
-cLog10:tW3
-tS2
-fp_log10);nD3
-fp_log10);tK
-cAcosh:tW3
-min.tL1
-cGreaterOrEq
-tH1
-fp_acosh
-tR3
-cGreaterOrEq
-tH1
-fp_acosh);tK
-cAsinh:tW3
-min.set(fp_asinh);tO
-set(fp_asinh);tK
-cAtanh:tW3
-min.n3-1),fp_atanh
-tR3
-cLess
-tH1
-fp_atanh);tK
-cAcos:lD
-nM(tO
-cF3(tO
-val)<e62
-1))?fp_acos(tO
-val):xH1,(m
-yI&&(m
-yM)>=nU2)?fp_acos(m
-yM):fp_const_pi
-xF());}
-case
-cAsin:tW3
-min.n3-1),fp_asin,yH1
-yM
-tR3
-cLess
-tH1
-fp_asin,yH1
-tG1;tK
-cAtan:tW3
-min.set(fp_atan,yH1
-yM);tO
-set(fp_atan,yH1
-tG1;tK
-cAtan2:{nP&&lJ3
-lR,xG1)yP
-abs_pi_limits;}
-if(eI1
-lJ3
-xW
-i8,xG1)yP
-yH1;eE3
-pi_limits;}
-case
-cSin:lD
-bool
-x11=!m
-yI||!tO
-known||(tO
-val-m
-yM)>=(yK
-x11)tM
-Value_t
-min=cK3
-m
-yM,yK
-min<xG1
-min
-yN
-Value_t
-max=cK3
-tO
-val,yK
-max<xG1
-max
-yN
-if(max<min)max
-yN
-bool
-y21=(min<=fp_const_pihalf
-xF()&&max>=fp_const_pihalf
-xF());bool
-nJ1=(min<=cD&&max>=cD);if(y21&&nJ1)tM
-if(nJ1)nM
-nU2,nW2
-if(y21)nM
-yL2
-e62
-1));nM
-yL2
-nW2}
-case
-cCos:lD
-if(m
-yI)m
-yM+=fp_const_pihalf
-xF();if(xI2
-tO
-val+=fp_const_pihalf
-xF();bool
-x11=!m
-yI||!tO
-known||(tO
-val-m
-yM)>=(yK
-x11)tM
-Value_t
-min=cK3
-m
-yM,yK
-min<xG1
-min
-yN
-Value_t
-max=cK3
-tO
-val,yK
-max<xG1
-max
-yN
-if(max<min)max
-yN
-bool
-y21=(min<=fp_const_pihalf
-xF()&&max>=fp_const_pihalf
-xF());bool
-nJ1=(min<=cD&&max>=cD);if(y21&&nJ1)tM
-if(nJ1)nM
-nU2,nW2
-if(y21)nM
-yL2
-e62
-1));nM
-yL2
-nW2}
-case
-cTan:{nM);}
-case
-cCeil:lD
-tO
-i81
-cFloor:lD
-m
-yI1
-tK
-cTrunc:lD
-m
-yI1
-tO
-i81
-cInt:lD
-m
-yI1
-tO
-i81
-cSinh:tW3
-min.set(fp_sinh);tO
-set(fp_sinh);tK
-cTanh:tW3
-min.set(fp_tanh,plusminus1_limits.min);tO
-set(fp_tanh,plusminus1_limits.max);tK
-cCosh:lD
-if(m
-yI){if(xI2{if(m
-yM>=xH1&&tO
-val>=xG1{m
-yM
-xS}
-iP1(m
-yM)<xH1&&tO
-val>=xG1
-l14
-tmp
-xS
-if(tmp>tO
-val)tO
-val=tmp;m
-yM=e62
-1);}
-else{m
-yM
-xS
-std::swap(m
-yM,tO
-val);}
-}
-cJ3
-m
-yM>=xG1{m.tL
-m
-yM=fp_cosh(m
-yM);}
-else{m.tL
-m
-yM=e62
-1);}
-}
-}
-else{m
-yI=true;m
-yM=e62
-1);if(xI2{m
-yM=fp_cosh(tO
-val);m.tL}
-else
-m.tL}
-tK
-cIf:case
-cAbsIf:{yD3
-res1=tZ
-1));yD3
-res2=tZ
-2));if(!res2
-yI)res1
-yI
-eW3
-iP1
-res1
-yI&&(res2
-yM)<res1
-yM)res1
-yM=res2
-yM;if(!res2
-e61)res1.tL
-iP1
-res1
-e61&&(res2
-tG1>res1
-tG1
-res1
-nL3=res2
-nL3
-i1
-res1;}
-case
-cMin:{bool
-iT
-eW3
-bool
-iU
-eW3
-e83;x7
-m
-tZ3
-m
-yI)iT
-iN3
-yI||(m
-yM)<nF3)nF3=m
-yM;if(!xI2
-iU
-iN3
-e61||(tO
-val)<nG3
-nH3=tO
-val;}
-if(iT)nK3
-iU)nQ3
-return
-nR3
-cMax:{bool
-iT
-eW3
-bool
-iU
-eW3
-e83;x7
-m
-tZ3
-m
-yI)iT
-iN3
-yI||m
-yM>nF3)nF3=m
-yM;if(!xI2
-iU
-iN3
-e61||tO
-val>nG3
-nH3=tO
-val;}
-if(iT)nK3
-iU)nQ3
-return
-nR3
-cAdd:{e83(xH1,xG1;x7
-item=tZ
-a));if(item
-yI)nF3+=item
-yM;else
-nK3
-item
-e61)nH3+=item
-nL3;else
-nQ3
-if(!nI3&&!nJ3)xY3
-if(nI3&&nJ3&&nF3>nG3
-std::swap(nF3,nG3
-i1
-nR3
-cMul:{e72
-Value{enum
-nT3{tT2,lG2,PlusInf}
-;nT3
-eB
-iK2
-value;Value(nT3
-t):eB(t),value(0){}
-Value
-cX3
-v):eB(tT2),value(v){}
-bool
-cQ2
-c01
-eB==lG2||(eB==tT2&&value<xG1;}
-void
-eM1*=iS1
-Value&rhs){if(eB==tT2&&rhs.eB==tT2)value*=rhs.value;else
-eB=(cQ2)!=rhs.cQ2)?lG2:PlusInf);}
-iD2<iS1
-Value&rhs
-c01(eB==lG2&&rhs.eB!=lG2)||(eB==tT2&&(rhs.eB==PlusInf||(rhs.eB==tT2&&value<rhs.value)));}
-}
-;e72
-yJ1{Value
-yN2,yO2;yJ1():yN2(Value::PlusInf),yO2(Value::lG2){}
-void
-xJ2
-Value
-cM3,const
-Value&value2){cM3*=value2;if(cM3<yN2)yN2=cM3;if(yO2<cM3)yO2=cM3;}
-}
-;e83(nM3
-x7
-item
-tZ3
-item
-yI&&!item
-e61)nM);Value
-iP3=nI3?Value(nF3):xC2
-lG2);Value
-nU3=nJ3?Value(nG3:xC2
-PlusInf);Value
-nV3=item
-yI?Value(item
-yM):xC2
-lG2);Value
-nW3=item
-e61?Value(item
-tG1:xC2
-PlusInf);yJ1
-range;range.xJ2
-iP3,nV3);range.xJ2
-iP3,nW3);range.xJ2
-nU3,nV3);range.xJ2
-nU3,nW3);if(range.yN2.eB==Value::tT2)nF3=range.yN2.value;else
-nK3
-range.yO2.eB==Value::tT2)nH3=range.yO2.value;else
-nQ3
-if(!nI3&&!nJ3)xY3
-if(nI3&&nJ3&&nF3>nG3
-std::swap(nF3,nG3
-i1
-nR3
-cMod:{yD3
-x=tZ
-yP2
-y=tZ
-1));if(y
-e61){if(y
-nL3>=xG1{if(!x
-yI||(x
-yM)<xG1
-nM-y
-nL3,y
-tG1;i03
-xH1,y
-tG1;}
-cJ3!x
-e61||(x
-tG1>=xG1
-nM
-y
-nL3,-y
-tG1;i03
-y
-nL3,fp_const_negativezero
-xF());}
-}
-i03);}
-case
-cPow:{if(eI1
-xW
-i8==xG1{nM
-nM3}
-nP&&lR==xG1{nM
-xH1,xG1;}
-nP&&lJ3
-lR
-nH2
-nM
-nM3}
-if(eI1
-xW
-i8>xH1&&GetEvennessInfo(xW
-1))==iF2)l14
-eD2
-xW
-i8;yD3
-tmp=tZ
-yP2
-nS3;nI3=true;nF3=0;if(tmp
-yI&&tmp
-yM>=xG1
-nF3=t33
-tmp
-yM,tU2
-iP1
-tmp
-e61&&tmp
-nL3<=xG1
-nF3=t33
-tmp
-nL3,tU2
-nQ3
-if(tmp
-yI&&tmp
-e61){nJ3=true;nH3=fp_max(fp_abs(tmp
-yM),fp_abs(tmp
-tG1);nH3=t33
-nH3,tU2
-eE3
-nS3;}
-yD3
-tY
-xW
-yP2
-p1=tZ
-1));TriTruthValue
-p0_positivity=cN3(p0
-yM)>=xG1?iF2:(p0
-e61&&(p0
-tG1<xH1?l03
-Unknown);TriTruthValue
-cR2=GetEvennessInfo(xW
-1));TriTruthValue
-eZ=Unknown;e23
-p0_positivity
-tN1
-eZ=iF2;lC
-l03{eZ=cR2;xY3
-yF3
-e23
-cR2
-tN1
-eZ=iF2;lC
-l03
-lC
-Unknown:{if(eI1!t42
-xW
-i8)&&xW
-i8>=xG1{eZ=iF2;}
-xY3}
-c73(eZ
-tN1
-l14
-min=xH1;if
-cN3
-p1
-yI){min=t33
-p0
-yM,p1
-yM);if(p0
-yM<xH1&&(!p1
-e61||p1
-nL3>=xG1&&min>=xG1
-min=xH1;}
-if
-cN3
-p0
-yM>=xH1&&p0
-e61&&p1
-e61)l14
-max=t33
-p0
-nL3,p1
-tG1;if(min>max)std::swap(min,max);nM
-min,max);}
-nM
-min,false);}
-case
-l03{nM
-false,fp_const_negativezero
-xF());}
-yF3{xY3
-e21
-cNeg:tW3
-set_neg();tK
-cSub:yJ
-cNeg);tmp2
-tX3
-tmp
-iH
-cAdd);tmp
-tY3
-tmp
-c91
-tmp2
-i0
-cInv:{c02
-lW-1))i0
-cDiv:yJ
-cInv);tmp2
-tX3
-tmp
-iH
-xC1
-AddParamMove(tmp2
-i0
-cRad:yV
-xC1
-yA
-fp_const_rad_to_deg
-xF())i0
-cDeg:yV
-xC1
-yA
-fp_const_deg_to_rad
-xF())i0
-cSqr:{c02
-lW
-2))i0
-cExp:yV
-cPow);tmp.yA
-fp_const_e
-xF()));tmp.nJ
-0)i0
-cExp2:yV
-cPow);tmp.yA
-nX3
-tmp.nJ
-0)i0
-cCbrt:tW3
-min.set(fp_cbrt);tO
-set(fp_cbrt);tK
-cSqrt:lD
-if(m
-yI)m
-yM=(m
-yM)<xH1?0:fp_sqrt(m
-yM);if(xI2
-tO
-val=(tO
-val)<xH1?0:fp_sqrt(tO
-val);tK
-cRSqrt:{c02
-lW-0.5))i0
-cHypot:{yZ2
-xsqr,ysqr,add,sqrt;xsqr
-tY3
-xsqr.yA
-nX3
-ysqr
-tX3
-ysqr.yA
-nX3
-xsqr
-iH
-cPow);ysqr
-iH
-cPow);add
-c91
-xsqr);add
-c91
-ysqr);add
-iH
-cAdd);sqrt
-c91
-add);sqrt
-iH
-cSqrt)i1
-CalculateResultBoundaries(sqrt);}
-case
-cQ3:yJ
-cLog2);tmp2
-tY3
-tmp
-iH
-cMul);tmp
-c91
-tmp2);tmp.nJ
-1)i0
-cCot:yJ
-cTan)x6
-lH
-cSec:yJ
-cCos)x6
-lH
-cCsc:yJ
-cSin)x6
-CalculateResultBoundaries(tmp);}
-lC
-cRDiv:case
-cRSub:case
-cDup:case
-cFetch:case
-cPopNMov:case
-cSinCos:case
-cSinhCosh:case
-cNop:case
-cJump:case
-iU2:lC
-cArg:case
-cConj:case
-cImag:case
-cReal:case
-cPolar:lC
-cPCall:lC
-cFCall:xY3
-nM);}
-tK1
-TriTruthValue
-GetIntegerInfo
-iS1
-eR{e23
-t72){case
-cImmed:return
-t42
-tree
-x41)?iF2:xX3
-t83
-cFloor:case
-cCeil:case
-cTrunc:case
-cInt:return
-iF2
-t83
-cAnd:case
-cOr:case
-cNot:case
-cNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:return
-iF2
-t83
-cIf:{TriTruthValue
-a=GetIntegerInfo(xW
-1));TriTruthValue
-b=GetIntegerInfo(xW
-2));if(a==b)return
-a
-xO2
-case
-cAdd:case
-cMul:{for
-l41
-if(GetIntegerInfo(xW
-a))!=iF2)return
-Unknown
-i1
-iF2;}
-yF3
-xY3
-return
-Unknown;}
-yP1
-IsLogicalValue
-iS1
-eR{e23
-t72){case
-cImmed:return
-lJ3
-tree
-x41,xG1||lJ3
-tree
-x41,e62
-1))t83
-cAnd:case
-cOr:case
-cNot:case
-cNotNot:case
-cAbsAnd:case
-cAbsOr:case
-cC3:case
-cAbsNotNot:case
-cEqual:case
-i51:case
-cLess:case
-cLessOrEq:case
-cGreater:case
-cGreaterOrEq:nZ
-cMul:{for
-l41
-if(!c83
-a))cQ
-lD2}
-case
-cIf:case
-cAbsIf:yP
-c83
-1))&&c83
-2));}
-yF3
-xY3
-return
-t23}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;
-#if defined(__x86_64) || !defined(FP_SUPPORT_CPLUSPLUS11_MATH_FUNCS)
-# define CBRT_IS_SLOW
-#endif
-#if defined(DEBUG_POWI) || defined(DEBUG_SUBSTITUTIONS)
-#include <cstdio>
-#endif
-l33
-xK1{extern
-const
-x83
-char
-powi_table[256];}
-l33{using
-t5
-yO1
-bool
-IsOptimizableUsingPowi(long
-immed,long
-penalty=0){xK1::eP3
-synth;synth.PushVar(iU2);size_t
-bytecodesize_backup=synth.GetByteCodeSize();xK1::x01
-immed,xK1::tU1
-xF::MulSequence,c92
-size_t
-bytecode_grow_amount=synth.GetByteCodeSize()-bytecodesize_backup
-i1
-bytecode_grow_amount<size_t(MAX_POWI_BYTECODE_LENGTH-penalty);}
-xL1
-ChangeIntoRootChain(nP1
-bool
-l13,long
-tY2,long
-tZ2){while(tZ2>0
-t82
-cCbrt);t92);tmp.e33
-xD2--tZ2;}
-while(tY2>0
-t82
-cSqrt);if(l13){tmp
-iH
-cRSqrt);l13
-eW3}
-t92);tmp.e33
-xD2--tY2;}
-if(l13
-t82
-cInv);t92
-xD2}
-}
-tK1
-e72
-RootPowerTable{static
-const
-Value_t
-RootPowers[(1+4)*(1+3)];}
-yO1
-const
-Value_t
-t9(1+4)*(1+3)]={e62
-1)lS
-2)lS
-2*2)lS
-2*2*2)lS
-2*2*2*2)lS
-3)lS
-3*2)lS
-3*2*2)lS
-3*2*2*2)lS
-3*2*2*2*2)lS
-3*3)lS
-3*3*2
-yG3
-yG3*2
-yG3*2*2)lS
-3*3*3
-eY2
-eY2*2
-eY2*2*2
-eY2*2*2*2)}
-;e72
-PowiResolver{static
-const
-x83
-MaxSep=4;static
-x03
-i13=5;typedef
-int
-cO3;typedef
-long
-x43;typedef
-long
-tP;e72
-yS2{yS2():n_int_sqrt(0),n_int_cbrt(0),sep_list(),n01(0){}
-int
-n_int_sqrt;int
-n_int_cbrt;int
-tT1
-MaxSep];tP
-n01;}
-yO1
-static
-yS2
-CreatePowiResult
-cX3
-exponent){yS2
-nS3;cO3
-tA=FindIntegerFactor(tU2
-if(tA==0){
-#ifdef DEBUG_POWI
-i02"no factor found for %Lg\n"
-,(cP3);
-#endif
-return
-nS3;}
-nS3.n01=y31
-exponent,tA);x43
-eT2=EvaluateFactorCost(tA,0,0,0)+cC
-nS3.n01);int
-s_count=0;int
-i23=0;int
-nZ3=0;
-#ifdef DEBUG_POWI
-i02"orig = %Lg\n"
-,(cP3);i02"plain factor = "
-iL3"%ld\n"
-,(int)tA,(long)eT2);
-#endif
-for
-lT1
-n_s=0;n_s<MaxSep;++n_s){int
-xD=0;x43
-yK1=eT2;cO3
-yX1=tA;for(int
-s=1;s<i13*4;++s){
-#ifdef CBRT_IS_SLOW
-if(s>=i13)break;
-#endif
-int
-n_sqrt=s%i13;int
-n_cbrt=s/i13;if(n_sqrt+n_cbrt>4)yA1
-Value_t
-lN1=exponent;lN1-=t9
-s];iE1=FindIntegerFactor(lN1);if(xT2!=0){tP
-xN=y31
-lN1,xT2);x43
-cost=EvaluateFactorCost(xT2,s_count+n_sqrt,i23+n_cbrt,nZ3+1)+cC
-xN);
-#ifdef DEBUG_POWI
-i02"Candidate sep %u (%d*sqrt %d*cbrt)factor = "
-iL3"%ld (for %Lg to %ld)\n"
-,s,n_sqrt,n_cbrt,xT2,(long)cost
-cX2
-lN1,(long)xN);
-#endif
-if(cost<yK1){xD=s;yX1=xT2;yK1=cost;}
-}
-}
-if(!xD)break;
-#ifdef DEBUG_POWI
-i02"CHOSEN sep %u (%d*sqrt %d*cbrt)factor = "
-iL3"%ld, exponent %Lg->%Lg\n"
-,xD,xD%i13,xD/i13,yX1,yK1
-cX2(exponent)cX2(exponent-t9
-xD]));
-#endif
-nS3.tT1
-n_s]=xD
-eX3-=t9
-xD];s_count+=xD%i13;i23+=xD/i13;eT2=yK1;tA=yX1;nZ3+=1;}
-nS3.n01=y31
-exponent,tA);
-#ifdef DEBUG_POWI
-i02"resulting exponent is %ld (from exponent=%Lg, best_factor=%Lg)\n"
-,nS3.n01,(cP3
-cX2
-tA);
-#endif
-while(tA%2==0){++nS3
-e52;tA/=2;}
-while(tA%3==0){++nS3.n_int_cbrt;tA/=3;eE3
-nS3;}
-private:static
-x43
-cC
-tP
-xN){static
-std::map
-cS2
-iM;if(xN<0){x43
-cost=22
-i1
-cost+cC-xN);}
-std::map
-cS2::y83
-i=iM.xU2
-xN);if(i!=iM.cX1
-xN)return
-i
-eC2;std::pair
-cS2
-nS3(xN,0.0);x43&cost=nS3.i63
-while(xN>1){int
-xT2=0;if(xN<256){xT2=xK1::powi_table[xN];if(xT2&128)xT2&=127;else
-xT2=0;if(xT2&64)xT2=-(xT2&63)-1;}
-if(xT2){cost+=cC
-xT2);xN/=xT2;yA1}
-if(!(xN&1)){xN/=2;cost+=6;}
-else{cost+=7;xN-=1;}
-}
-iM.y43,nS3)i1
-cost;}
-cB1
-tP
-y31
-yL1,iE1)yP
-makeLongInteger(value*e62
-xT2));}
-cB1
-bool
-yM1
-yL1,iE1)l14
-v=value*e62
-xT2)i1
-isLongInteger(v);}
-cB1
-cO3
-FindIntegerFactor(yL1){iE1=(2*2*2*2);
-#ifdef CBRT_IS_SLOW
-#else
-xT2*=(3*3*3);
-#endif
-cO3
-nS3=0;if(yM1
-value,xT2)){nS3=xT2;while((xT2%2)==0&&yM1
-value,xT2/2))nS3=xT2/=2;while((xT2%3)==0&&yM1
-value,xT2/3))nS3=xT2/=3;}
-#ifdef CBRT_IS_SLOW
-if(nS3==0){if(yM1
-value,3
-y03
-3;}
-#endif
-return
-nS3;}
-static
-int
-EvaluateFactorCost(int
-xT2,int
-s,int
-c,int
-nmuls){x03
-x13=6;
-#ifdef CBRT_IS_SLOW
-x03
-eU2=25;
-#else
-x03
-eU2=8;
-#endif
-int
-nS3=s*x13+c*eU2;while(xT2%2==0){xT2/=2;nS3+=x13;}
-while(xT2%3==0){xT2/=3;nS3+=eU2;}
-nS3+=nmuls
-i1
-nS3;}
-}
-;}
-t5{yP1
-yZ2::RecreateInversionsAndNegations(bool
-prefer_base2){bool
-changed=false
-e73
-0;a<l91++a)if(lX1.RecreateInversionsAndNegations(prefer_base2))yS1
-if(changed){exit_changed:Mark_Incompletely_Hashed(yQ2
-e23
-l92{case
-cMul:{eK
-nE2
-tX
-nF2,cR1;if(true){bool
-nK1=false
-iK2
-xE2=0
-e73
-tI1
-i12
-tI
-0)i22
-tI
-1)tD1){nK1=true;xE2=tI
-i8;xY3}
-if(nK1)l14
-immeds=1.0
-e73
-tI1
-tD1){immeds*=powgroup
-x41;yN1}
-for
-iZ1
-a=l91
-a-->0;nQ&powgroup=lX1;if(powgroup
-i12
-tI
-0)i22
-tI
-1)tD1
-nQ&log2=tI
-0);log2.lD1
-log2
-iH
-cQ3);log2.yA
-t33
-immeds,e62
-1)/xE2)));log2
-iW1;xY3}
-}
-}
-for
-iZ1
-a=tI1
-i12
-tI
-1)tD1){iT1&exp_param=tI
-1)iK2
-eD2
-exp_param
-x41;if(cZ1,nU2)){lD1
-nE2
-c52
-lX1
-c43
-yN1
-iP1
-exponent<xH1&&t42
-exponent)nQ
-iV;iV
-iH
-cPow);iV
-cS
-tI
-0));iV.yA-exponent));iV
-iW1;nE2
-c52
-iV);lD1
-yN1}
-iP1
-powgroup
-i22!nF2.nX2){nF2=tI
-0);lD1
-yN1
-iP1
-powgroup
-nC==cQ3&&!cR1.nX2){cR1=powgroup;lD1
-yN1}
-if(!nE2
-eU3){changed=true
-tX
-cF1;cF1
-iH
-cMul);cF1
-iF1
-nE2);cF1
-iW1
-tX
-iG
-cMul);cA1
-SetParamsMove
-eM
-if(cA1
-IsImmed()&&fp_equal
-eH2
-x41
-nH2
-eL3
-cInv)tN
-cF1);}
-cJ3
-cA1
-GetDepth()>=cF1
-nP2
-tC2
-cDiv
-iG1
-tN
-cF1);}
-else{eL3
-cRDiv)tN
-cF1
-iG1;}
-}
-}
-if(nF2.nX2
-nQ
-iG
-l92;cA1
-SetParamsMove
-eM
-while(cA1
-RecreateInversionsAndNegations(prefer_base2))cA1
-tE3;eL3
-cQ3)tN
-nF2
-iG1;yS1}
-if(cR1.nX2
-nQ
-iG
-cMul);mulgroup
-c91
-cR1
-l8
-1));cA1
-AddParamsMove
-eM
-while(cA1
-RecreateInversionsAndNegations(prefer_base2))cA1
-tE3;DelParams();eL3
-cQ3)tN
-cR1
-l8
-0)iG1;yS1
-e21
-cAdd:{eK
-i32
-e73
-l91
-a-->0;)if(eY3
-cMul){nG2
-y41:tX&mulgroup=cT2
-for
-iZ1
-b=cA1
-l91
-b-->0;){if
-eH2
-l8
-b).lV1
-xT2=mulgroup
-l8
-b)x41;lG3
-xT2
-xU
-y41;}
-cA1
-lD1
-cA1
-i91
-b
-tA2
-iP1
-lJ3
-xT2,e62-2)))eN
-y41;}
-cA1
-lD1
-cA1
-i91
-b);cA1
-yA
-e62
-2))tA2}
-}
-if(t0){cA1
-tB
-mulgroup);yN1}
-iP1
-eY3
-cDiv&&!IsIntType
-xF::nS3){nG2
-y51:tX&cF1=cT2
-if(cF1
-l8
-0)tD1){lG3
-cF1
-l8
-0)x41
-xU
-y51;}
-cF1.lD1
-cF1.i91
-0);cF1
-iH
-cInv
-tA2}
-if(t0)eN
-y51;}
-cF1.tB
-cF1);yN1}
-iP1
-eY3
-cRDiv&&!IsIntType
-xF::nS3){nG2
-xD1:tX&cF1=cT2
-if(cF1
-l8
-1)tD1){lG3
-cF1
-l8
-i8
-xU
-xD1;}
-cF1.lD1
-cF1.i91
-1);cF1
-iH
-cInv
-tA2}
-if(t0)eN
-xD1;}
-cF1.tB
-cF1);yN1}
-if(!i32
-eU3){
-#ifdef DEBUG_SUBSTITUTIONS
-i02"Will make a Sub conversion in:\n"
-);fflush(stdout);l21
-#endif
-yZ2
-yT2;yT2
-iH
-cAdd);yT2
-iF1
-i32);yT2
-iW1
-tX
-cS1;cS1
-iH
-cAdd);cS1
-iF1
-lJ2));cS1
-iW1;if(cS1
-tD1&&lJ3
-cS1
-x41,xG1
-tC2
-cNeg);eC);}
-cJ3
-cS1
-nP2==1
-tC2
-cRSub);eC)eV3}
-iP1
-yT2
-nC==cAdd
-tC2
-cSub)eV3
-eC
-l8
-0)iY1
-1;a<yT2.l91++a
-nQ
-eV2;eV2
-iH
-cSub);eV2
-iF1
-lJ2));eV2.yC2)tN
-eV2);eC
-n93}
-}
-else{eL3
-cSub)eV3
-eC);}
-}
-#ifdef DEBUG_SUBSTITUTIONS
-i02"After Sub conversion:\n"
-);fflush(stdout);l21
-#endif
-e21
-cPow:{iT1&p0
-i42
-0);iT1&p1
-i42
-1);if(p1
-tD1){if(p1
-x41!=xH1&&!t42
-p1
-x41)){eG
-yS2
-r=eG
-CreatePowiResult(fp_abs
-cR3);if(r.n01!=0){bool
-lH2
-eW3
-if(p1
-x41<xH1&&r.tT1
-0]==0&&r
-e52>0){lH2=true;}
-#ifdef DEBUG_POWI
-i02"Will resolve powi %Lg as powi(chain(%d,%d),%ld)"
-cX2
-fp_abs
-cR3,r
-e52,r.n_int_cbrt,r.n01);for
-lT1
-n=0;n<eG
-MaxSep;++n){if(r
-i52==0)break;int
-n_sqrt=r
-i52%eG
-i13;int
-n_cbrt=r
-i52/eG
-i13;i02"*chain(%d,%d)"
-,n_sqrt,n_cbrt);}
-i02"\n"
-);
-#endif
-yZ2
-cU2
-i42
-0)tX
-yU2=cU2;yU2.lD1
-ChangeIntoRootChain(yU2,lH2,r
-e52,r.n_int_cbrt);yU2
-iW1
-tX
-pow;if(r.n01!=1){pow
-iH
-cPow);pow
-c91
-yU2);pow.yA
-e62
-r.n01)));}
-else
-pow.swap(yU2)tX
-mul;mul
-iH
-cMul);mul
-c91
-pow);for
-lT1
-n=0;n<eG
-MaxSep;++n){if(r
-i52==0)break;int
-n_sqrt=r
-i52%eG
-i13;int
-n_cbrt=r
-i52/eG
-i13
-tX
-eW2=cU2;eW2.lD1
-ChangeIntoRootChain(eW2,false,n_sqrt,n_cbrt);eW2
-iW1;mul
-c91
-eW2);}
-if(p1
-x41<xH1&&!lH2){mul
-iW1;eL3
-cInv);nB1
-0,mul);i91
-1);}
-else{eL3
-cMul);SetParamsMove(mul.lJ2));}
-#ifdef DEBUG_POWI
-l21
-#endif
-yS1
-xY3}
-}
-if(GetOpcode()==cPow&&(!p1
-tD1||!isLongInteger
-cR3||!IsOptimizableUsingPowi
-xF(makeLongInteger
-cR3))){if(p0
-tD1&&p0
-x41>e62
-0.0)){if(prefer_base2)l14
-yV2=fp_log2(p0
-x41);lG3
-yV2
-nH2
-i91
-0);}
-else{n0
-eA1
-yV2))eX3
-cS
-p1
-t81
-nB1
-t1}
-eL3
-cExp2);yS1}
-else
-l14
-yV2=fp_log(p0
-x41);lG3
-yV2
-nH2
-i91
-0);}
-else{n0
-eA1
-yV2))eX3
-cS
-p1
-t81
-nB1
-t1}
-eL3
-cExp);yS1}
-}
-iP1
-GetPositivityInfo(p0)==iF2){if(prefer_base2
-nQ
-log;log
-iH
-cLog2);log
-cS
-p0);log
-iW1;n0
-p1)eX3
-c91
-log
-t81
-eL3
-cExp2);nB1
-t1
-yS1}
-else{yZ2
-log;log
-iH
-cLog);log
-cS
-p0);log
-iW1;n0
-p1)eX3
-c91
-log
-t81
-eL3
-cExp);nB1
-t1
-yS1}
-}
-e21
-cDiv:{if(GetParam(0)tD1&&lJ3
-GetParam(0)x41
-nH2
-eL3
-cInv);i91
-0);}
-xY3
-yF3
-xY3
-if(changed)goto
-exit_changed
-i1
-changed;}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-using
-l33
-FUNCTIONPARSERTYPES;l33{using
-t5;class
-eF3{size_t
-nL1;size_t
-eH;size_t
-eI;size_t
-lO1;size_t
-t3;size_t
-t4;size_t
-n71;e43
-eF3():nL1(0),eH(0),eI(0),lO1(0),t3(0),t4(0),n71(0){}
-void
-i43
-OPCODE
-op){nL1+=1
-i33
-cCos)++eH
-i33
-cSin)++eI
-i33
-cSec)++eH
-i33
-cCsc)++eI
-i33
-cTan)++lO1
-i33
-cCot)++lO1
-i33
-cSinh)++t4
-i33
-cCosh)++t3
-i33
-cTanh)++n71;}
-size_t
-GetCSEscore()const{size_t
-nS3=nL1
-i1
-nS3;}
-int
-NeedsSinCos()const{bool
-y61=(nL1==(eH+eI+lO1));if((lO1&&(eI||eH))||(eI&&eH)){if(y61)return
-1
-i1
-2;eE3
-0;}
-int
-NeedsSinhCosh()const{bool
-y61=(nL1==(t3+t4+n71));if((n71&&(t4||t3))||(t4&&t3)){if(y61)return
-1
-i1
-2;eE3
-0;}
-size_t
-MinimumDepth()const{size_t
-n_sincos=std::min(eH,eI);size_t
-n_sinhcosh=std::min(t3,t4);if(n_sincos==0&&n_sinhcosh==0)return
-2
-i1
-1;}
-}
-yO1
-class
-TreeCountType:public
-std::multimap<fphash_t,std::pair<eF3,yZ2> >{}
-;xL1
-FindTreeCounts(tJ1&nI2,const
-nP1
-OPCODE
-xF2,bool
-skip_root=false){cX
-i=nI2.xU2
-nJ2);if(!skip_root){bool
-found
-eW3
-for(;i!=nI2.cX1
-nJ2;++i){if(tree
-xI
-i
-eC2.second)){i
-eC2.first.i43
-xF2);found=true;xY3}
-if(!found){eF3
-count;count.i43
-xF2);nI2.y43,std::make_pair(nJ2,std::make_pair
-cW3
-cU3)));}
-}
-x51
-FindTreeCounts(nI2,xW
-a),t72);}
-e72
-yW{bool
-BalanceGood;bool
-FoundChild;}
-yO1
-yW
-lP1
-iT1&root,iT1&cS3{if(root
-xI
-cS3){yW
-nS3={true,true}
-i1
-nS3;}
-yW
-nS3={true,false}
-;if(root
-nC==cIf||root
-nC==t03{yW
-cond=lP1
-root
-l8
-0),cS3;yW
-xV=lP1
-root
-l8
-1),cS3;yW
-y4=lP1
-root
-l8
-2),cS3;if
-l23||xV
-yX||y4
-yX){nS3
-yX=true;}
-nS3
-eD=((xV
-yX==y4
-yX)||l23
-i62)&&(cond
-eD||(xV
-yX&&y4
-yX))&&(xV
-eD||l23
-i62)&&(y4
-eD||l23
-i62);}
-else{bool
-iH1
-eW3
-bool
-nM1=false
-eK3
-b=root.GetParamCount(),a=0;a<b;++a){yW
-tmp=lP1
-root
-l8
-a),cS3;if(tmp
-yX)nS3
-yX=true;if(tmp
-eD==false)iH1=true;iP1
-tmp
-yX)nM1=true;}
-if(iH1&&!nM1)nS3
-eD
-eW3
-eE3
-nS3;}
-yP1
-cW2
-iR1
-i53
-const
-nP1
-const
-xK1::eP3&synth,const
-tJ1&nI2){for
-iZ1
-b=tree.GetParamCount(),a=0;a<b;++a){iT1&leaf=xW
-a);cX
-synth_it;for(x93
-tJ1::const_iterator
-i=nI2.y73
-i!=nI2.end();++i){if(i->first!=leaf.GetHash())yA1
-const
-eF3&occ
-nY2
-first;size_t
-score=occ.GetCSEscore();iT1&candidate
-nY2
-i63
-if(lF2
-candidate))yA1
-if(leaf
-nP2<occ.MinimumDepth())yA1
-if(score<2)yA1
-if(lP1
-i53
-leaf)eD==false)continue
-l43
-if(cW2(i53
-leaf,synth,nI2))lD2
-eE3
-t23
-yP1
-iI1
-iT1&y53,iT1&expr){yY1
-y53
-lF3
-expr))lD2
-yY1
-iI1
-y53
-l8
-a),expr
-y03
-true
-i1
-t23
-yP1
-GoodMomentForCSE
-iR1
-y53,iT1&expr){if(y53
-nC==cIf)lD2
-yY1
-y53
-lF3
-expr))lD2
-size_t
-i72=0;yY1
-iI1
-y53
-l8
-a),expr))++i72
-i1
-i72!=1;}
-}
-t5{tK1
-size_t
-yZ2::SynthCommonSubExpressions(xK1::xI1
-const{if(e91
-0)return
-0;size_t
-stacktop_before=synth.GetStackTop();tJ1
-nI2;FindTreeCounts(nI2,*this,GetOpcode(),true);for(;;){size_t
-yW2=0;
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"Finding a CSE candidate, root is:"
-<<std::y11*this);
-#endif
-cX
-cs_it(nI2.end());for(cX
-j=nI2.y73
-j!=nI2.end();){cX
-i(j++);const
-eF3&occ
-nY2
-first;size_t
-score=occ.GetCSEscore();iT1&tree
-nY2
-i63
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"Score "
-<<score<<":\n"
-<<std::flush;DumpTreeWithIndent(tree);
-#endif
-if(lF2
-tree))xZ
-if(tree
-nP2<occ.MinimumDepth())xZ
-if(score<2)xZ
-if(lP1*this
-cU3)eD==false)xZ
-if(cW2(*this
-cU3,synth,nI2)){yA1}
-if(!GoodMomentForCSE(*this
-cU3))xZ
-score*=tree
-nP2;if(score>yW2){yW2=score;cs_it=i;}
-}
-if(yW2<=0){
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<"No more CSE candidates.\n"
-<<std::flush;
-#endif
-xY3
-iT1&tree=cs_it
-eC2.i63
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-cV2<<iX3"Common Subexpression:"
-;DumpTree
-xF(tree
-lE2
-std::endl;
-#endif
-#if 0
-int
-n11=occ.NeedsSinCos();int
-i9=occ.NeedsSinhCosh()tX
-i82,i92,yX2,yY2;if(n11){i82
-eX2
-i82
-iH
-cSin);i82
-iW1;i92
-eX2
-i92
-iH
-cCos);i92
-iW1;if(lF2
-i82)||lF2
-i92))i73==2){nI2.xG2
-yA1}
-n11=0;}
-}
-if(i9){yX2
-eX2
-yX2
-iH
-cSinh);yX2
-iW1;yY2
-eX2
-yY2
-iH
-cCosh);yY2
-iW1;if(lF2
-yX2)||lF2
-yY2)){if(i9==2){nI2.xG2
-yA1}
-i9=0;}
-}
-#endif
-tree.SynthesizeByteCode(synth,false);nI2.xG2
-#ifdef DEBUG_SUBSTITUTIONS_CSE
-synth.x73
-Dump<0>(lE2"Done with Common Subexpression:"
-;DumpTree
-xF(tree
-lE2
-std::endl;
-#endif
-#if 0
-if(n11)i73==2||i9){synth.eL1}
-yB1
-cSinCos,1,2)yC1
-i82,1)yC1
-i92,0);}
-if(i9)i73)synth.eL1
-if(i9==2){synth.eL1}
-yB1
-cSinhCosh,1,2)yC1
-yX2,1)yC1
-yY2,0);}
-#endif
-eE3
-xV3
-stacktop_before;}
-}
-#endif
-#ifdef FP_SUPPORT_OPTIMIZER
-tK1
-lU1
-xF::iA2{using
-t5;CopyOnWrite()tX
-tree;tree.GenerateFrom(*mData);FPoptimizer_Optimize::ApplyGrammars(tree);eO3
-x83>cT3;std
-xM3
-xF
-immed;size_t
-stacktop_max=0;tree.SynthesizeByteCode(cT3,immed,stacktop_max);if(mData->mStackSize!=stacktop_max){mData->mStackSize=x83(stacktop_max);
-#if !defined(FP_USE_THREAD_SAFE_EVAL) && \
- !defined(FP_USE_THREAD_SAFE_EVAL_WITH_ALLOCA)
-mData->mStack
-xF3
-stacktop_max);
-#endif
-}
-mData->mByteCode.swap(cT3);mData->mImmed.swap(immed);}
-#define FUNCTIONPARSER_INSTANTIATE_EMPTY_OPTIMIZE(type) tP1>lU1<type>::iA2{}
-#ifdef FP_SUPPORT_MPFR_FLOAT_TYPE
-i93(MpfrFloat)
-#endif
-#ifdef FP_SUPPORT_GMP_INT_TYPE
-i93(GmpInt)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_DOUBLE_TYPE
-i93(std::complex<double>)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_FLOAT_TYPE
-i93(std::complex<float>)
-#endif
-#ifdef FP_SUPPORT_COMPLEX_LONG_DOUBLE_TYPE
-i93(std::complex<long
-double>)
-#endif
-#define FUNCTIONPARSER_INSTANTIATE_OPTIMIZE(type) x73 lU1<type>::iA2;
-#ifndef FP_DISABLE_DOUBLE_TYPE
-iA3(double)
-#endif
-#ifdef FP_SUPPORT_FLOAT_TYPE
-iA3(float)
-#endif
-#ifdef FP_SUPPORT_LONG_DOUBLE_TYPE
-iA3(long
-double)
-#endif
-#ifdef FP_SUPPORT_LONG_INT_TYPE
-iA3(long)
-#endif
-#endif // FP_SUPPORT_OPTIMIZER
-
-#endif
+++ /dev/null
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+++ /dev/null
-#include "GmpInt.hh"
-#include <gmp.h>
-#include <deque>
-#include <vector>
-#include <cstring>
-#include <cctype>
-
-//===========================================================================
-// Shared data
-//===========================================================================
-namespace
-{
- unsigned long gIntDefaultNumberOfBits = 256;
-
- std::vector<char>& intString()
- {
- static std::vector<char> str;
- return str;
- }
-}
-
-//===========================================================================
-// Auxiliary structs
-//===========================================================================
-struct GmpInt::GmpIntData
-{
- unsigned mRefCount;
- GmpIntData* nextFreeNode;
- mpz_t mInteger;
-
- GmpIntData(): mRefCount(1), nextFreeNode(0) {}
-};
-
-class GmpInt::GmpIntDataContainer
-{
- std::deque<GmpInt::GmpIntData> mData;
- GmpInt::GmpIntData* mFirstFreeNode;
- GmpInt::GmpIntData* mConst_0;
-
- public:
- GmpIntDataContainer(): mFirstFreeNode(0), mConst_0(0) {}
-
- ~GmpIntDataContainer()
- {
- for(size_t i = 0; i < mData.size(); ++i)
- mpz_clear(mData[i].mInteger);
- }
-
- GmpInt::GmpIntData* allocateGmpIntData(unsigned long numberOfBits,
- bool initToZero)
- {
- if(mFirstFreeNode)
- {
- GmpInt::GmpIntData* node = mFirstFreeNode;
- mFirstFreeNode = node->nextFreeNode;
- if(initToZero) mpz_set_si(node->mInteger, 0);
- ++(node->mRefCount);
- return node;
- }
-
- mData.push_back(GmpInt::GmpIntData());
- if(numberOfBits > 0)
- mpz_init2(mData.back().mInteger, numberOfBits);
- else
- mpz_init(mData.back().mInteger);
- return &mData.back();
- }
-
- void releaseGmpIntData(GmpIntData* data)
- {
- if(--(data->mRefCount) == 0)
- {
- data->nextFreeNode = mFirstFreeNode;
- mFirstFreeNode = data;
- }
- }
-
- GmpInt::GmpIntData* const_0()
- {
- if(!mConst_0)
- mConst_0 = allocateGmpIntData(gIntDefaultNumberOfBits, true);
- return mConst_0;
- }
-};
-
-
-GmpInt::GmpIntDataContainer& GmpInt::gmpIntDataContainer()
-{
- static GmpIntDataContainer container;
- return container;
-}
-
-//===========================================================================
-// Auxiliary functions
-//===========================================================================
-void GmpInt::setDefaultNumberOfBits(unsigned long value)
-{
- gIntDefaultNumberOfBits = value;
-}
-
-unsigned long GmpInt::getDefaultNumberOfBits()
-{
- return gIntDefaultNumberOfBits;
-}
-
-inline void GmpInt::copyIfShared()
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- GmpIntData* oldData = mData;
- mData = gmpIntDataContainer().allocateGmpIntData(0, false);
- mpz_set(mData->mInteger, oldData->mInteger);
- }
-}
-
-
-//===========================================================================
-// Constructors, destructor, assignment
-//===========================================================================
-GmpInt::GmpInt(DummyType):
- mData(gmpIntDataContainer().allocateGmpIntData(0, false))
-{}
-
-GmpInt::GmpInt()
-{
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
-}
-
-GmpInt::GmpInt(long value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_si(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(unsigned long value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_ui(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(int value)
-{
- if(value == 0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_si(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(double value)
-{
- const double absValue = value >= 0.0 ? value : -value;
- if(absValue < 1.0)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_d(mData->mInteger, value);
- }
-}
-
-GmpInt::GmpInt(long double value)
-{
- const long double absValue = value >= 0.0L ? value : -value;
- if(absValue < 1.0L)
- {
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- mpz_set_d(mData->mInteger, double(value));
- }
-}
-
-GmpInt::GmpInt(const GmpInt& rhs):
- mData(rhs.mData)
-{
- ++(mData->mRefCount);
-}
-
-GmpInt& GmpInt::operator=(const GmpInt& rhs)
-{
- if(mData != rhs.mData)
- {
- gmpIntDataContainer().releaseGmpIntData(mData);
- mData = rhs.mData;
- ++(mData->mRefCount);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator=(signed long value)
-{
- if(value == 0)
- {
- gmpIntDataContainer().releaseGmpIntData(mData);
- mData = gmpIntDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = gmpIntDataContainer().allocateGmpIntData
- (gIntDefaultNumberOfBits, false);
- }
- mpz_set_si(mData->mInteger, value);
- }
- return *this;
-}
-
-GmpInt::~GmpInt()
-{
- gmpIntDataContainer().releaseGmpIntData(mData);
-}
-
-
-//===========================================================================
-// Data getters
-//===========================================================================
-template<>
-void GmpInt::get_raw_mpfr_data<mpz_t>(mpz_t& dest_mpz_t)
-{
- std::memcpy(&dest_mpz_t, mData->mInteger, sizeof(mpz_t));
-}
-
-const char* GmpInt::getAsString(int base) const
-{
- intString().resize(mpz_sizeinbase(mData->mInteger, base) + 2);
- return mpz_get_str(&intString()[0], base, mData->mInteger);
-}
-
-long GmpInt::toInt() const
-{
- return mpz_get_si(mData->mInteger);
-}
-
-
-//===========================================================================
-// Modifying operators
-//===========================================================================
-GmpInt& GmpInt::operator+=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_add(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator+=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_add_ui(mData->mInteger, mData->mInteger, value);
- else
- mpz_sub_ui(mData->mInteger, mData->mInteger, -value);
- return *this;
-}
-
-GmpInt& GmpInt::operator-=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_sub(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator-=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_sub_ui(mData->mInteger, mData->mInteger, value);
- else
- mpz_add_ui(mData->mInteger, mData->mInteger, -value);
- return *this;
-}
-
-GmpInt& GmpInt::operator*=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_mul(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator*=(long value)
-{
- copyIfShared();
- mpz_mul_si(mData->mInteger, mData->mInteger, value);
- return *this;
-}
-
-GmpInt& GmpInt::operator/=(const GmpInt& rhs)
-{
- copyIfShared();
- mpz_tdiv_q(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return *this;
-}
-
-GmpInt& GmpInt::operator/=(long value)
-{
- copyIfShared();
- if(value >= 0)
- mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, value);
- else
- {
- mpz_neg(mData->mInteger, mData->mInteger);
- mpz_tdiv_q_ui(mData->mInteger, mData->mInteger, -value);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator%=(const GmpInt& rhs)
-{
- copyIfShared();
- if(operator<(0))
- {
- negate();
- mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- negate();
- }
- else
- {
- mpz_mod(mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator%=(long value)
-{
- copyIfShared();
- if(value < 0) value = -value;
- if(operator<(0))
- {
- negate();
- mpz_mod_ui(mData->mInteger, mData->mInteger, value);
- negate();
- }
- else
- {
- mpz_mod_ui(mData->mInteger, mData->mInteger, value);
- }
- return *this;
-}
-
-GmpInt& GmpInt::operator<<=(unsigned long bits)
-{
- copyIfShared();
- mpz_mul_2exp(mData->mInteger, mData->mInteger, bits);
- return *this;
-}
-
-GmpInt& GmpInt::operator>>=(unsigned long bits)
-{
- copyIfShared();
- mpz_tdiv_q_2exp(mData->mInteger, mData->mInteger, bits);
- return *this;
-}
-
-
-//===========================================================================
-// Modifying functions
-//===========================================================================
-void GmpInt::addProduct(const GmpInt& value1, const GmpInt& value2)
-{
- copyIfShared();
- mpz_addmul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
-}
-
-void GmpInt::addProduct(const GmpInt& value1, unsigned long value2)
-{
- copyIfShared();
- mpz_addmul_ui(mData->mInteger, value1.mData->mInteger, value2);
-}
-
-void GmpInt::subProduct(const GmpInt& value1, const GmpInt& value2)
-{
- copyIfShared();
- mpz_submul(mData->mInteger, value1.mData->mInteger, value2.mData->mInteger);
-}
-
-void GmpInt::subProduct(const GmpInt& value1, unsigned long value2)
-{
- copyIfShared();
- mpz_submul_ui(mData->mInteger, value1.mData->mInteger, value2);
-}
-
-void GmpInt::negate()
-{
- copyIfShared();
- mpz_neg(mData->mInteger, mData->mInteger);
-}
-
-void GmpInt::abs()
-{
- copyIfShared();
- mpz_abs(mData->mInteger, mData->mInteger);
-}
-
-GmpInt GmpInt::abs(const GmpInt& value)
-{
- GmpInt retval(kNoInitialization);
- mpz_abs(retval.mData->mInteger, value.mData->mInteger);
- return retval;
-}
-
-
-//===========================================================================
-// Non-modifying operators
-//===========================================================================
-GmpInt GmpInt::operator+(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_add(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator+(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_add_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- mpz_sub_ui(retval.mData->mInteger, mData->mInteger, -value);
- return retval;
-}
-
-GmpInt GmpInt::operator-(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_sub(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator-(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_sub_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- mpz_add_ui(retval.mData->mInteger, mData->mInteger, -value);
- return retval;
-}
-
-GmpInt GmpInt::operator*(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator*(long value) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul_si(retval.mData->mInteger, mData->mInteger, value);
- return retval;
-}
-
-GmpInt GmpInt::operator/(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- mpz_tdiv_q(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator/(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value >= 0)
- mpz_tdiv_q_ui(retval.mData->mInteger, mData->mInteger, value);
- else
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_tdiv_q_ui(retval.mData->mInteger, retval.mData->mInteger, -value);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator%(const GmpInt& rhs) const
-{
- GmpInt retval(kNoInitialization);
- if(operator<(0))
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_mod(retval.mData->mInteger,
- retval.mData->mInteger, rhs.mData->mInteger);
- retval.negate();
- }
- else
- {
- mpz_mod(retval.mData->mInteger, mData->mInteger, rhs.mData->mInteger);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator%(long value) const
-{
- GmpInt retval(kNoInitialization);
- if(value < 0) value = -value;
- if(operator<(0))
- {
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- mpz_mod_ui(retval.mData->mInteger, retval.mData->mInteger, value);
- retval.negate();
- }
- else
- {
- mpz_mod_ui(retval.mData->mInteger, mData->mInteger, value);
- }
- return retval;
-}
-
-GmpInt GmpInt::operator-() const
-{
- GmpInt retval(kNoInitialization);
- mpz_neg(retval.mData->mInteger, mData->mInteger);
- return retval;
-}
-
-GmpInt GmpInt::operator<<(unsigned long bits) const
-{
- GmpInt retval(kNoInitialization);
- mpz_mul_2exp(retval.mData->mInteger, mData->mInteger, bits);
- return retval;
-}
-
-GmpInt GmpInt::operator>>(unsigned long bits) const
-{
- GmpInt retval(kNoInitialization);
- mpz_tdiv_q_2exp(retval.mData->mInteger, mData->mInteger, bits);
- return retval;
-}
-
-
-//===========================================================================
-// Comparison operators
-//===========================================================================
-bool GmpInt::operator<(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) < 0;
-}
-
-bool GmpInt::operator<(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) < 0;
-}
-
-bool GmpInt::operator<=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) <= 0;
-}
-
-bool GmpInt::operator<=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) <= 0;
-}
-
-bool GmpInt::operator>(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) > 0;
-}
-
-bool GmpInt::operator>(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) > 0;
-}
-
-bool GmpInt::operator>=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) >= 0;
-}
-
-bool GmpInt::operator>=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) >= 0;
-}
-
-bool GmpInt::operator==(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) == 0;
-}
-
-bool GmpInt::operator==(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) == 0;
-}
-
-bool GmpInt::operator!=(const GmpInt& rhs) const
-{
- return mpz_cmp(mData->mInteger, rhs.mData->mInteger) != 0;
-}
-
-bool GmpInt::operator!=(long value) const
-{
- return mpz_cmp_si(mData->mInteger, value) != 0;
-}
-
-void GmpInt::parseValue(const char* value)
-{
- mpz_set_str(mData->mInteger, value, 10);
-}
-
-void GmpInt::parseValue(const char* value, char** endptr)
-{
- static std::vector<char> str;
-
- unsigned startIndex = 0;
- while(value[startIndex] && std::isspace(value[startIndex])) ++startIndex;
- if(!value[startIndex]) { *endptr = const_cast<char*>(value); return; }
-
- unsigned endIndex = startIndex;
- if(value[endIndex] == '-') ++endIndex;
- if(!std::isdigit(value[endIndex]))
- { *endptr = const_cast<char*>(value); return; }
- if(value[endIndex] == '0' && value[endIndex+1] == 'x')
- {
- endIndex += 1;
- while(std::isxdigit(value[++endIndex])) {}
- }
- else
- {
- while(std::isdigit(value[++endIndex])) {}
- }
-
- str.reserve(endIndex - startIndex + 1);
- str.assign(value + startIndex, value + endIndex);
- str.push_back(0);
-
- mpz_set_str(mData->mInteger, &str[0], 0);
- *endptr = const_cast<char*>(value + endIndex);
-}
-
-GmpInt GmpInt::parseString(const char* str, char** endptr)
-{
- GmpInt retval(kNoInitialization);
- retval.parseValue(str, endptr);
- return retval;
-}
-
-//===========================================================================
-// Operator functions
-//===========================================================================
-GmpInt operator+(long lhs, const GmpInt& rhs)
-{
- GmpInt retval(GmpInt::kNoInitialization);
- if(lhs >= 0)
- mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, lhs);
- else
- mpz_sub_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
- return retval;
-}
-
-GmpInt operator-(long lhs, const GmpInt& rhs)
-{
- GmpInt retval(GmpInt::kNoInitialization);
- if(lhs >= 0)
- mpz_ui_sub(retval.mData->mInteger, lhs, rhs.mData->mInteger);
- else
- {
- mpz_add_ui(retval.mData->mInteger, rhs.mData->mInteger, -lhs);
- mpz_neg(retval.mData->mInteger, retval.mData->mInteger);
- }
- return retval;
-}
-
-GmpInt operator*(long lhs, const GmpInt& rhs)
-{
- return rhs * lhs;
-}
-
-GmpInt operator/(long lhs, const GmpInt& rhs)
-{
- return GmpInt(lhs) / rhs;
-}
-
-GmpInt operator%(long lhs, const GmpInt& rhs)
-{
- return GmpInt(lhs) % rhs;
-}
+++ /dev/null
-#ifndef ONCE_FP_GMP_INT_HH_
-#define ONCE_FP_GMP_INT_HH_
-
-#include <iostream>
-
-class GmpInt
-{
- public:
- /* A default of 256 bits will be used for all newly-instantiated GmpInt
- objects. This default can be changed with the function below.
- */
- static void setDefaultNumberOfBits(unsigned long);
- static unsigned long getDefaultNumberOfBits();
-
- GmpInt();
- GmpInt(long value);
- GmpInt(unsigned long value);
- GmpInt(int value);
- GmpInt(double value);
- GmpInt(long double value);
-
- GmpInt(const GmpInt&);
- GmpInt& operator=(const GmpInt&);
- GmpInt& operator=(signed long value);
-
- ~GmpInt();
-
-
- /* This function can be used to retrieve the raw mpz_t data structure
- used by this object. (The template trick is used to avoid a dependency
- of this header file with <gmp.h>.)
- In other words, it can be called like:
-
- mpz_t raw_mpz_data;
- intValue.get_raw_mpz_data(raw_mpz_data);
-
- Note that the returned mpz_t should be considered as read-only and
- not be modified from the outside because it may be shared among
- several objects. If the calling code needs to modify the data, it
- should copy it for itself first with the appropriate GMP library
- functions.
- */
- template<typename Mpz_t>
- void get_raw_mpfr_data(Mpz_t& dest_mpz_t);
-
-
- // Note that the returned char* points to an internal (shared) buffer
- // which will be valid until the next time this function is called
- // (by any object).
- const char* getAsString(int base = 10) const;
- long toInt() const;
-
- GmpInt& operator+=(const GmpInt&);
- GmpInt& operator+=(long);
- GmpInt& operator-=(const GmpInt&);
- GmpInt& operator-=(long);
- GmpInt& operator*=(const GmpInt&);
- GmpInt& operator*=(long);
- GmpInt& operator/=(const GmpInt&);
- GmpInt& operator/=(long);
- GmpInt& operator%=(const GmpInt&);
- GmpInt& operator%=(long);
-
- GmpInt& operator<<=(unsigned long);
- GmpInt& operator>>=(unsigned long);
-
- // Equivalent to "+= value1 * value2;"
- void addProduct(const GmpInt& value1, const GmpInt& value2);
- void addProduct(const GmpInt& value1, unsigned long value2);
-
- // Equivalent to "-= value1 * value2;"
- void subProduct(const GmpInt& value1, const GmpInt& value2);
- void subProduct(const GmpInt& value1, unsigned long value2);
-
- void negate();
- void abs();
- static GmpInt abs(const GmpInt&);
-
- GmpInt operator+(const GmpInt&) const;
- GmpInt operator+(long) const;
- GmpInt operator-(const GmpInt&) const;
- GmpInt operator-(long) const;
- GmpInt operator*(const GmpInt&) const;
- GmpInt operator*(long) const;
- GmpInt operator/(const GmpInt&) const;
- GmpInt operator/(long) const;
- GmpInt operator%(const GmpInt&) const;
- GmpInt operator%(long) const;
-
- GmpInt operator-() const;
-
- GmpInt operator<<(unsigned long) const;
- GmpInt operator>>(unsigned long) const;
-
- bool operator<(const GmpInt&) const;
- bool operator<(long) const;
- bool operator<=(const GmpInt&) const;
- bool operator<=(long) const;
- bool operator>(const GmpInt&) const;
- bool operator>(long) const;
- bool operator>=(const GmpInt&) const;
- bool operator>=(long) const;
- bool operator==(const GmpInt&) const;
- bool operator==(long) const;
- bool operator!=(const GmpInt&) const;
- bool operator!=(long) const;
-
- void parseValue(const char* value);
- void parseValue(const char* value, char** endptr);
- static GmpInt parseString(const char* str, char** endptr);
-
-
- private:
- struct GmpIntData;
- class GmpIntDataContainer;
-
- GmpIntData* mData;
-
- enum DummyType { kNoInitialization };
- GmpInt(DummyType);
-
- void copyIfShared();
- static GmpIntDataContainer& gmpIntDataContainer();
-
- friend GmpInt operator+(long lhs, const GmpInt& rhs);
- friend GmpInt operator-(long lhs, const GmpInt& rhs);
-};
-
-GmpInt operator+(long lhs, const GmpInt& rhs);
-GmpInt operator-(long lhs, const GmpInt& rhs);
-GmpInt operator*(long lhs, const GmpInt& rhs);
-GmpInt operator/(long lhs, const GmpInt& rhs);
-GmpInt operator%(long lhs, const GmpInt& rhs);
-
-inline bool operator<(long lhs, const GmpInt& rhs) { return rhs > lhs; }
-inline bool operator<=(long lhs, const GmpInt& rhs) { return rhs >= lhs; }
-inline bool operator>(long lhs, const GmpInt& rhs) { return rhs < lhs; }
-inline bool operator>=(long lhs, const GmpInt& rhs) { return rhs <= lhs; }
-inline bool operator==(long lhs, const GmpInt& rhs) { return rhs == lhs; }
-inline bool operator!=(long lhs, const GmpInt& rhs) { return rhs != lhs; }
-
-inline std::ostream& operator<<(std::ostream& os, const GmpInt& value)
-{
- os << value.getAsString();
- return os;
-}
-
-#endif
+++ /dev/null
-#include "MpfrFloat.hh"
-#include <stdio.h>
-#include <mpfr.h>
-#include <deque>
-#include <vector>
-#include <cstring>
-#include <cassert>
-
-//===========================================================================
-// Auxiliary structs
-//===========================================================================
-struct MpfrFloat::MpfrFloatData
-{
- unsigned mRefCount;
- MpfrFloatData* nextFreeNode;
- mpfr_t mFloat;
-
- MpfrFloatData(): mRefCount(1), nextFreeNode(0) {}
-};
-
-class MpfrFloat::MpfrFloatDataContainer
-{
- unsigned long mDefaultPrecision;
- std::deque<MpfrFloatData> mData;
- MpfrFloatData* mFirstFreeNode;
-
- MpfrFloatData
- *mConst_0, *mConst_pi, *mConst_e, *mConst_log2, *mConst_epsilon;
-
- void recalculateEpsilon()
- {
- mpfr_set_si(mConst_epsilon->mFloat, 1, GMP_RNDN);
- mpfr_div_2ui(mConst_epsilon->mFloat, mConst_epsilon->mFloat,
- mDefaultPrecision*7/8 - 1, GMP_RNDN);
- }
-
- public:
- MpfrFloatDataContainer():
- mDefaultPrecision(256), mFirstFreeNode(0), mConst_0(0),
- mConst_pi(0), mConst_e(0), mConst_log2(0), mConst_epsilon(0)
- {}
-
- ~MpfrFloatDataContainer()
- {
- for(size_t i = 0; i < mData.size(); ++i)
- mpfr_clear(mData[i].mFloat);
- }
-
- MpfrFloatData* allocateMpfrFloatData(bool initToZero)
- {
- if(mFirstFreeNode)
- {
- MpfrFloatData* node = mFirstFreeNode;
- mFirstFreeNode = node->nextFreeNode;
- if(initToZero) mpfr_set_si(node->mFloat, 0, GMP_RNDN);
- ++(node->mRefCount);
- return node;
- }
-
- mData.push_back(MpfrFloatData());
- mpfr_init2(mData.back().mFloat, mDefaultPrecision);
- if(initToZero) mpfr_set_si(mData.back().mFloat, 0, GMP_RNDN);
- return &mData.back();
- }
-
- void releaseMpfrFloatData(MpfrFloatData* data)
- {
- if(--(data->mRefCount) == 0)
- {
- data->nextFreeNode = mFirstFreeNode;
- mFirstFreeNode = data;
- }
- }
-
- void setDefaultPrecision(unsigned long bits)
- {
- if(bits != mDefaultPrecision)
- {
- mDefaultPrecision = bits;
- for(size_t i = 0; i < mData.size(); ++i)
- mpfr_prec_round(mData[i].mFloat, bits, GMP_RNDN);
-
- if(mConst_pi) mpfr_const_pi(mConst_pi->mFloat, GMP_RNDN);
- if(mConst_e)
- {
- mpfr_set_si(mConst_e->mFloat, 1, GMP_RNDN);
- mpfr_exp(mConst_e->mFloat, mConst_e->mFloat, GMP_RNDN);
- }
- if(mConst_log2) mpfr_const_log2(mConst_log2->mFloat, GMP_RNDN);
- if(mConst_epsilon) recalculateEpsilon();
- }
- }
-
- unsigned long getDefaultPrecision() const
- {
- return mDefaultPrecision;
- }
-
- MpfrFloatData* const_0()
- {
- if(!mConst_0) mConst_0 = allocateMpfrFloatData(true);
- return mConst_0;
- }
-
- MpfrFloat const_pi()
- {
- if(!mConst_pi)
- {
- mConst_pi = allocateMpfrFloatData(false);
- mpfr_const_pi(mConst_pi->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_pi);
- }
-
- MpfrFloat const_e()
- {
- if(!mConst_e)
- {
- mConst_e = allocateMpfrFloatData(false);
- mpfr_set_si(mConst_e->mFloat, 1, GMP_RNDN);
- mpfr_exp(mConst_e->mFloat, mConst_e->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_e);
- }
-
- MpfrFloat const_log2()
- {
- if(!mConst_log2)
- {
- mConst_log2 = allocateMpfrFloatData(false);
- mpfr_const_log2(mConst_log2->mFloat, GMP_RNDN);
- }
- return MpfrFloat(mConst_log2);
- }
-
- MpfrFloat const_epsilon()
- {
- if(!mConst_epsilon)
- {
- mConst_epsilon = allocateMpfrFloatData(false);
- recalculateEpsilon();
- }
- return MpfrFloat(mConst_epsilon);
- }
-};
-
-
-//===========================================================================
-// Shared data
-//===========================================================================
-// This should ensure that the container is not accessed by any MpfrFloat
-// instance before it has been constructed or after it has been destroyed
-// (which might otherwise happen if MpfrFloat is instantiated globally.)
-MpfrFloat::MpfrFloatDataContainer& MpfrFloat::mpfrFloatDataContainer()
-{
- static MpfrFloat::MpfrFloatDataContainer container;
- return container;
-}
-
-
-//===========================================================================
-// Auxiliary functions
-//===========================================================================
-void MpfrFloat::setDefaultMantissaBits(unsigned long bits)
-{
- mpfrFloatDataContainer().setDefaultPrecision(bits);
-}
-
-unsigned long MpfrFloat::getCurrentDefaultMantissaBits()
-{
- return mpfrFloatDataContainer().getDefaultPrecision();
-}
-
-inline void MpfrFloat::copyIfShared()
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- MpfrFloatData* oldData = mData;
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set(mData->mFloat, oldData->mFloat, GMP_RNDN);
- }
-}
-
-
-//===========================================================================
-// Constructors, destructor, assignment
-//===========================================================================
-MpfrFloat::MpfrFloat(DummyType):
- mData(mpfrFloatDataContainer().allocateMpfrFloatData(false))
-{}
-
-MpfrFloat::MpfrFloat(MpfrFloatData* data):
- mData(data)
-{
- assert(data != 0);
- ++(mData->mRefCount);
-}
-
-MpfrFloat::MpfrFloat():
- mData(mpfrFloatDataContainer().const_0())
-{
- ++(mData->mRefCount);
-}
-
-MpfrFloat::MpfrFloat(double value)
-{
- if(value == 0.0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_d(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(long double value)
-{
- if(value == 0.0L)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_ld(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(long value)
-{
- if(value == 0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(int value)
-{
- if(value == 0)
- {
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
-}
-
-MpfrFloat::MpfrFloat(const char* value, char** endptr):
- mData(mpfrFloatDataContainer().allocateMpfrFloatData(false))
-{
- mpfr_strtofr(mData->mFloat, value, endptr, 0, GMP_RNDN);
-}
-
-MpfrFloat::~MpfrFloat()
-{
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
-}
-
-MpfrFloat::MpfrFloat(const MpfrFloat& rhs):
- mData(rhs.mData)
-{
- ++(mData->mRefCount);
-}
-
-MpfrFloat& MpfrFloat::operator=(const MpfrFloat& rhs)
-{
- if(mData != rhs.mData)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = rhs.mData;
- ++(mData->mRefCount);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(double value)
-{
- if(value == 0.0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_d(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(long double value)
-{
- if(value == 0.0L)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_ld(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(long value)
-{
- if(value == 0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator=(int value)
-{
- if(value == 0)
- {
- mpfrFloatDataContainer().releaseMpfrFloatData(mData);
- mData = mpfrFloatDataContainer().const_0();
- ++(mData->mRefCount);
- }
- else
- {
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
- mpfr_set_si(mData->mFloat, value, GMP_RNDN);
- }
- return *this;
-}
-
-/*
-MpfrFloat& MpfrFloat::operator=(const char* value)
-{
- if(mData->mRefCount > 1)
- {
- --(mData->mRefCount);
- mData = mpfrFloatDataContainer().allocateMpfrFloatData(false);
- }
-
- mpfr_set_str(mData->mFloat, value, 10, GMP_RNDN);
- return *this;
-}
-*/
-
-void MpfrFloat::parseValue(const char* value)
-{
- copyIfShared();
- mpfr_set_str(mData->mFloat, value, 10, GMP_RNDN);
-}
-
-void MpfrFloat::parseValue(const char* value, char** endptr)
-{
- copyIfShared();
- mpfr_strtofr(mData->mFloat, value, endptr, 0, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Data getters
-//===========================================================================
-template<>
-void MpfrFloat::get_raw_mpfr_data<mpfr_t>(mpfr_t& dest_mpfr_t)
-{
- std::memcpy(&dest_mpfr_t, mData->mFloat, sizeof(mpfr_t));
-}
-
-const char* MpfrFloat::getAsString(unsigned precision) const
-{
-#if(MPFR_VERSION_MAJOR < 2 || (MPFR_VERSION_MAJOR == 2 && MPFR_VERSION_MINOR < 4))
- static const char* retval =
- "[mpfr_snprintf() is not supported in mpfr versions prior to 2.4]";
- return retval;
-#else
- static std::vector<char> str;
- str.resize(precision+30);
- mpfr_snprintf(&(str[0]), precision+30, "%.*RNg", precision, mData->mFloat);
- return &(str[0]);
-#endif
-}
-
-bool MpfrFloat::isInteger() const
-{
- return mpfr_integer_p(mData->mFloat) != 0;
-}
-
-long MpfrFloat::toInt() const
-{
- return mpfr_get_si(mData->mFloat, GMP_RNDN);
-}
-
-double MpfrFloat::toDouble() const
-{
- return mpfr_get_d(mData->mFloat, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Modifying operators
-//===========================================================================
-MpfrFloat& MpfrFloat::operator+=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_add(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator+=(double value)
-{
- copyIfShared();
- mpfr_add_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator-=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_sub(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator-=(double value)
-{
- copyIfShared();
- mpfr_sub_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator*=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_mul(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator*=(double value)
-{
- copyIfShared();
- mpfr_mul_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator/=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_div(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator/=(double value)
-{
- copyIfShared();
- mpfr_div_d(mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return *this;
-}
-
-MpfrFloat& MpfrFloat::operator%=(const MpfrFloat& rhs)
-{
- copyIfShared();
- mpfr_fmod(mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return *this;
-}
-
-
-//===========================================================================
-// Modifying functions
-//===========================================================================
-void MpfrFloat::negate()
-{
- copyIfShared();
- mpfr_neg(mData->mFloat, mData->mFloat, GMP_RNDN);
-}
-
-void MpfrFloat::abs()
-{
- copyIfShared();
- mpfr_abs(mData->mFloat, mData->mFloat, GMP_RNDN);
-}
-
-
-//===========================================================================
-// Non-modifying operators
-//===========================================================================
-MpfrFloat MpfrFloat::operator+(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_add(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator+(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_add_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_sub(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_sub_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator*(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_mul(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator*(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_mul_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator/(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_div(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator/(double value) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_div_d(retval.mData->mFloat, mData->mFloat, value, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator%(const MpfrFloat& rhs) const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_fmod(retval.mData->mFloat, mData->mFloat, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::operator-() const
-{
- MpfrFloat retval(kNoInitialization);
- mpfr_neg(retval.mData->mFloat, mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-
-
-//===========================================================================
-// Comparison operators
-//===========================================================================
-bool MpfrFloat::operator<(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) < 0;
-}
-
-bool MpfrFloat::operator<(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) < 0;
-}
-
-bool MpfrFloat::operator<=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) <= 0;
-}
-
-bool MpfrFloat::operator<=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) <= 0;
-}
-
-bool MpfrFloat::operator>(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) > 0;
-}
-
-bool MpfrFloat::operator>(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) > 0;
-}
-
-bool MpfrFloat::operator>=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) >= 0;
-}
-
-bool MpfrFloat::operator>=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) >= 0;
-}
-
-bool MpfrFloat::operator==(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) == 0;
-}
-
-bool MpfrFloat::operator==(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) == 0;
-}
-
-bool MpfrFloat::operator!=(const MpfrFloat& rhs) const
-{
- return mpfr_cmp(mData->mFloat, rhs.mData->mFloat) != 0;
-}
-
-bool MpfrFloat::operator!=(double value) const
-{
- return mpfr_cmp_d(mData->mFloat, value) != 0;
-}
-
-
-//===========================================================================
-// Operator functions
-//===========================================================================
-MpfrFloat operator+(double lhs, const MpfrFloat& rhs)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_add_d(retval.mData->mFloat, rhs.mData->mFloat, lhs, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat operator-(double lhs, const MpfrFloat& rhs)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_d_sub(retval.mData->mFloat, lhs, rhs.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat operator*(double lhs, const MpfrFloat& rhs)
-{
- return rhs * lhs;
-}
-
-MpfrFloat operator/(double lhs, const MpfrFloat& rhs)
-{
- return MpfrFloat(lhs) / rhs;
-}
-
-MpfrFloat operator%(double lhs, const MpfrFloat& rhs)
-{
- return MpfrFloat(lhs) % rhs;
-}
-
-std::ostream& operator<<(std::ostream& os, const MpfrFloat& value)
-{
- os << value.getAsString(unsigned(os.precision()));
- return os;
-}
-
-//===========================================================================
-// Static functions
-//===========================================================================
-MpfrFloat MpfrFloat::log(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::log2(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log2(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::log10(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_log10(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp2(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp2(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::exp10(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_exp10(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cos(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cos(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sin(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sin(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::tan(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_tan(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sec(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sec(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::csc(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_csc(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cot(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cot(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-void MpfrFloat::sincos(const MpfrFloat& value,
- MpfrFloat& sin,
- MpfrFloat& cos)
-{
- sin.copyIfShared();
- cos.copyIfShared();
- mpfr_sin_cos
- (sin.mData->mFloat, cos.mData->mFloat, value.mData->mFloat, GMP_RNDN);
-}
-
-MpfrFloat MpfrFloat::acos(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_acos(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::asin(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_asin(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atan(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atan(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atan2(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atan2(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::hypot(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_hypot(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cosh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cosh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sinh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sinh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::tanh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_tanh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::acosh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_acosh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::asinh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_asinh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::atanh(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_atanh(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::sqrt(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_sqrt(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::cbrt(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_cbrt(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::root(const MpfrFloat& value, unsigned long root)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_root(retval.mData->mFloat, value.mData->mFloat, root, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::pow(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_pow(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::pow(const MpfrFloat& value, long exponent)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_pow_si(retval.mData->mFloat, value.mData->mFloat, exponent, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::abs(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_abs(retval.mData->mFloat, value.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::dim(const MpfrFloat& value1, const MpfrFloat& value2)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_dim(retval.mData->mFloat,
- value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::round(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_round(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::ceil(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_ceil(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::floor(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_floor(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::trunc(const MpfrFloat& value)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_trunc(retval.mData->mFloat, value.mData->mFloat);
- return retval;
-}
-
-MpfrFloat MpfrFloat::parseString(const char* str, char** endptr)
-{
- MpfrFloat retval(MpfrFloat::kNoInitialization);
- mpfr_strtofr(retval.mData->mFloat, str, endptr, 0, GMP_RNDN);
- return retval;
-}
-
-MpfrFloat MpfrFloat::const_pi()
-{
- return mpfrFloatDataContainer().const_pi();
-}
-
-MpfrFloat MpfrFloat::const_e()
-{
- return mpfrFloatDataContainer().const_e();
-}
-
-MpfrFloat MpfrFloat::const_log2()
-{
- return mpfrFloatDataContainer().const_log2();
-}
-
-MpfrFloat MpfrFloat::someEpsilon()
-{
- return mpfrFloatDataContainer().const_epsilon();
-}
+++ /dev/null
-#ifndef ONCE_FP_MPFR_FLOAT_
-#define ONCE_FP_MPFR_FLOAT_
-
-#include <iostream>
-
-class MpfrFloat
-{
- public:
- /* A default of 256 bits will be used unless changed with this function.
- Note that all existing and cached GMP objects will be resized to the
- specified precision (which can be a somewhat heavy operation).
- */
- static void setDefaultMantissaBits(unsigned long bits);
-
- static unsigned long getCurrentDefaultMantissaBits();
-
- /* The default constructor initializes the object to the value 0.
- It's efficient to instantiate such zero-initialized objects because
- all of them will share the same mpfr data. (Also any object initialized
- with or assigned the explicit value of zero will also share that one
- mpfr data.) Thus multiple zero-initialized MpfrFloat instances won't
- consume significant amounts of memory (until they are modified to
- contain some other value, of course).
-
- Important caveat:
- ----------------
- Note that initializing an MpfrFloat object with, for example, 0.1 will
- suffer from accuracy problems (at least if the MpfrFloat object has
- more mantissa bits than a double). The C++ double value 0.1 has only
- 53 mantissa bits, while the MpfrFloat object usually has more. If the
- MpfrFloat object is initialized with a double, only that many bits of
- accuracy will end up in the value of the MpfrFloat object. This can
- create significant rounding/accuracy problems in some cases.
- If you need to initialize the MpfrObject with some value (which cannot
- be represented accurately by base-2 floating point numbers, eg. 0.1)
- at full mantissa precision, you have to use parseValue("0.1") instead,
- rather than relying on the constructor taking a double type value.
- */
- MpfrFloat();
- MpfrFloat(double value);
- MpfrFloat(long double value);
- MpfrFloat(long value);
- MpfrFloat(int value);
- MpfrFloat(const char* value, char** endptr);
-
- ~MpfrFloat();
-
- MpfrFloat(const MpfrFloat&);
-
- MpfrFloat& operator=(const MpfrFloat&);
- MpfrFloat& operator=(double value);
- MpfrFloat& operator=(long double value);
- MpfrFloat& operator=(long value);
- MpfrFloat& operator=(int value);
- //MpfrFloat& operator=(const char* value);
-
- void parseValue(const char* value);
- void parseValue(const char* value, char** endptr);
-
-
- /* This function can be used to retrieve the raw mpfr_t data structure
- used by this object. (The template trick is used to avoid a dependency
- of this header file with <mpfr.h>.)
- In other words, it can be called like:
-
- mpfr_t raw_mpfr_data;
- floatValue.get_raw_mpfr_data(raw_mpfr_data);
-
- Note that the returned mpfr_t should be considered as read-only and
- not be modified from the outside because it may be shared among
- several objects. If the calling code needs to modify the data, it
- should copy it for itself first with the appropriate MPFR library
- functions.
- */
- template<typename Mpfr_t>
- void get_raw_mpfr_data(Mpfr_t& dest_mpfr_t);
-
-
- /* Note that the returned char* points to an internal (shared) buffer
- which will be valid until the next time this function is called
- (by any object).
- */
- const char* getAsString(unsigned precision) const;
-
- bool isInteger() const;
- long toInt() const;
- double toDouble() const;
-
- MpfrFloat& operator+=(const MpfrFloat&);
- MpfrFloat& operator+=(double);
- MpfrFloat& operator-=(const MpfrFloat&);
- MpfrFloat& operator-=(double);
- MpfrFloat& operator*=(const MpfrFloat&);
- MpfrFloat& operator*=(double);
- MpfrFloat& operator/=(const MpfrFloat&);
- MpfrFloat& operator/=(double);
- MpfrFloat& operator%=(const MpfrFloat&);
-
- void negate();
- void abs();
-
- MpfrFloat operator+(const MpfrFloat&) const;
- MpfrFloat operator+(double) const;
- MpfrFloat operator-(const MpfrFloat&) const;
- MpfrFloat operator-(double) const;
- MpfrFloat operator*(const MpfrFloat&) const;
- MpfrFloat operator*(double) const;
- MpfrFloat operator/(const MpfrFloat&) const;
- MpfrFloat operator/(double) const;
- MpfrFloat operator%(const MpfrFloat&) const;
-
- MpfrFloat operator-() const;
-
- bool operator<(const MpfrFloat&) const;
- bool operator<(double) const;
- bool operator<=(const MpfrFloat&) const;
- bool operator<=(double) const;
- bool operator>(const MpfrFloat&) const;
- bool operator>(double) const;
- bool operator>=(const MpfrFloat&) const;
- bool operator>=(double) const;
- bool operator==(const MpfrFloat&) const;
- bool operator==(double) const;
- bool operator!=(const MpfrFloat&) const;
- bool operator!=(double) const;
-
- static MpfrFloat log(const MpfrFloat&);
- static MpfrFloat log2(const MpfrFloat&);
- static MpfrFloat log10(const MpfrFloat&);
- static MpfrFloat exp(const MpfrFloat&);
- static MpfrFloat exp2(const MpfrFloat&);
- static MpfrFloat exp10(const MpfrFloat&);
- static MpfrFloat cos(const MpfrFloat&);
- static MpfrFloat sin(const MpfrFloat&);
- static MpfrFloat tan(const MpfrFloat&);
- static MpfrFloat sec(const MpfrFloat&);
- static MpfrFloat csc(const MpfrFloat&);
- static MpfrFloat cot(const MpfrFloat&);
- static void sincos(const MpfrFloat&, MpfrFloat& sin, MpfrFloat& cos);
- static MpfrFloat acos(const MpfrFloat&);
- static MpfrFloat asin(const MpfrFloat&);
- static MpfrFloat atan(const MpfrFloat&);
- static MpfrFloat atan2(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat hypot(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat cosh(const MpfrFloat&);
- static MpfrFloat sinh(const MpfrFloat&);
- static MpfrFloat tanh(const MpfrFloat&);
- static MpfrFloat acosh(const MpfrFloat&);
- static MpfrFloat asinh(const MpfrFloat&);
- static MpfrFloat atanh(const MpfrFloat&);
- static MpfrFloat sqrt(const MpfrFloat&);
- static MpfrFloat cbrt(const MpfrFloat&);
- static MpfrFloat root(const MpfrFloat&, unsigned long root);
- static MpfrFloat pow(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat pow(const MpfrFloat&, long exponent);
- static MpfrFloat abs(const MpfrFloat&);
- static MpfrFloat dim(const MpfrFloat&, const MpfrFloat&);
- static MpfrFloat round(const MpfrFloat&);
- static MpfrFloat ceil(const MpfrFloat&);
- static MpfrFloat floor(const MpfrFloat&);
- static MpfrFloat trunc(const MpfrFloat&);
-
- static MpfrFloat parseString(const char* str, char** endptr);
-
- // These values are cached (and recalculated every time the mantissa bits
- // change), so it's efficient to call these repeatedly:
- static MpfrFloat const_pi();
- static MpfrFloat const_e();
- static MpfrFloat const_log2();
- static MpfrFloat someEpsilon();
-
-
- private:
- struct MpfrFloatData;
- class MpfrFloatDataContainer;
-
- MpfrFloatData* mData;
-
- enum DummyType { kNoInitialization };
- MpfrFloat(DummyType);
- MpfrFloat(MpfrFloatData*);
-
- void copyIfShared();
- static MpfrFloatDataContainer& mpfrFloatDataContainer();
-
- friend MpfrFloat operator+(double lhs, const MpfrFloat& rhs);
- friend MpfrFloat operator-(double lhs, const MpfrFloat& rhs);
-};
-
-MpfrFloat operator+(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator-(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator*(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator/(double lhs, const MpfrFloat& rhs);
-MpfrFloat operator%(double lhs, const MpfrFloat& rhs);
-
-inline bool operator<(double lhs, const MpfrFloat& rhs) { return rhs > lhs; }
-inline bool operator<=(double lhs, const MpfrFloat& rhs) { return rhs >= lhs; }
-inline bool operator>(double lhs, const MpfrFloat& rhs) { return rhs < lhs; }
-inline bool operator>=(double lhs, const MpfrFloat& rhs) { return rhs <= lhs; }
-inline bool operator==(double lhs, const MpfrFloat& rhs) { return rhs == lhs; }
-inline bool operator!=(double lhs, const MpfrFloat& rhs) { return rhs != lhs; }
-
-// This function takes into account the value of os.precision()
-std::ostream& operator<<(std::ostream& os, const MpfrFloat& value);
-
-#endif
## ---------------------------------------------------------------------
-## $Id$
+## $Id: CMakeLists.txt 32392 2014-02-03 16:24:36Z heister $
##
## Copyright (C) 2012 - 2013 by the deal.II authors
##
## ---------------------------------------------------------------------
#
-# Remove -Wall and -pedantic from DEAL_II_CXX_FLAGS (in directory scope) to
# avoid some annoying warnings...
#
STRIP_FLAG(DEAL_II_CXX_FLAGS "-Wall")
STRIP_FLAG(DEAL_II_CXX_FLAGS "-pedantic")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-switch)
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS -Wno-nested-anon-types)
-DEAL_II_ADD_LIBRARY(obj_functionparser OBJECT
- fparser.cc
- fpoptimizer.cc
+INCLUDE_DIRECTORIES(
+ include/
+)
+
+DEAL_II_ADD_LIBRARY(obj_muparser OBJECT
+src/muParserBase.cpp
+src/muParserBytecode.cpp
+src/muParserCallback.cpp
+src/muParser.cpp
+src/muParserError.cpp
+src/muParserInt.cpp
+src/muParserTest.cpp
+src/muParserTokenReader.cpp
)
-IF(DEAL_II_WITH_THREADS)
- DEAL_II_ADD_DEFINITIONS(obj_functionparser "FP_USE_THREAD_SAFE_EVAL")
-ENDIF()
+#IF(DEAL_II_WITH_THREADS)
+# DEAL_II_ADD_DEFINITIONS(obj_muparser "FP_USE_THREAD_SAFE_EVAL")
+#ENDIF()
--- /dev/null
+#######################################################################\r
+# #\r
+# #\r
+# __________ #\r
+# _____ __ __\______ \_____ _______ ______ ____ _______ #\r
+# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #\r
+# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #\r
+# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #\r
+# \/ \/ \/ \/ #\r
+# Fast math parser Library #\r
+# #\r
+# Copyright (C) 2013 Ingo Berg #\r
+# #\r
+# Web: muparser.beltoforion.de #\r
+# e-mail: muparser@beltoforion.de #\r
+# #\r
+# #\r
+#######################################################################\r
+\r
+\r
+History:\r
+--------\r
+\r
+Rev 2.2.3: 22.12.2012\r
+---------------------\r
+\r
+ Removed features:\r
+ * build files for msvc2005, borland and watcom compiler were removed\r
+\r
+ Bugfixes:\r
+ * Bugfix for Intel Compilers added: The power operator did not work properly \r
+ with Intel C++ composer XE 2011.\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5117983/index/page/1)\r
+ * Issue 3509860: Callbacks of functions with string parameters called twice\r
+ (see http://sourceforge.net/tracker/?func=detail&aid=3509860&group_id=137191&atid=737979)\r
+ * Issue 3570423: example1 shows slot number in hexadecimal\r
+ (see https://sourceforge.net/tracker/?func=detail&aid=3570423&group_id=137191&atid=737979)\r
+ * Fixes for compiling with the "MUP_MATH_EXCEPTIONS" macro definition:\r
+ - division by zero in constant expressions was reported with the code "ec_GENERIC" \r
+ instead of "ecDIV_BY_ZERO"\r
+ - added throwing of "ecDOMAIN_ERROR" to sqrt and log functions\r
+\r
+\r
+Rev 2.2.2: 18.02.2012\r
+---------------------\r
+ Bugfixes:\r
+ * Optimizer did'nt work properly for division:\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825)\r
+\r
+Rev 2.2.1: 22.01.2012\r
+---------------------\r
+ Bugfixes:\r
+ * Optimizer bug in 64 bit systems fixed\r
+ (see https://sourceforge.net/projects/muparser/forums/forum/462843/topic/4977977/index/page/1)\r
+ \r
+Rev 2.2.0: 22.01.2012\r
+---------------------\r
+ Improvements:\r
+ * Optimizer rewritten and improved. In general: more optimizations are \r
+ now applied to the bytecode. The downside is that callback Functions \r
+ can no longer be flagged as non-optimizable. (The flag is still present \r
+ but ignored) This is necessary since the optimizer had to call the \r
+ functions in order to precalculate the result (see Bugfixes). These calls \r
+ posed a problems for callback functions with side effects and if-then-else \r
+ clauses in general since they undermined the shortcut evaluation prinziple.\r
+\r
+ Bugfixes:\r
+ * Infix operators where not properly detected in the presence of a constant \r
+ name starting with an underscore which is a valid character for infix \r
+ operators too (i.e. "-_pi").\r
+ * Issue 3463353: Callback functions are called twice during the first call to eval.\r
+ * Issue 3447007: GetUsedVar unnecessaryly executes callback functions.\r
+\r
+\r
+Rev 2.1.0: 19.11.2011\r
+---------------------\r
+ New feature:\r
+ * Function atan2 added\r
+\r
+ Bugfixes:\r
+ * Issue 3438380: Changed behaviour of tellg with GCC >4.6 led to failures \r
+ in value detection callbacks.\r
+ * Issue 3438715: only "double" is a valid MUP_BASETYPE \r
+ MUP_BASETYPE can now be any of:\r
+ float, \r
+ double, \r
+ long double, \r
+ short, \r
+ unsigned short, \r
+ unsigned int, \r
+ long,\r
+ unsigned long. \r
+ Previousely only floating point types were allowed. \r
+ Using "int" is still not allowed!\r
+ * Compiler issues with GCC 4.6 fixed\r
+ * Custom value recognition callbacks added with AddValIdent had lower\r
+ priority than built in functions. This was causing problems with \r
+ hex value recognition since detection of non hex values had priority\r
+ over the detection of hex values. The "0" in the hex prefix "0x" would \r
+ be read as a separate non-hex number leaving the rest of the expression\r
+ unparseable.\r
+\r
+Rev 2.0.0: 04.09.2011\r
+---------------------\r
+This release introduces a new version numbering scheme in order to make\r
+future changes in the ABI apparent to users of the library. The number is\r
+now based on the SONAME property as used by GNU/Linux. \r
+\r
+ Changes:\r
+ * Beginning with this version all version numbers will be SONAME compliant\r
+ * Project files for MSVC2010 added\r
+ * Project files for MSVC2003 removed\r
+ * Bytecode parsing engine cleaned up and rewritten\r
+ * Retrieving all results of expressions made up of comma separate \r
+ subexpressions is now possible with a new Eval overload.\r
+ * Callback functions with fixed number of arguments can now have up to 10 \r
+ Parameters (previous limit was 5)\r
+\r
+ New features:\r
+ * ternary if-then-else operator added (C++ like; "(...) ? ... : ..." )\r
+ * new intrinsic binary operators: "&&", "||" (logical and, or)\r
+ * A new bulkmode allows submitting large arrays as variables to compute large \r
+ numbers of expressions with a single call. This can drastically improve \r
+ parsing performance when interfacing the library from managed languages like \r
+ C#. (It doesn't bring any performance benefit for C++ users though...)\r
+\r
+ Removed features:\r
+ * intrinsic "and", "or" and "xor" operators have been removed. I'd like to let \r
+ users the freedom of defining them on their own versions (either as logical or bitwise \r
+ operators).\r
+ * Implementation for complex numbers removed. This was merely a hack. If you \r
+ need complex numbers try muParserX which provides native support for them.\r
+ (see: http://beltoforion.de/muparserx/math_expression_parser_en.html)\r
+\r
+ Bugfixes:\r
+ * User defined operators could collide with built in operators that entirely \r
+ contained their identifier. i.e. user defined "&" would not work with the built \r
+ in "&&" operator since the user defined operator was detected with a higher \r
+ priority resulting in a syntax error.\r
+ * Detection of unknown variables did not work properly in case a postfix operator\r
+ was defined which was part of the undefined variable.\r
+ i.e. If a postfix operator "m" was defined expressions like "multi*1.0" did\r
+ not detect "multi" as an undefined variable.\r
+ (Reference: http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979)\r
+ * Postfix operators sharing the first few characters were causing bogus parsing exception.\r
+ (Reference: https://sourceforge.net/tracker/?func=detail&aid=3358571&group_id=137191&atid=737979)\r
+\r
+Rev 1.34: 04.09.2010\r
+--------------------\r
+ Changes:\r
+ * The prefix needed for parsing hex values is now "0x" and no longer "$". \r
+ * AddValIdent reintroduced into the DLL interface\r
+\r
+ New features:\r
+ * The associativity of binary operators can now be changed. The pow operator \r
+ is now right associative. (This is what Mathematica is using) \r
+ * Seperator can now be used outside of functions. This allows compound \r
+ expressions like:\r
+ "a=10,b=20,c=a*b" The last "argument" will be taken as the return value\r
+\r
+ Bugfixes: \r
+ * The copy constructor did not copy binary operator definitions. Those were lost\r
+ in the copied parser instance.\r
+ * Mixing special characters and alphabetic characters in binary operator names \r
+ led to inconsistent parsing behaviour when parsing expressions like "a ++ b" \r
+ and "a++b" when "++" is defined as a binary operator. Binary operators must \r
+ now consist entirely of special characters or of alphabetic ones.\r
+ (original bug report: https://sourceforge.net/projects/muparser/forums/forum/462843/topic/3696881/index/page/1)\r
+ * User defined operators were not exactly handled like built in operators. This \r
+ led to inconsistencies in expression evaluation when using them. The results \r
+ differed due to slightly different precedence rules.\r
+ * Using empty string arguments ("") would cause a crash of muParser\r
+\r
+\r
+Rev 1.32: 29.01.2010 \r
+--------------------\r
+\r
+ Changes:\r
+ * "example3" renamed to "example2"\r
+ * Project/Makefiles files are now provided for:\r
+ - msvc2003 \r
+ - msvc2005 \r
+ - msvc2008\r
+ - watcom (makefile)\r
+ - mingw (makefile)\r
+ - bcc (makefile)\r
+ * Project files for borland cpp builder were removed\r
+\r
+\r
+ New features:\r
+ * Added function returning muparsers version number\r
+ * Added function for resetting the locale\r
+\r
+\r
+ Bugfixes: \r
+ * Changes example1 in order to fix issues with irritating memory leak reports. \r
+ Added conditional code for memory leak detection with MSVC in example1.\r
+ (see: http://www.codeproject.com/KB/recipes/FastMathParser.aspx?msg=3286367#xx3286367xx)\r
+ * Fixed some warnings for gcc\r
+\r
+\r
+\r
+Rev 1.31cp: 15.01.2010 (Maintainance release for CodeProject)\r
+----------------------\r
+\r
+ Changes:\r
+ * Archive structure changed\r
+ * C# wrapper added\r
+ * Fixed issued that prevented compiling with VS2010 Beta2\r
+ \r
+\r
+Rev 1.30: 09.06.2008\r
+--------------------\r
+\r
+ Changes:\r
+ * Epsilon of the numerical differentiation algorithm changed to allow greater accuracy.\r
+\r
+ New features:\r
+ * Setting thousands separator and decimal separator is now possible\r
+\r
+ Bugfixes:\r
+ * The dll interface did not provide a callback for functions without any arguments. \r
+ \r
+\r
+Rev 1.29: Januar 2008\r
+---------------------\r
+\r
+ Unrelease Version available only via SVN.\r
+\r
+\r
+Rev 1.28: 02. July, 2007\r
+---------------------------\r
+ \r
+ Library changes:\r
+ * Interface for the dynamic library changed and extended to create an interface \r
+ using pure C functions only. \r
+ * mupInit() removed\r
+\r
+ Build system:\r
+ * MSVC7 Project files removed in favor of MSVC8\r
+\r
+ Bugfixes:\r
+ * The dynamic library did not build on other systems than linux due to a misplaced \r
+ preprocessor definition. This is fixed now.\r
+\r
+\r
+Rev 1.27:\r
+---------------------------\r
+\r
+ Build system:\r
+ * Modified build\ directory layout introducing some subfolders \r
+ for the various IDE supported\r
+ * Project files for BCB and MSVC7 added\r
+ * Switched to use bakefile 0.2.1 which now correctly creates the \r
+ "make uninstall" target for autoconf's Makefile.in\r
+ * Now the library debug builds are named "muparserd" instead of "muparser"\r
+ to allow multiple mixed release/debug builds to coexist; so e.g. on Windows\r
+ when building with DEBUG=1, you'll get "muparserd.lib" instead of "muparser.lib"\r
+\r
+ New Features:\r
+ * Factory functions can now take a user defined pointer\r
+ * String functions can now be used with up to two additional \r
+ double parameters\r
+ * Support for UNICODE character types added\r
+ * Infix operator priority can now be changed by the user\r
+\r
+ Bugfixes:\r
+ * An internal error was raised when evaluating an empty \r
+ expressions\r
+ * The error message raised in case of name collisions between \r
+ implicitely defined variables and postfix operators did contain\r
+ misleading data.\r
+\r
+\r
+Rev 1.26: (unofficial release)\r
+------------------------------\r
+\r
+ New Features:\r
+ * Unary operator precedence can now be changed by the user.\r
+\r
+\r
+Rev 1.25: 5. February, 2006\r
+---------------------------\r
+\r
+ Build system: (special thanks to Francesco Montorsi for implementing it!)\r
+ * created a bakefile-based build system which adds support for the following win32 compilers:\r
+ -> MS visual C++ (6 and .NET)\r
+ -> BorlandC++ (5 or greater)\r
+ -> Mingw32 (tested with gcc 3.2)\r
+ -> Watcom (not tested)\r
+ and for GCC on Unix (using a standard autoconf's configure script).\r
+\r
+ Compatibility improvements:\r
+ * fixed some small warnings when using -Wall with GCC on Unix\r
+ * added inclusion guards for win32-specific portions of code\r
+ * added fixes that remove compiler warnings on Intel C++ and the Solaris C++ compiler.\r
+\r
+\r
+Rev 1.24: 29. October, 2005\r
+---------------------------\r
+\r
+Changes:\r
+\r
+ Compatibility improvements:\r
+ * parser now works on 64 bit compilers\r
+ * (bytecode base datatype can now be changed freely)\r
+\r
+\r
+Rev 1.23: 19. October, 2005\r
+---------------------------\r
+\r
+Changes:\r
+\r
+ Bugfixes:\r
+ * Variable factory examples in Example1.cpp and Example3.cpp contained a subtle bug.\r
+\r
+ New features:\r
+ * Added a MSVC6 project file and introduced muParserFixes.h in order to make it compile with MSVC6\r
+\r
+\r
+Rev 1.22: October, 2005\r
+-----------------------\r
+\r
+Release notes:\r
+\r
+All features of Version 1.22 are similar to Version 1.21. Version 1.22 fixes a compilation issue with\r
+gcc 4.0. In order to fix this issue I rewrote part of the library to remove some unnecessary templates. \r
+This should make the code cleaner. The Borland Project files were removed. If you want to use it \r
+with Borland either use the dll version or create your own project files. I can't support it since I don't \r
+have this compiler at hand.\r
+\r
+Changes:\r
+\r
+ Project Changes:\r
+ * Borland project files removed\r
+ (The code should still compile with BCB but I cant provide you with project files)\r
+\r
+ Internal Changes:\r
+ * unnecessary template files have been removed:\r
+ - new files: muParserError.cpp, muParserTokenReader.cpp, muParserCallback.cpp\r
+ - removed Files: muIParserTypes.h\r
+\r
+\r
+Rev 1.2 / 1.21: April, 2005\r
+---------------------------\r
+\r
+Release Notes:\r
+First of all the interface has changed so this version is not backwards compatible.\r
+After receiving a couple of questions about it, this version features support for\r
+user defined binary operators. Consequently the built in operators can now be \r
+turned off, thus you can deactivate them and write complete customized parser\r
+subclasses that only contain the functionality you want. Another new feature is \r
+the introduction of callback functions taking string arguments, implicit \r
+generation of variables and the Assignement operator.\r
+\r
+ Functionality\r
+ * New built in operator: xor; Logical xor.\r
+ * New built in operator: Assignement operator; Defining variables in terms of \r
+ other variables/constants\r
+ * New feature: Strings as arguments for callback functions\r
+ * New feature: User defined binary operators\r
+ * New feature: ParserInt a class with a sample implementation for\r
+ integer numbers.\r
+ * New feature: Callbacks to value regognition functions.\r
+\r
+ * Removed: all predefined postfix operators have been removed.\r
+ * New project file: Now comes with a ready to use windows DLL.\r
+ * New project file: Makefile for cygwin now included.\r
+ * New example: Example3 shows usage of the DLL.\r
+\r
+ Interface changes\r
+ * New member function: DefineOprt For adding user defined binary operators.\r
+ * New member function: EnableBuiltInOprt(bool) Enables/Disables built in \r
+ binary operators.\r
+ * New member function: AddValIdent(...) to add callbacks for custom value \r
+ recognition functions.\r
+ * Removed: SetVar(), SetConst().\r
+ * Renamed: Most interface functions have been renamed\r
+ * Changed: The type for multiargument callbacks multfun_type has changed. \r
+ It no longer takes a std::vector as input.\r
+\r
+ Internal changes\r
+ * new class muParserTokenReader.h encapsulates the token identification \r
+ and token assignement.\r
+ * Internal handling of function callbacks unified as a result the performance \r
+ of the bytecode evaluation increased.\r
+\r
+\r
+Rev 1.10 : December 30, 2004\r
+----------------------------\r
+\r
+Release Notes:\r
+This version does not contain major new feature compared to V1.07 but its internal structure has\r
+changed significantly. The String parsing routine is slower than the one of V1.07 but bytecode\r
+parsing is equally fast. On the other hand the error messages of V1.09 are more flexible and you\r
+can change its value datatype. It should work on 64-bit systems. For this reason I supply both\r
+versions for download. If you use V1.07 and are happy with it there is no need for updating\r
+your version.\r
+\r
+ * New example program: Archive now contains two demo programs: One for standard C++ and one for\r
+ managed C++.\r
+ * New member function: RemoveVar(...) can be used for removing a single variable from the internal \r
+ storage.\r
+ * New member function: GetVar() can be used for querying the variable names and pointers of all\r
+ variables defined in the parser.\r
+ * New member function: GetConst() can be used for querying all defined constants and their values.\r
+ * New member function: GetFunDef() can be used for querying all defined functions and the number of\r
+ arguments they expect.\r
+ * Internal structure changed; hanging base datatype at compile time is now possible.\r
+ * Bugfix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
+ * Bugfix: Variable names must will now be tested if they conflict with constant or function names.\r
+ * Internal change: Removed most dependencies from the C-string libraries.\r
+ * Internal change: Bytecode is now stored in a separate class: ParserByteCode.h\r
+ * Internal change: GetUsedVar() does no longer require that variables are defined at time of call.\r
+ * Internal change: Error treatment changed. ParserException is no longer derived from\r
+ std::runtime_error; Internal treatment of Error messages changed.\r
+ * New functions in Parser interface: ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
+ they are used for defining the charset allowed for variable-, operator- and\r
+ function names.\r
+\r
+\r
+Rev 1.09 : November 20, 2004\r
+----------------------------\r
+\r
+ * New member function: RemoveVar(...) can be used for removing a single variable from the internal \r
+ storage.\r
+ * Internal structure changed; changing base datatype at compile time is now possible.\r
+ * Bug fix: Postfix operator parsing could fail in certain cases; This has been fixed now.\r
+ * Internal change: Removed most dependencies from the C-string libraries.\r
+ * Internal change: Bytecode is now stored in a seperate class: ParserByteCode.h.\r
+ * Internal change: GetUsedVar() does no longer require that variables are defined at time of call.\r
+ * Internal change: Error treatment changed. ParserException is no longer derived from \r
+ std::runtime_error; Internal treatment of Error messages changed.\r
+ * New functions in Parser interface; ValidNameChars(), ValidOprtChars() and ValidPrefixOprtChars()\r
+ they are used for defining the charset allowed for variable-, operator- and function names.\r
+\r
+\r
+Rev 1.08 : November, 2004 \r
+-------------------------\r
+\r
+ * unpublished; experimental template version with respect to data type and underlying string\r
+ type (string <-> widestring). The idea was dropped...\r
+\r
+\r
+Rev 1.07 : September 4 2004\r
+---------------------------\r
+\r
+ * Improved portability; Changes to make life for MSVC 6 user easier, there are probably still some\r
+ issues left.\r
+ * Improved portability; Changes in order to allow compiling on BCB.\r
+ * New function; value_type Diff(value_type *a_Var, value_type a_fPos) 4th order Differentiation with\r
+ respect to a certain variable; added in muParser.h.\r
+\r
+\r
+Rev 1.06 : August 20 2004\r
+-------------------------\r
+\r
+ * Volatile functions added; All overloaded AddFun(...) functions can now take a third parameter\r
+ indicating that the function can not be optimized.\r
+ * Internal changes: muParserStack.h simplified; refactorings\r
+ * Parser is now distributed under the MIT License; all comments changed accordingly.\r
+\r
+\r
+Rev 1.05 : August 20 2004\r
+-------------------------\r
+\r
+ * Variable/constant names will now be checked for invalid characters.\r
+ * Querying the names of all variables used in an expression is now possible; new function: GetUsedVar().\r
+ * Disabling bytecode parsing is now possible; new function: EnableByteCode(bool bStat).\r
+ * Predefined functions with variable number of arguments added: sum, avg, min, max.\r
+ * Unary prefix operators added; new functions: AddPrefixOp(...), ClearPrefixOp().\r
+ * Postfix operator interface names changed; new function names: AddPostfixOp(...), ClearPostfixOp().\r
+ * Hardcoded sign operators removed in favor of prefix operators; bytecode format changed accordingly.\r
+ * Internal changes: static array removed in Command code calculation routine; misc. changes.\r
+\r
+\r
+Rev 1.04 : August 16 2004\r
+-------------------------\r
+\r
+ * Support for functions with variable number of arguments added.\r
+ * Internal structure changed; new: ParserBase.h, ParserBase.cpp; removed: ParserException.h;\r
+ changed: Parser.h, Parser.cpp.\r
+ * Bug in the bytecode calculation function fixed (affected the unary minus operator).\r
+ * Optimizer can be deactivated; new function: EnableOptimizer(bool bStat).\r
+\r
+\r
+Rev 1.03 : August 10 2004\r
+-------------------------\r
+\r
+ * Support for user-defined unary postfix operators added; new functions: AddPostOp(), InitPostOp(),\r
+ ClearPostOp().\r
+ * Minor changes to the bytecode parsing routine.\r
+ * User defined functions can now have up to four parameters.\r
+ * Performance optimized: simple formula optimization added; (precalculation of constant parts of the\r
+ expression).\r
+ * Bug fixes: Multi-arg function parameters, constant name lookup and unary minus did not work properly.\r
+\r
+\r
+Rev 1.02 : July 30 2004\r
+-----------------------\r
+\r
+ * Support for user defined constants added; new functions: InitConst(), AddConst(), SetConst(),\r
+ ClearConst().\r
+ * Single variables can now be added using AddVar(); you have now the choice of adding them either\r
+ one by one or all at the same time using SetVar(const varmap_type &a_vVar).\r
+ * Internal handling of variables changed, is now similar to function handling.\r
+ * Virtual destructor added; InitFun(), InitConst() are now virtual too thus making it possible to\r
+ derive new parsers with a modified set of default functions and constants.\r
+ * Support for user defined functions with 2 or 3 parameters added; bytecode format changed to hold\r
+ function parameter count.\r
+\r
+\r
+Rev 1.01 : July 23 2004\r
+-----------------------\r
+\r
+ * Support for user defined functions has been added; new functions: AddFun(), ClearFun(),\r
+ InitFunctions().\r
+ * Built in constants have been removed; the parser contained undocumented built in\r
+ constants pi, e.\r
+ There was the possibility of name conflicts with user defined variables.\r
+ * Setting multiple variables with SetVar can now be done with a map of names and pointers as the only\r
+ argument. For this reason, a new type Parser::varmap_type was added. The old version that took 3\r
+ arguments (array of names, array of pointers, and array length) is now marked as deprecated.\r
+ * The names of logarithm functions have changed. The new names are: log2 for base 2, log10 or log for\r
+ base 10, and ln for base e.\r
+\r
+\r
+Rev 1.00 : July 21 2004\r
+-----------------------\r
+\r
+ * Initial release\r
--- /dev/null
+#######################################################################\r
+# #\r
+# #\r
+# __________ #\r
+# _____ __ __\______ \_____ _______ ______ ____ _______ #\r
+# / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ #\r
+# | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ #\r
+# |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| #\r
+# \/ \/ \/ \/ #\r
+# Fast math parser Library #\r
+# #\r
+# Copyright (C) 2011 Ingo Berg #\r
+# #\r
+# Web: muparser.beltoforion.de #\r
+# e-mail: muparser@beltoforion.de #\r
+# #\r
+# #\r
+#######################################################################\r
+\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+ OR OTHER DEALINGS IN THE SOFTWARE.\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_H\r
+#define MU_PARSER_H\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <vector>\r
+\r
+//--- Parser includes --------------------------------------------------------------------------\r
+#include "muParserBase.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+/** \file\r
+ \brief Definition of the standard floating point parser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Mathematical expressions parser.\r
+ \r
+ Standard implementation of the mathematical expressions parser. \r
+ Can be used as a reference implementation for subclassing the parser.\r
+\r
+ <small>\r
+ (C) 2011 Ingo Berg<br>\r
+ muparser(at)gmx.de\r
+ </small>\r
+ */\r
+ /* final */ class Parser : public ParserBase\r
+ {\r
+ public:\r
+\r
+ Parser();\r
+\r
+ virtual void InitCharSets();\r
+ virtual void InitFun();\r
+ virtual void InitConst();\r
+ virtual void InitOprt();\r
+ virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);\r
+\r
+ value_type Diff(value_type *a_Var, \r
+ value_type a_fPos, \r
+ value_type a_fEpsilon = 0) const;\r
+\r
+ protected:\r
+\r
+ // Trigonometric functions\r
+ static value_type Sin(value_type);\r
+ static value_type Cos(value_type);\r
+ static value_type Tan(value_type);\r
+ static value_type Tan2(value_type, value_type);\r
+ // arcus functions\r
+ static value_type ASin(value_type);\r
+ static value_type ACos(value_type);\r
+ static value_type ATan(value_type);\r
+ static value_type ATan2(value_type, value_type);\r
+\r
+ // hyperbolic functions\r
+ static value_type Sinh(value_type);\r
+ static value_type Cosh(value_type);\r
+ static value_type Tanh(value_type);\r
+ // arcus hyperbolic functions\r
+ static value_type ASinh(value_type);\r
+ static value_type ACosh(value_type);\r
+ static value_type ATanh(value_type);\r
+ // Logarithm functions\r
+ static value_type Log2(value_type); // Logarithm Base 2\r
+ static value_type Log10(value_type); // Logarithm Base 10\r
+ static value_type Ln(value_type); // Logarithm Base e (natural logarithm)\r
+ // misc\r
+ static value_type Exp(value_type);\r
+ static value_type Abs(value_type);\r
+ static value_type Sqrt(value_type);\r
+ static value_type Rint(value_type);\r
+ static value_type Sign(value_type);\r
+\r
+ // Prefix operators\r
+ // !!! Unary Minus is a MUST if you want to use negative signs !!!\r
+ static value_type UnaryMinus(value_type);\r
+\r
+ // Functions with variable number of arguments\r
+ static value_type Sum(const value_type*, int); // sum\r
+ static value_type Avg(const value_type*, int); // mean value\r
+ static value_type Min(const value_type*, int); // minimum\r
+ static value_type Max(const value_type*, int); // maximum\r
+\r
+ static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal);\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_BASE_H\r
+#define MU_PARSER_BASE_H\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cmath>\r
+#include <string>\r
+#include <iostream>\r
+#include <map>\r
+#include <memory>\r
+#include <locale>\r
+\r
+//--- Parser includes --------------------------------------------------------------------------\r
+#include "muParserDef.h"\r
+#include "muParserStack.h"\r
+#include "muParserTokenReader.h"\r
+#include "muParserBytecode.h"\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+/** \file\r
+ \brief This file contains the class definition of the muparser engine.\r
+*/\r
+\r
+//--------------------------------------------------------------------------------------------------\r
+/** \brief Mathematical expressions parser (base parser engine).\r
+ \author (C) 2013 Ingo Berg\r
+\r
+ This is the implementation of a bytecode based mathematical expressions parser. \r
+ The formula will be parsed from string and converted into a bytecode. \r
+ Future calculations will be done with the bytecode instead the formula string\r
+ resulting in a significant performance increase. \r
+ Complementary to a set of internally implemented functions the parser is able to handle \r
+ user defined functions and variables. \r
+*/\r
+class ParserBase \r
+{\r
+friend class ParserTokenReader;\r
+\r
+private:\r
+\r
+ /** \brief Typedef for the parse functions. \r
+ \r
+ The parse function do the actual work. The parser exchanges\r
+ the function pointer to the parser function depending on \r
+ which state it is in. (i.e. bytecode parser vs. string parser)\r
+ */\r
+ typedef value_type (ParserBase::*ParseFunction)() const; \r
+\r
+ /** \brief Type used for storing an array of values. */\r
+ typedef std::vector<value_type> valbuf_type;\r
+\r
+ /** \brief Type for a vector of strings. */\r
+ typedef std::vector<string_type> stringbuf_type;\r
+\r
+ /** \brief Typedef for the token reader. */\r
+ typedef ParserTokenReader token_reader_type;\r
+ \r
+ /** \brief Type used for parser tokens. */\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */\r
+ static const int s_MaxNumOpenMPThreads = 4;\r
+\r
+ public:\r
+\r
+ /** \brief Type of the error class. \r
+ \r
+ Included for backwards compatibility.\r
+ */\r
+ typedef ParserError exception_type;\r
+\r
+ static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);\r
+\r
+ ParserBase(); \r
+ ParserBase(const ParserBase &a_Parser);\r
+ ParserBase& operator=(const ParserBase &a_Parser);\r
+\r
+ virtual ~ParserBase();\r
+ \r
+ value_type Eval() const;\r
+ value_type* Eval(int &nStackSize) const;\r
+ void Eval(value_type *results, int nBulkSize);\r
+\r
+ int GetNumResults() const;\r
+\r
+ void SetExpr(const string_type &a_sExpr);\r
+ void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);\r
+\r
+ void SetDecSep(char_type cDecSep);\r
+ void SetThousandsSep(char_type cThousandsSep = 0);\r
+ void ResetLocale();\r
+\r
+ void EnableOptimizer(bool a_bIsOn=true);\r
+ void EnableBuiltInOprt(bool a_bIsOn=true);\r
+\r
+ bool HasBuiltInOprt() const;\r
+ void AddValIdent(identfun_type a_pCallback);\r
+\r
+ /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) \r
+ \brief Define a parser function without arguments.\r
+ \param a_strName Name of the function\r
+ \param a_pFun Pointer to the callback function\r
+ \param a_bAllowOpt A flag indicating this function may be optimized\r
+ */\r
+ template<typename T>\r
+ void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)\r
+ {\r
+ AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );\r
+ }\r
+\r
+ void DefineOprt(const string_type &a_strName, \r
+ fun_type2 a_pFun, \r
+ unsigned a_iPri=0, \r
+ EOprtAssociativity a_eAssociativity = oaLEFT,\r
+ bool a_bAllowOpt = false);\r
+ void DefineConst(const string_type &a_sName, value_type a_fVal);\r
+ void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);\r
+ void DefineVar(const string_type &a_sName, value_type *a_fVar);\r
+ void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);\r
+ void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);\r
+\r
+ // Clear user defined variables, constants or functions\r
+ void ClearVar();\r
+ void ClearFun();\r
+ void ClearConst();\r
+ void ClearInfixOprt();\r
+ void ClearPostfixOprt();\r
+ void ClearOprt();\r
+ \r
+ void RemoveVar(const string_type &a_strVarName);\r
+ const varmap_type& GetUsedVar() const;\r
+ const varmap_type& GetVar() const;\r
+ const valmap_type& GetConst() const;\r
+ const string_type& GetExpr() const;\r
+ const funmap_type& GetFunDef() const;\r
+ string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;\r
+\r
+ const char_type ** GetOprtDef() const;\r
+ void DefineNameChars(const char_type *a_szCharset);\r
+ void DefineOprtChars(const char_type *a_szCharset);\r
+ void DefineInfixOprtChars(const char_type *a_szCharset);\r
+\r
+ const char_type* ValidNameChars() const;\r
+ const char_type* ValidOprtChars() const;\r
+ const char_type* ValidInfixOprtChars() const;\r
+\r
+ void SetArgSep(char_type cArgSep);\r
+ char_type GetArgSep() const;\r
+ \r
+ void Error(EErrorCodes a_iErrc, \r
+ int a_iPos = (int)mu::string_type::npos, \r
+ const string_type &a_strTok = string_type() ) const;\r
+\r
+ protected:\r
+ \r
+ void Init();\r
+\r
+ virtual void InitCharSets() = 0;\r
+ virtual void InitFun() = 0;\r
+ virtual void InitConst() = 0;\r
+ virtual void InitOprt() = 0; \r
+\r
+ virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);\r
+\r
+ static const char_type *c_DefaultOprt[]; \r
+ static std::locale s_locale; ///< The locale used by the parser\r
+ static bool g_DbgDumpCmdCode;\r
+ static bool g_DbgDumpStack;\r
+\r
+ /** \brief A facet class used to change decimal and thousands separator. */\r
+ template<class TChar>\r
+ class change_dec_sep : public std::numpunct<TChar>\r
+ {\r
+ public:\r
+ \r
+ explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
+ :std::numpunct<TChar>()\r
+ ,m_nGroup(nGroup)\r
+ ,m_cDecPoint(cDecSep)\r
+ ,m_cThousandsSep(cThousandsSep)\r
+ {}\r
+ \r
+ protected:\r
+ \r
+ virtual char_type do_decimal_point() const\r
+ {\r
+ return m_cDecPoint;\r
+ }\r
+\r
+ virtual char_type do_thousands_sep() const\r
+ {\r
+ return m_cThousandsSep;\r
+ }\r
+\r
+ virtual std::string do_grouping() const \r
+ { \r
+ return std::string(1, m_nGroup); \r
+ }\r
+\r
+ private:\r
+\r
+ int m_nGroup;\r
+ char_type m_cDecPoint; \r
+ char_type m_cThousandsSep;\r
+ };\r
+\r
+ private:\r
+\r
+ void Assign(const ParserBase &a_Parser);\r
+ void InitTokenReader();\r
+ void ReInit() const;\r
+\r
+ void AddCallback( const string_type &a_strName, \r
+ const ParserCallback &a_Callback, \r
+ funmap_type &a_Storage,\r
+ const char_type *a_szCharSet );\r
+\r
+ void ApplyRemainingOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+ void ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+\r
+ void ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const;\r
+\r
+ void ApplyFunc(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal, \r
+ int iArgCount) const; \r
+\r
+ token_type ApplyStrFunc(const token_type &a_FunTok,\r
+ const std::vector<token_type> &a_vArg) const;\r
+\r
+ int GetOprtPrecedence(const token_type &a_Tok) const;\r
+ EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;\r
+\r
+ void CreateRPN() const;\r
+\r
+ value_type ParseString() const; \r
+ value_type ParseCmdCode() const;\r
+ value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;\r
+\r
+ void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;\r
+ void CheckOprt(const string_type &a_sName,\r
+ const ParserCallback &a_Callback,\r
+ const string_type &a_szCharSet) const;\r
+\r
+ void StackDump(const ParserStack<token_type > &a_stVal, \r
+ const ParserStack<token_type > &a_stOprt) const;\r
+\r
+ /** \brief Pointer to the parser function. \r
+ \r
+ Eval() calls the function whose address is stored there.\r
+ */\r
+ mutable ParseFunction m_pParseFormula;\r
+ mutable ParserByteCode m_vRPN; ///< The Bytecode class.\r
+ mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments\r
+ stringbuf_type m_vStringVarBuf;\r
+\r
+ std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.\r
+\r
+ funmap_type m_FunDef; ///< Map of function names and pointers.\r
+ funmap_type m_PostOprtDef; ///< Postfix operator callbacks\r
+ funmap_type m_InfixOprtDef; ///< unary infix operator.\r
+ funmap_type m_OprtDef; ///< Binary operator callbacks\r
+ valmap_type m_ConstDef; ///< user constants.\r
+ strmap_type m_StrVarDef; ///< user defined string constants\r
+ varmap_type m_VarDef; ///< user defind variables.\r
+\r
+ bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off\r
+\r
+ string_type m_sNameChars; ///< Charset for names\r
+ string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens\r
+ string_type m_sInfixOprtChars; ///< Charset for infix operator tokens\r
+ \r
+ mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses\r
+\r
+ // items merely used for caching state information\r
+ mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine\r
+ mutable int m_nFinalResultIdx;\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_BYTECODE_H\r
+#define MU_PARSER_BYTECODE_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file\r
+ \brief Definition of the parser bytecode class.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ struct SToken\r
+ {\r
+ ECmdCode Cmd;\r
+ int StackPos;\r
+\r
+ union u\r
+ {\r
+ struct sVal\r
+ {\r
+ value_type *ptr;\r
+ value_type data;\r
+ value_type data2;\r
+ } Val;\r
+\r
+ struct sFun\r
+ {\r
+ // Note: generic_fun_type is merely a placeholder. The real type could be \r
+ // anything between gun_type1 and fun_type9. I can't use a void\r
+ // pointer due to constraints in the ANSI standard which allows\r
+ // data pointers and function pointers to differ in size.\r
+ generic_fun_type ptr;\r
+ int argc;\r
+ int idx;\r
+ } Fun;\r
+\r
+ struct sOprt\r
+ {\r
+ value_type *ptr;\r
+ int offset;\r
+ } Oprt;\r
+ } u;\r
+ };\r
+ \r
+ \r
+ /** \brief Bytecode implementation of the Math Parser.\r
+\r
+ The bytecode contains the formula converted to revers polish notation stored in a continious\r
+ memory area. Associated with this data are operator codes, variable pointers, constant \r
+ values and function pointers. Those are necessary in order to calculate the result.\r
+ All those data items will be casted to the underlying datatype of the bytecode.\r
+\r
+ \author (C) 2004-2013 Ingo Berg \r
+*/\r
+class ParserByteCode\r
+{\r
+private:\r
+\r
+ /** \brief Token type for internal use only. */\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ /** \brief Token vector for storing the RPN. */\r
+ typedef std::vector<SToken> rpn_type;\r
+\r
+ /** \brief Position in the Calculation array. */\r
+ unsigned m_iStackPos;\r
+\r
+ /** \brief Maximum size needed for the stack. */\r
+ std::size_t m_iMaxStackSize;\r
+ \r
+ /** \brief The actual rpn storage. */\r
+ rpn_type m_vRPN;\r
+\r
+ bool m_bEnableOptimizer;\r
+\r
+ void ConstantFolding(ECmdCode a_Oprt);\r
+\r
+public:\r
+\r
+ ParserByteCode();\r
+ ParserByteCode(const ParserByteCode &a_ByteCode);\r
+ ParserByteCode& operator=(const ParserByteCode &a_ByteCode);\r
+ void Assign(const ParserByteCode &a_ByteCode);\r
+\r
+ void AddVar(value_type *a_pVar);\r
+ void AddVal(value_type a_fVal);\r
+ void AddOp(ECmdCode a_Oprt);\r
+ void AddIfElse(ECmdCode a_Oprt);\r
+ void AddAssignOp(value_type *a_pVar);\r
+ void AddFun(generic_fun_type a_pFun, int a_iArgc);\r
+ void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);\r
+ void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);\r
+\r
+ void EnableOptimizer(bool bStat);\r
+\r
+ void Finalize();\r
+ void clear();\r
+ std::size_t GetMaxStackSize() const;\r
+ std::size_t GetSize() const;\r
+\r
+ const SToken* GetBase() const;\r
+ void AsciiDump();\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_CALLBACK_H\r
+#define MU_PARSER_CALLBACK_H\r
+\r
+#include "muParserDef.h"\r
+\r
+/** \file\r
+ \brief Definition of the parser callback class.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Encapsulation of prototypes for a numerical parser function.\r
+\r
+ Encapsulates the prototyp for numerical parser functions. The class\r
+ stores the number of arguments for parser functions as well\r
+ as additional flags indication the function is non optimizeable.\r
+ The pointer to the callback function pointer is stored as void* \r
+ and needs to be casted according to the argument count.\r
+ Negative argument counts indicate a parser function with a variable number\r
+ of arguments. \r
+\r
+ \author (C) 2004-2011 Ingo Berg\r
+*/\r
+class ParserCallback\r
+{\r
+public:\r
+ ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);\r
+ ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity);\r
+ ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti);\r
+\r
+ ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti);\r
+\r
+ ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);\r
+ ParserCallback();\r
+ ParserCallback(const ParserCallback &a_Fun);\r
+ \r
+ ParserCallback* Clone() const;\r
+\r
+ bool IsOptimizable() const;\r
+ void* GetAddr() const;\r
+ ECmdCode GetCode() const;\r
+ ETypeCode GetType() const;\r
+ int GetPri() const;\r
+ EOprtAssociativity GetAssociativity() const;\r
+ int GetArgc() const;\r
+\r
+private:\r
+ void *m_pFun; ///< Pointer to the callback function, casted to void\r
+ \r
+ /** \brief Number of numeric function arguments\r
+ \r
+ This number is negative for functions with variable number of arguments. in this cases\r
+ they represent the actual number of arguments found.\r
+ */\r
+ int m_iArgc; \r
+ int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.\r
+ EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators \r
+ ECmdCode m_iCode;\r
+ ETypeCode m_iType;\r
+ bool m_bAllowOpti; ///< Flag indication optimizeability \r
+};\r
+\r
+//------------------------------------------------------------------------------\r
+/** \brief Container for Callback objects. */\r
+typedef std::map<string_type, ParserCallback> funmap_type; \r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MU_PARSER_DLL_H\r
+#define MU_PARSER_DLL_H\r
+\r
+#if defined(WIN32) || defined(_WIN32)\r
+ #ifdef MUPARSERLIB_EXPORTS\r
+ #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl\r
+ #else\r
+ #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl\r
+ #endif\r
+#else\r
+ #define API_EXPORT(TYPE) TYPE\r
+#endif\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+/** \file \r
+ \brief This file contains the DLL interface of muparser.\r
+*/\r
+\r
+// Basic types\r
+typedef void* muParserHandle_t; // parser handle\r
+typedef char muChar_t; // character type\r
+typedef int muBool_t; // boolean type\r
+typedef int muInt_t; // integer type \r
+typedef double muFloat_t; // floating point type\r
+\r
+// function types for calculation\r
+typedef muFloat_t (*muFun0_t )(); \r
+typedef muFloat_t (*muFun1_t )(muFloat_t); \r
+typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+\r
+// Function prototypes for bulkmode functions\r
+typedef muFloat_t (*muBulkFun0_t )(int, int); \r
+typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); \r
+typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); \r
+\r
+typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t);\r
+typedef muFloat_t (*muStrFun1_t)(const muChar_t*);\r
+typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t);\r
+typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t);\r
+\r
+// Functions for parser management\r
+typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler\r
+typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables\r
+typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+// Constants\r
+static const int muOPRT_ASCT_LEFT = 0;\r
+static const int muOPRT_ASCT_RIGHT = 1;\r
+\r
+static const int muBASETYPE_FLOAT = 0;\r
+static const int muBASETYPE_INT = 1;\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+//\r
+//\r
+// muParser C compatible bindings\r
+//\r
+//\r
+//-----------------------------------------------------------------------------------------------------\r
+\r
+\r
+// Basic operations / initialization \r
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType);\r
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser);\r
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr);\r
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData);\r
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser);\r
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser);\r
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum);\r
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize);\r
+\r
+// Defining callbacks / variables / constants\r
+API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize);\r
+API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize);\r
+\r
+// Defining bulkmode functions\r
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun);\r
+API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun);\r
+\r
+// string functions\r
+API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun);\r
+API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun);\r
+API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun);\r
+\r
+API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muMultFun_t a_pFun, \r
+ muBool_t a_bOptimize);\r
+\r
+API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muInt_t a_nPrec, \r
+ muInt_t a_nOprtAsct,\r
+ muBool_t a_bOptimize);\r
+\r
+API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t a_fVal );\r
+\r
+API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ const muChar_t *a_sVal );\r
+\r
+API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t *a_fVar);\r
+\r
+API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFloat_t *a_fVar);\r
+\r
+API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pOprt, \r
+ muBool_t a_bOptimize);\r
+\r
+\r
+API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pOprt, \r
+ muBool_t a_bOptimize);\r
+\r
+// Define character sets for identifiers\r
+API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset);\r
+\r
+// Remove all / single variables\r
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName);\r
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser);\r
+\r
+// Querying variables / expression variables / constants\r
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser);\r
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser);\r
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);\r
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar);\r
+API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar);\r
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep);\r
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser);\r
+\r
+// Add value recognition callbacks\r
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t);\r
+\r
+// Error handling\r
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser);\r
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler);\r
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser);\r
+API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser);\r
+API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser);\r
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser);\r
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser);\r
+\r
+// This is used for .NET only. It creates a new variable allowing the dll to\r
+// manage the variable rather than the .NET garbage collector.\r
+API_EXPORT(muFloat_t*) mupCreateVar();\r
+API_EXPORT(void) mupReleaseVar(muFloat_t*);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // include guard\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#ifndef MUP_DEF_H\r
+#define MUP_DEF_H\r
+\r
+#include <iostream>\r
+#include <string>\r
+#include <sstream>\r
+#include <map>\r
+\r
+#include "muParserFixes.h"\r
+\r
+/** \file\r
+ \brief This file contains standard definitions used by the parser.\r
+*/\r
+\r
+#define MUP_VERSION _T("2.2.3")\r
+#define MUP_VERSION_DATE _T("20121222; SF")\r
+\r
+#define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")\r
+\r
+/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */\r
+//#define MUP_MATH_EXCEPTIONS\r
+\r
+/** \brief Define the base datatype for values.\r
+\r
+ This datatype must be a built in value type. You can not use custom classes.\r
+ It should be working with all types except "int"!\r
+*/\r
+#define MUP_BASETYPE double\r
+\r
+/** \brief Activate this option in order to compile with OpenMP support. \r
+\r
+ OpenMP is used only in the bulk mode it may increase the performance a bit. \r
+*/\r
+//#define MUP_USE_OPENMP\r
+\r
+#if defined(_UNICODE)\r
+ /** \brief Definition of the basic parser string type. */\r
+ #define MUP_STRING_TYPE std::wstring\r
+\r
+ #if !defined(_T)\r
+ #define _T(x) L##x\r
+ #endif // not defined _T\r
+#else\r
+ #ifndef _T\r
+ #define _T(x) x\r
+ #endif\r
+ \r
+ /** \brief Definition of the basic parser string type. */\r
+ #define MUP_STRING_TYPE std::string\r
+#endif\r
+\r
+#if defined(_DEBUG)\r
+ /** \brief Debug macro to force an abortion of the programm with a certain message.\r
+ */\r
+ #define MUP_FAIL(MSG) \\r
+ { \\r
+ bool MSG=false; \\r
+ assert(MSG); \\r
+ }\r
+\r
+ /** \brief An assertion that does not kill the program.\r
+\r
+ This macro is neutralised in UNICODE builds. It's\r
+ too difficult to translate.\r
+ */\r
+ #define MUP_ASSERT(COND) \\r
+ if (!(COND)) \\r
+ { \\r
+ stringstream_type ss; \\r
+ ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \\r
+ << __FILE__ << _T(" line ") \\r
+ << __LINE__ << _T("."); \\r
+ throw ParserError( ss.str() ); \\r
+ }\r
+#else\r
+ #define MUP_FAIL(MSG)\r
+ #define MUP_ASSERT(COND)\r
+#endif\r
+\r
+\r
+namespace mu\r
+{\r
+#if defined(_UNICODE)\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Encapsulate wcout. */\r
+ inline std::wostream& console()\r
+ {\r
+ return std::wcout;\r
+ }\r
+\r
+ /** \brief Encapsulate cin. */\r
+ inline std::wistream& console_in()\r
+ {\r
+ return std::wcin;\r
+ }\r
+\r
+#else\r
+\r
+ /** \brief Encapsulate cout. \r
+ \r
+ Used for supporting UNICODE more easily.\r
+ */\r
+ inline std::ostream& console()\r
+ {\r
+ return std::cout;\r
+ }\r
+\r
+ /** \brief Encapsulate cin. \r
+\r
+ Used for supporting UNICODE more easily.\r
+ */\r
+ inline std::istream& console_in()\r
+ {\r
+ return std::cin;\r
+ }\r
+\r
+#endif\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Bytecode values.\r
+\r
+ \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!\r
+ */\r
+ enum ECmdCode\r
+ {\r
+ // The following are codes for built in binary operators\r
+ // apart from built in operators the user has the opportunity to\r
+ // add user defined operators.\r
+ cmLE = 0, ///< Operator item: less or equal\r
+ cmGE = 1, ///< Operator item: greater or equal\r
+ cmNEQ = 2, ///< Operator item: not equal\r
+ cmEQ = 3, ///< Operator item: equals\r
+ cmLT = 4, ///< Operator item: less than\r
+ cmGT = 5, ///< Operator item: greater than\r
+ cmADD = 6, ///< Operator item: add\r
+ cmSUB = 7, ///< Operator item: subtract\r
+ cmMUL = 8, ///< Operator item: multiply\r
+ cmDIV = 9, ///< Operator item: division\r
+ cmPOW = 10, ///< Operator item: y to the power of ...\r
+ cmLAND = 11,\r
+ cmLOR = 12,\r
+ cmASSIGN = 13, ///< Operator item: Assignment operator\r
+ cmBO = 14, ///< Operator item: opening bracket\r
+ cmBC = 15, ///< Operator item: closing bracket\r
+ cmIF = 16, ///< For use in the ternary if-then-else operator\r
+ cmELSE = 17, ///< For use in the ternary if-then-else operator\r
+ cmENDIF = 18, ///< For use in the ternary if-then-else operator\r
+ cmARG_SEP = 19, ///< function argument separator\r
+ cmVAR = 20, ///< variable item\r
+ cmVAL = 21, ///< value item\r
+\r
+ // For optimization purposes\r
+ cmVARPOW2,\r
+ cmVARPOW3,\r
+ cmVARPOW4,\r
+ cmVARMUL,\r
+ cmPOW2,\r
+\r
+ // operators and functions\r
+ cmFUNC, ///< Code for a generic function item\r
+ cmFUNC_STR, ///< Code for a function with a string parameter\r
+ cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index \r
+ cmSTRING, ///< Code for a string token\r
+ cmOPRT_BIN, ///< user defined binary operator\r
+ cmOPRT_POSTFIX, ///< code for postfix operators\r
+ cmOPRT_INFIX, ///< code for infix operators\r
+ cmEND, ///< end of formula\r
+ cmUNKNOWN ///< uninitialized item\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Types internally used by the parser.\r
+ */\r
+ enum ETypeCode\r
+ {\r
+ tpSTR = 0, ///< String type (Function arguments and constants only, no string variables)\r
+ tpDBL = 1, ///< Floating point variables\r
+ tpVOID = 2 ///< Undefined type.\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ enum EParserVersionInfo\r
+ {\r
+ pviBRIEF,\r
+ pviFULL\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Parser operator precedence values. */\r
+ enum EOprtAssociativity\r
+ {\r
+ oaLEFT = 0,\r
+ oaRIGHT = 1,\r
+ oaNONE = 2\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Parser operator precedence values. */\r
+ enum EOprtPrecedence\r
+ {\r
+ // binary operators\r
+ prLOR = 1,\r
+ prLAND = 2,\r
+ prLOGIC = 3, ///< logic operators\r
+ prCMP = 4, ///< comparsion operators\r
+ prADD_SUB = 5, ///< addition\r
+ prMUL_DIV = 6, ///< multiplication/division\r
+ prPOW = 7, ///< power operator priority (highest)\r
+\r
+ // infix operators\r
+ prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator\r
+ prPOSTFIX = 6 ///< Postfix operator priority (currently unused)\r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ // basic types\r
+\r
+ /** \brief The numeric datatype used by the parser. \r
+ \r
+ Normally this is a floating point type either single or double precision.\r
+ */\r
+ typedef MUP_BASETYPE value_type;\r
+\r
+ /** \brief The stringtype used by the parser. \r
+\r
+ Depends on wether UNICODE is used or not.\r
+ */\r
+ typedef MUP_STRING_TYPE string_type;\r
+\r
+ /** \brief The character type used by the parser. \r
+ \r
+ Depends on wether UNICODE is used or not.\r
+ */\r
+ typedef string_type::value_type char_type;\r
+\r
+ /** \brief Typedef for easily using stringstream that respect the parser stringtype. */\r
+ typedef std::basic_stringstream<char_type,\r
+ std::char_traits<char_type>,\r
+ std::allocator<char_type> > stringstream_type;\r
+\r
+ // Data container types\r
+\r
+ /** \brief Type used for storing variables. */\r
+ typedef std::map<string_type, value_type*> varmap_type;\r
+ \r
+ /** \brief Type used for storing constants. */\r
+ typedef std::map<string_type, value_type> valmap_type;\r
+ \r
+ /** \brief Type for assigning a string name to an index in the internal string table. */\r
+ typedef std::map<string_type, std::size_t> strmap_type;\r
+\r
+ // Parser callbacks\r
+ \r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*generic_fun_type)();\r
+\r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*fun_type0)();\r
+\r
+ /** \brief Callback type used for functions with a single arguments. */\r
+ typedef value_type (*fun_type1)(value_type);\r
+\r
+ /** \brief Callback type used for functions with two arguments. */\r
+ typedef value_type (*fun_type2)(value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with three arguments. */\r
+ typedef value_type (*fun_type3)(value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with four arguments. */\r
+ typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions without arguments. */\r
+ typedef value_type (*bulkfun_type0)(int, int);\r
+\r
+ /** \brief Callback type used for functions with a single arguments. */\r
+ typedef value_type (*bulkfun_type1)(int, int, value_type);\r
+\r
+ /** \brief Callback type used for functions with two arguments. */\r
+ typedef value_type (*bulkfun_type2)(int, int, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with three arguments. */\r
+ typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with four arguments. */\r
+ typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with five arguments. */\r
+ typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type);\r
+\r
+ /** \brief Callback type used for functions with a variable argument list. */\r
+ typedef value_type (*multfun_type)(const value_type*, int);\r
+\r
+ /** \brief Callback type used for functions taking a string as an argument. */\r
+ typedef value_type (*strfun_type1)(const char_type*);\r
+\r
+ /** \brief Callback type used for functions taking a string and a value as arguments. */\r
+ typedef value_type (*strfun_type2)(const char_type*, value_type);\r
+\r
+ /** \brief Callback type used for functions taking a string and two values as arguments. */\r
+ typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);\r
+\r
+ /** \brief Callback used for functions that identify values in a string. */\r
+ typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal);\r
+\r
+ /** \brief Callback used for variable creation factory functions. */\r
+ typedef value_type* (*facfun_type)(const char_type*, void*);\r
+} // end of namespace\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_ERROR_H\r
+#define MU_PARSER_ERROR_H\r
+\r
+#include <cassert>\r
+#include <stdexcept>\r
+#include <string>\r
+#include <sstream>\r
+#include <vector>\r
+#include <memory>\r
+\r
+#include "muParserDef.h"\r
+\r
+/** \file \r
+ \brief This file defines the error class used by the parser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Error codes. */\r
+enum EErrorCodes\r
+{\r
+ // Formula syntax errors\r
+ ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found\r
+ ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.\r
+ ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(")\r
+ ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23")\r
+ ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found\r
+ ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found\r
+ ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found\r
+ ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing\r
+ ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position\r
+ ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument\r
+ ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument\r
+ ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3")\r
+ ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")\r
+ ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")\r
+ ecTOO_MANY_PARAMS = 14, ///< Too many function parameters\r
+ ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")\r
+ ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type\r
+ ecSTR_RESULT = 17, ///< result is a string\r
+\r
+ // Invalid Parser input Parameters\r
+ ecINVALID_NAME = 18, ///< Invalid function, variable or constant name.\r
+ ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier\r
+ ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name.\r
+ ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name.\r
+\r
+ ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator\r
+ ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer \r
+ ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer \r
+ ecEMPTY_EXPRESSION = 25, ///< The Expression is empty\r
+ ecNAME_CONFLICT = 26, ///< Name conflict\r
+ ecOPT_PRI = 27, ///< Invalid operator priority\r
+ // \r
+ ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused)\r
+ ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused)\r
+ ecGENERIC = 30, ///< Generic error\r
+ ecLOCALE = 31, ///< Conflict with current locale\r
+\r
+ ecUNEXPECTED_CONDITIONAL = 32,\r
+ ecMISSING_ELSE_CLAUSE = 33, \r
+ ecMISPLACED_COLON = 34,\r
+\r
+ // internal errors\r
+ ecINTERNAL_ERROR = 35, ///< Internal error of any kind.\r
+ \r
+ // The last two are special entries \r
+ ecCOUNT, ///< This is no error code, It just stores just the total number of error codes\r
+ ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages\r
+};\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief A class that handles the error messages.\r
+*/\r
+class ParserErrorMsg\r
+{\r
+public:\r
+ typedef ParserErrorMsg self_type;\r
+\r
+ ParserErrorMsg& operator=(const ParserErrorMsg &);\r
+ ParserErrorMsg(const ParserErrorMsg&);\r
+ ParserErrorMsg();\r
+\r
+ ~ParserErrorMsg();\r
+\r
+ static const ParserErrorMsg& Instance();\r
+ string_type operator[](unsigned a_iIdx) const;\r
+\r
+private:\r
+ std::vector<string_type> m_vErrMsg; ///< A vector with the predefined error messages\r
+ static const self_type m_Instance; ///< The instance pointer\r
+};\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Error class of the parser. \r
+ \author Ingo Berg\r
+\r
+ Part of the math parser package.\r
+*/\r
+class ParserError\r
+{\r
+private:\r
+\r
+ /** \brief Replace all ocuurences of a substring with another string. */\r
+ void ReplaceSubString( string_type &strSource, \r
+ const string_type &strFind,\r
+ const string_type &strReplaceWith);\r
+ void Reset();\r
+\r
+public:\r
+\r
+ ParserError();\r
+ explicit ParserError(EErrorCodes a_iErrc);\r
+ explicit ParserError(const string_type &sMsg);\r
+ ParserError( EErrorCodes a_iErrc,\r
+ const string_type &sTok,\r
+ const string_type &sFormula = string_type(),\r
+ int a_iPos = -1);\r
+ ParserError( EErrorCodes a_iErrc, \r
+ int a_iPos, \r
+ const string_type &sTok);\r
+ ParserError( const char_type *a_szMsg, \r
+ int a_iPos = -1, \r
+ const string_type &sTok = string_type());\r
+ ParserError(const ParserError &a_Obj);\r
+ ParserError& operator=(const ParserError &a_Obj);\r
+ ~ParserError();\r
+\r
+ void SetFormula(const string_type &a_strFormula);\r
+ const string_type& GetExpr() const;\r
+ const string_type& GetMsg() const;\r
+ std::size_t GetPos() const;\r
+ const string_type& GetToken() const;\r
+ EErrorCodes GetCode() const;\r
+\r
+private:\r
+ string_type m_strMsg; ///< The message string\r
+ string_type m_strFormula; ///< Formula string\r
+ string_type m_strTok; ///< Token related with the error\r
+ int m_iPos; ///< Formula position related to the error \r
+ EErrorCodes m_iErrc; ///< Error code\r
+ const ParserErrorMsg &m_ErrMsg;\r
+}; \r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_FIXES_H\r
+#define MU_PARSER_FIXES_H\r
+\r
+/** \file\r
+ \brief This file contains compatibility fixes for some platforms.\r
+*/\r
+\r
+//\r
+// Compatibility fixes\r
+//\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+// Intel Compiler\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+#ifdef __INTEL_COMPILER\r
+\r
+// remark #981: operands are evaluated in unspecified order\r
+// disabled -> completely pointless if the functions do not have side effects\r
+//\r
+#pragma warning(disable:981)\r
+\r
+// remark #383: value copied to temporary, reference to temporary used\r
+#pragma warning(disable:383)\r
+\r
+// remark #1572: floating-point equality and inequality comparisons are unreliable\r
+// disabled -> everyone knows it, the parser passes this problem\r
+// deliberately to the user\r
+#pragma warning(disable:1572)\r
+\r
+#endif\r
+\r
+#endif // include guard\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_INT_H\r
+#define MU_PARSER_INT_H\r
+\r
+#include "muParserBase.h"\r
+#include <vector>\r
+\r
+\r
+/** \file\r
+ \brief Definition of a parser using integer value.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+\r
+/** \brief Mathematical expressions parser.\r
+ \r
+ This version of the parser handles only integer numbers. It disables the built in operators thus it is \r
+ slower than muParser. Integer values are stored in the double value_type and converted if needed.\r
+*/\r
+class ParserInt : public ParserBase\r
+{\r
+private:\r
+ static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };\r
+ \r
+ static value_type Abs(value_type);\r
+ static value_type Sign(value_type);\r
+ static value_type Ite(value_type, value_type, value_type);\r
+ // !! The unary Minus is a MUST, otherwise you cant use negative signs !!\r
+ static value_type UnaryMinus(value_type);\r
+ // Functions with variable number of arguments\r
+ static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum\r
+ static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum\r
+ static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum\r
+ // binary operator callbacks\r
+ static value_type Add(value_type v1, value_type v2);\r
+ static value_type Sub(value_type v1, value_type v2);\r
+ static value_type Mul(value_type v1, value_type v2);\r
+ static value_type Div(value_type v1, value_type v2);\r
+ static value_type Mod(value_type v1, value_type v2);\r
+ static value_type Pow(value_type v1, value_type v2);\r
+ static value_type Shr(value_type v1, value_type v2);\r
+ static value_type Shl(value_type v1, value_type v2);\r
+ static value_type LogAnd(value_type v1, value_type v2);\r
+ static value_type LogOr(value_type v1, value_type v2);\r
+ static value_type And(value_type v1, value_type v2);\r
+ static value_type Or(value_type v1, value_type v2);\r
+ static value_type Xor(value_type v1, value_type v2);\r
+ static value_type Less(value_type v1, value_type v2);\r
+ static value_type Greater(value_type v1, value_type v2);\r
+ static value_type LessEq(value_type v1, value_type v2);\r
+ static value_type GreaterEq(value_type v1, value_type v2);\r
+ static value_type Equal(value_type v1, value_type v2);\r
+ static value_type NotEqual(value_type v1, value_type v2);\r
+ static value_type Not(value_type v1);\r
+\r
+ static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+ static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+ static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal);\r
+\r
+ /** \brief A facet class used to change decimal and thousands separator. */\r
+ template<class TChar>\r
+ class change_dec_sep : public std::numpunct<TChar>\r
+ {\r
+ public:\r
+ \r
+ explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)\r
+ :std::numpunct<TChar>()\r
+ ,m_cDecPoint(cDecSep)\r
+ ,m_cThousandsSep(cThousandsSep)\r
+ ,m_nGroup(nGroup)\r
+ {}\r
+ \r
+ protected:\r
+ \r
+ virtual char_type do_decimal_point() const\r
+ {\r
+ return m_cDecPoint;\r
+ }\r
+\r
+ virtual char_type do_thousands_sep() const\r
+ {\r
+ return m_cThousandsSep;\r
+ }\r
+\r
+ virtual std::string do_grouping() const \r
+ { \r
+ return std::string(1, m_nGroup); \r
+ }\r
+\r
+ private:\r
+\r
+ int m_nGroup;\r
+ char_type m_cDecPoint; \r
+ char_type m_cThousandsSep;\r
+ };\r
+\r
+public:\r
+ ParserInt();\r
+\r
+ virtual void InitFun();\r
+ virtual void InitOprt();\r
+ virtual void InitConst();\r
+ virtual void InitCharSets();\r
+};\r
+\r
+} // namespace mu\r
+\r
+#endif\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_STACK_H\r
+#define MU_PARSER_STACK_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file \r
+ \brief This file defines the stack used by muparser.\r
+*/\r
+\r
+namespace mu\r
+{\r
+\r
+ /** \brief Parser stack implementation. \r
+\r
+ Stack implementation based on a std::stack. The behaviour of pop() had been\r
+ slightly changed in order to get an error code if the stack is empty.\r
+ The stack is used within the Parser both as a value stack and as an operator stack.\r
+\r
+ \author (C) 2004-2011 Ingo Berg \r
+ */\r
+ template <typename TValueType>\r
+ class ParserStack \r
+ {\r
+ private:\r
+\r
+ /** \brief Type of the underlying stack implementation. */\r
+ typedef std::stack<TValueType, std::vector<TValueType> > impl_type;\r
+ \r
+ impl_type m_Stack; ///< This is the actual stack.\r
+\r
+ public: \r
+ \r
+ //---------------------------------------------------------------------------\r
+ ParserStack()\r
+ :m_Stack()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ virtual ~ParserStack()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Pop a value from the stack.\r
+ \r
+ Unlike the standard implementation this function will return the value that\r
+ is going to be taken from the stack.\r
+\r
+ \throw ParserException in case the stack is empty.\r
+ \sa pop(int &a_iErrc)\r
+ */\r
+ TValueType pop()\r
+ {\r
+ if (empty())\r
+ throw ParserError( _T("stack is empty.") );\r
+\r
+ TValueType el = top();\r
+ m_Stack.pop();\r
+ return el;\r
+ }\r
+\r
+ /** \brief Push an object into the stack. \r
+\r
+ \param a_Val object to push into the stack.\r
+ \throw nothrow\r
+ */\r
+ void push(const TValueType& a_Val) \r
+ { \r
+ m_Stack.push(a_Val); \r
+ }\r
+\r
+ /** \brief Return the number of stored elements. */\r
+ unsigned size() const\r
+ { \r
+ return (unsigned)m_Stack.size(); \r
+ }\r
+\r
+ /** \brief Returns true if stack is empty false otherwise. */\r
+ bool empty() const\r
+ {\r
+ return m_Stack.size()==0; \r
+ }\r
+ \r
+ /** \brief Return reference to the top object in the stack. \r
+ \r
+ The top object is the one pushed most recently.\r
+ */\r
+ TValueType& top() \r
+ { \r
+ return m_Stack.top(); \r
+ }\r
+ };\r
+} // namespace MathUtils\r
+\r
+#endif\r
--- /dev/null
+#ifndef MU_PARSER_TEMPLATE_MAGIC_H\r
+#define MU_PARSER_TEMPLATE_MAGIC_H\r
+\r
+#include <cmath>\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ //-----------------------------------------------------------------------------------------------\r
+ //\r
+ // Compile time type detection\r
+ //\r
+ //-----------------------------------------------------------------------------------------------\r
+\r
+ /** \brief A class singling out integer types at compile time using \r
+ template meta programming.\r
+ */\r
+ template<typename T>\r
+ struct TypeInfo\r
+ {\r
+ static bool IsInteger() { return false; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<char>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<short>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<int>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<long>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned char>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned short>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned int>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+ template<>\r
+ struct TypeInfo<unsigned long>\r
+ {\r
+ static bool IsInteger() { return true; }\r
+ };\r
+\r
+\r
+ //-----------------------------------------------------------------------------------------------\r
+ //\r
+ // Standard math functions with dummy overload for integer types\r
+ //\r
+ //-----------------------------------------------------------------------------------------------\r
+\r
+ /** \brief A template class for providing wrappers for essential math functions.\r
+\r
+ This template is spezialized for several types in order to provide a unified interface\r
+ for parser internal math function calls regardless of the data type.\r
+ */\r
+ template<typename T>\r
+ struct MathImpl\r
+ {\r
+ static T Sin(T v) { return sin(v); }\r
+ static T Cos(T v) { return cos(v); }\r
+ static T Tan(T v) { return tan(v); }\r
+ static T ASin(T v) { return asin(v); }\r
+ static T ACos(T v) { return acos(v); }\r
+ static T ATan(T v) { return atan(v); }\r
+ static T ATan2(T v1, T v2) { return atan2(v1, v2); }\r
+ static T Sinh(T v) { return sinh(v); }\r
+ static T Cosh(T v) { return cosh(v); }\r
+ static T Tanh(T v) { return tanh(v); }\r
+ static T ASinh(T v) { return log(v + sqrt(v * v + 1)); }\r
+ static T ACosh(T v) { return log(v + sqrt(v * v - 1)); }\r
+ static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); }\r
+ static T Log(T v) { return log(v); } \r
+ static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2\r
+ static T Log10(T v) { return log10(v); } // Logarithm base 10\r
+ static T Exp(T v) { return exp(v); }\r
+ static T Abs(T v) { return (v>=0) ? v : -v; }\r
+ static T Sqrt(T v) { return sqrt(v); }\r
+ static T Rint(T v) { return floor(v + (T)0.5); }\r
+ static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); }\r
+ static T Pow(T v1, T v2) { return std::pow(v1, v2); }\r
+ };\r
+\r
+ // Create (mostly) dummy math function definitions for integer types. They are mostly\r
+ // empty since they are not applicable for integer values.\r
+#define MAKE_MATH_DUMMY(TYPE) \\r
+ template<> \\r
+ struct MathImpl<TYPE> \\r
+ { \\r
+ static TYPE Sin(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Cos(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Tan(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ASin(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ACos(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATan(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATan2(TYPE, TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sinh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Cosh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Tanh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ASinh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ACosh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE ATanh(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log2(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Log10(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Exp(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Abs(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sqrt(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Rint(TYPE) { throw ParserError(_T("unimplemented function.")); } \\r
+ static TYPE Sign(TYPE v) { return (TYPE)((v<0) ? -1 : (v>0) ? 1 : 0); } \\r
+ static TYPE Pow(TYPE v1, TYPE v2) { return (TYPE)std::pow((double)v1, (double)v2); } \\r
+ };\r
+\r
+ MAKE_MATH_DUMMY(char)\r
+ MAKE_MATH_DUMMY(short)\r
+ MAKE_MATH_DUMMY(int)\r
+ MAKE_MATH_DUMMY(long)\r
+\r
+#undef MAKE_MATH_DUMMY\r
+}\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TEST_H\r
+#define MU_PARSER_TEST_H\r
+\r
+#include <string>\r
+#include <cstdlib>\r
+#include <numeric> // for accumulate\r
+#include "muParser.h"\r
+#include "muParserInt.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser test class.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Namespace for test cases. */\r
+ namespace Test\r
+ {\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Test cases for unit testing.\r
+\r
+ (C) 2004-2011 Ingo Berg\r
+ */\r
+ class ParserTester // final\r
+ {\r
+ private:\r
+ static int c_iCount;\r
+\r
+ // Multiarg callbacks\r
+ static value_type f1of1(value_type v) { return v;};\r
+ \r
+ static value_type f1of2(value_type v, value_type ) {return v;};\r
+ static value_type f2of2(value_type , value_type v) {return v;};\r
+\r
+ static value_type f1of3(value_type v, value_type , value_type ) {return v;};\r
+ static value_type f2of3(value_type , value_type v, value_type ) {return v;};\r
+ static value_type f3of3(value_type , value_type , value_type v) {return v;};\r
+ \r
+ static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;}\r
+ static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;}\r
+ static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;}\r
+ static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;}\r
+\r
+ static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; }\r
+ static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; }\r
+ static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; }\r
+ static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; }\r
+ static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; }\r
+\r
+ static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }\r
+ static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }\r
+\r
+ static value_type plus2(value_type v1) { return v1+2; }\r
+ static value_type times3(value_type v1) { return v1*3; }\r
+ static value_type sqr(value_type v1) { return v1*v1; }\r
+ static value_type sign(value_type v) { return -v; }\r
+ static value_type add(value_type v1, value_type v2) { return v1+v2; }\r
+ static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; }\r
+ \r
+\r
+ static value_type FirstArg(const value_type* a_afArg, int a_iArgc)\r
+ {\r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") );\r
+\r
+ return a_afArg[0];\r
+ }\r
+\r
+ static value_type LastArg(const value_type* a_afArg, int a_iArgc)\r
+ {\r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") );\r
+\r
+ return a_afArg[a_iArgc-1];\r
+ }\r
+\r
+ static value_type Sum(const value_type* a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw mu::Parser::exception_type( _T("too few arguments for function sum.") );\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes;\r
+ }\r
+\r
+ static value_type Rnd(value_type v)\r
+ {\r
+ return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));\r
+ }\r
+\r
+ static value_type RndWithString(const char_type*)\r
+ {\r
+ return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );\r
+ }\r
+\r
+ static value_type Ping()\r
+ { \r
+ return 10; \r
+ }\r
+\r
+ static value_type ValueOf(const char_type*) \r
+ { \r
+ return 123; \r
+ }\r
+\r
+ static value_type StrFun1(const char_type* v1) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return (value_type)val;\r
+ }\r
+\r
+ static value_type StrFun2(const char_type* v1, value_type v2) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return (value_type)(val + v2);\r
+ }\r
+ \r
+ static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) \r
+ { \r
+ int val(0);\r
+ stringstream_type(v1) >> val;\r
+ return val + v2 + v3;\r
+ }\r
+\r
+ static value_type StrToFloat(const char_type* a_szMsg)\r
+ {\r
+ value_type val(0);\r
+ stringstream_type(a_szMsg) >> val;\r
+ return val;\r
+ }\r
+\r
+ // postfix operator callback\r
+ static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; }\r
+ static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; }\r
+ static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; }\r
+\r
+ // Custom value recognition\r
+ static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal);\r
+\r
+ int TestNames();\r
+ int TestSyntax();\r
+ int TestMultiArg();\r
+ int TestPostFix();\r
+ int TestExpression();\r
+ int TestInfixOprt();\r
+ int TestBinOprt();\r
+ int TestVarConst();\r
+ int TestInterface();\r
+ int TestException();\r
+ int TestStrArg();\r
+ int TestIfThenElse();\r
+\r
+ void Abort() const;\r
+\r
+ public:\r
+ typedef int (ParserTester::*testfun_type)();\r
+\r
+ ParserTester();\r
+ void Run();\r
+\r
+ private:\r
+ std::vector<testfun_type> m_vTestFun;\r
+ void AddTest(testfun_type a_pFun);\r
+\r
+ // Test Double Parser\r
+ int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);\r
+ int EqnTestWithVarChange(const string_type& a_str, \r
+ double a_fRes1, \r
+ double a_fVar1, \r
+ double a_fRes2, \r
+ double a_fVar2);\r
+ int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);\r
+\r
+ // Test Int Parser\r
+ int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);\r
+ };\r
+ } // namespace Test\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TOKEN_H\r
+#define MU_PARSER_TOKEN_H\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+#include <memory>\r
+\r
+#include "muParserError.h"\r
+#include "muParserCallback.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token definition.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ /** \brief Encapsulation of the data for a single formula token. \r
+\r
+ Formula token implementation. Part of the Math Parser Package.\r
+ Formula tokens can be either one of the following:\r
+ <ul>\r
+ <li>value</li>\r
+ <li>variable</li>\r
+ <li>function with numerical arguments</li>\r
+ <li>functions with a string as argument</li>\r
+ <li>prefix operators</li>\r
+ <li>infix operators</li>\r
+ <li>binary operator</li>\r
+ </ul>\r
+\r
+ \author (C) 2004-2013 Ingo Berg \r
+ */\r
+ template<typename TBase, typename TString>\r
+ class ParserToken\r
+ {\r
+ private:\r
+\r
+ ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.\r
+ ETypeCode m_iType;\r
+ void *m_pTok; ///< Stores Token pointer; not applicable for all tokens\r
+ int m_iIdx; ///< An otional index to an external buffer storing the token data\r
+ TString m_strTok; ///< Token string\r
+ TString m_strVal; ///< Value for string variables\r
+ value_type m_fVal; ///< the value \r
+ std::auto_ptr<ParserCallback> m_pCallback;\r
+\r
+ public:\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor (default).\r
+ \r
+ Sets token to an neutral state of type cmUNKNOWN.\r
+ \throw nothrow\r
+ \sa ECmdCode\r
+ */\r
+ ParserToken()\r
+ :m_iCode(cmUNKNOWN)\r
+ ,m_iType(tpVOID)\r
+ ,m_pTok(0)\r
+ ,m_iIdx(-1)\r
+ ,m_strTok()\r
+ ,m_pCallback()\r
+ {}\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Create token from another one.\r
+ \r
+ Implemented by calling Assign(...)\r
+ \throw nothrow\r
+ \post m_iType==cmUNKNOWN\r
+ \sa #Assign\r
+ */\r
+ ParserToken(const ParserToken &a_Tok)\r
+ {\r
+ Assign(a_Tok);\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assignement operator. \r
+ \r
+ Copy token state from another token and return this.\r
+ Implemented by calling Assign(...).\r
+ \throw nothrow\r
+ */\r
+ ParserToken& operator=(const ParserToken &a_Tok)\r
+ {\r
+ Assign(a_Tok);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Copy token information from argument.\r
+ \r
+ \throw nothrow\r
+ */\r
+ void Assign(const ParserToken &a_Tok)\r
+ {\r
+ m_iCode = a_Tok.m_iCode;\r
+ m_pTok = a_Tok.m_pTok;\r
+ m_strTok = a_Tok.m_strTok;\r
+ m_iIdx = a_Tok.m_iIdx;\r
+ m_strVal = a_Tok.m_strVal;\r
+ m_iType = a_Tok.m_iType;\r
+ m_fVal = a_Tok.m_fVal;\r
+ // create new callback object if a_Tok has one \r
+ m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assign a token type. \r
+\r
+ Token may not be of type value, variable or function. Those have seperate set functions. \r
+\r
+ \pre [assert] a_iType!=cmVAR\r
+ \pre [assert] a_iType!=cmVAL\r
+ \pre [assert] a_iType!=cmFUNC\r
+ \post m_fVal = 0\r
+ \post m_pTok = 0\r
+ */\r
+ ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())\r
+ {\r
+ // The following types cant be set this way, they have special Set functions\r
+ assert(a_iType!=cmVAR);\r
+ assert(a_iType!=cmVAL);\r
+ assert(a_iType!=cmFUNC);\r
+\r
+ m_iCode = a_iType;\r
+ m_iType = tpVOID;\r
+ m_pTok = 0;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set Callback type. */\r
+ ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)\r
+ {\r
+ assert(a_pCallback.GetAddr());\r
+\r
+ m_iCode = a_pCallback.GetCode();\r
+ m_iType = tpVOID;\r
+ m_strTok = a_sTok;\r
+ m_pCallback.reset(new ParserCallback(a_pCallback));\r
+\r
+ m_pTok = 0;\r
+ m_iIdx = -1;\r
+ \r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Make this token a value token. \r
+ \r
+ Member variables not necessary for value tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())\r
+ {\r
+ m_iCode = cmVAL;\r
+ m_iType = tpDBL;\r
+ m_fVal = a_fVal;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+ \r
+ m_pTok = 0;\r
+ m_pCallback.reset(0);\r
+\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief make this token a variable token. \r
+ \r
+ Member variables not necessary for variable tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)\r
+ {\r
+ m_iCode = cmVAR;\r
+ m_iType = tpDBL;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = -1;\r
+ m_pTok = (void*)a_pVar;\r
+ m_pCallback.reset(0);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Make this token a variable token. \r
+ \r
+ Member variables not necessary for variable tokens will be invalidated.\r
+ \throw nothrow\r
+ */\r
+ ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)\r
+ {\r
+ m_iCode = cmSTRING;\r
+ m_iType = tpSTR;\r
+ m_strTok = a_strTok;\r
+ m_iIdx = static_cast<int>(a_iSize);\r
+\r
+ m_pTok = 0;\r
+ m_pCallback.reset(0);\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set an index associated with the token related data. \r
+ \r
+ In cmSTRFUNC - This is the index to a string table in the main parser.\r
+ \param a_iIdx The index the string function result will take in the bytecode parser.\r
+ \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING\r
+ */\r
+ void SetIdx(int a_iIdx)\r
+ {\r
+ if (m_iCode!=cmSTRING || a_iIdx<0)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ \r
+ m_iIdx = a_iIdx;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return Index associated with the token related data. \r
+ \r
+ In cmSTRFUNC - This is the index to a string table in the main parser.\r
+\r
+ \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING\r
+ \return The index the result will take in the Bytecode calculatin array (#m_iIdx).\r
+ */\r
+ int GetIdx() const\r
+ {\r
+ if (m_iIdx<0 || m_iCode!=cmSTRING )\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_iIdx;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the token type.\r
+ \r
+ \return #m_iType\r
+ \throw nothrow\r
+ */\r
+ ECmdCode GetCode() const\r
+ {\r
+ if (m_pCallback.get())\r
+ {\r
+ return m_pCallback->GetCode();\r
+ }\r
+ else\r
+ {\r
+ return m_iCode;\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ ETypeCode GetType() const\r
+ {\r
+ if (m_pCallback.get())\r
+ {\r
+ return m_pCallback->GetType();\r
+ }\r
+ else\r
+ {\r
+ return m_iType;\r
+ }\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ int GetPri() const\r
+ {\r
+ if ( !m_pCallback.get())\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ \r
+ if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetPri();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ EOprtAssociativity GetAssociativity() const\r
+ {\r
+ if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetAssociativity();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the address of the callback function assoziated with\r
+ function and operator tokens.\r
+\r
+ \return The pointer stored in #m_pTok.\r
+ \throw exception_type if token type is non of:\r
+ <ul>\r
+ <li>cmFUNC</li>\r
+ <li>cmSTRFUNC</li>\r
+ <li>cmPOSTOP</li>\r
+ <li>cmINFIXOP</li>\r
+ <li>cmOPRT_BIN</li>\r
+ </ul>\r
+ \sa ECmdCode\r
+ */\r
+ generic_fun_type GetFuncAddr() const\r
+ {\r
+ return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \biref Get value of the token.\r
+ \r
+ Only applicable to variable and value tokens.\r
+ \throw exception_type if token is no value/variable token.\r
+ */\r
+ TBase GetVal() const\r
+ {\r
+ switch (m_iCode)\r
+ {\r
+ case cmVAL: return m_fVal;\r
+ case cmVAR: return *((TBase*)m_pTok);\r
+ default: throw ParserError(ecVAL_EXPECTED);\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Get address of a variable token.\r
+\r
+ Valid only if m_iType==CmdVar.\r
+ \throw exception_type if token is no variable token.\r
+ */\r
+ TBase* GetVar() const\r
+ {\r
+ if (m_iCode!=cmVAR)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return (TBase*)m_pTok;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the number of function arguments. \r
+\r
+ Valid only if m_iType==CmdFUNC.\r
+ */\r
+ int GetArgCount() const\r
+ {\r
+ assert(m_pCallback.get());\r
+\r
+ if (!m_pCallback->GetAddr())\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+\r
+ return m_pCallback->GetArgc();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the token identifier. \r
+ \r
+ If #m_iType is cmSTRING the token identifier is the value of the string argument\r
+ for a string function.\r
+ \return #m_strTok\r
+ \throw nothrow\r
+ \sa m_strTok\r
+ */\r
+ const TString& GetAsString() const\r
+ {\r
+ return m_strTok;\r
+ }\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#ifndef MU_PARSER_TOKEN_READER_H\r
+#define MU_PARSER_TOKEN_READER_H\r
+\r
+#include <cassert>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <list>\r
+#include <map>\r
+#include <memory>\r
+#include <stack>\r
+#include <string>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserToken.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token reader definition.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ // Forward declaration\r
+ class ParserBase;\r
+\r
+ /** \brief Token reader for the ParserBase class.\r
+\r
+ */\r
+ class ParserTokenReader \r
+ {\r
+ private:\r
+\r
+ typedef ParserToken<value_type, string_type> token_type;\r
+\r
+ public:\r
+\r
+ ParserTokenReader(ParserBase *a_pParent);\r
+ ParserTokenReader* Clone(ParserBase *a_pParent) const;\r
+\r
+ void AddValIdent(identfun_type a_pCallback);\r
+ void SetVarCreator(facfun_type a_pFactory, void *pUserData);\r
+ void SetFormula(const string_type &a_strFormula);\r
+ void SetArgSep(char_type cArgSep);\r
+\r
+ int GetPos() const;\r
+ const string_type& GetExpr() const;\r
+ varmap_type& GetUsedVar();\r
+ char_type GetArgSep() const;\r
+\r
+ void IgnoreUndefVar(bool bIgnore);\r
+ void ReInit();\r
+ token_type ReadNextToken();\r
+\r
+ private:\r
+\r
+ /** \brief Syntax codes. \r
+ \r
+ The syntax codes control the syntax check done during the first time parsing of \r
+ the expression string. They are flags that indicate which tokens are allowed next\r
+ if certain tokens are identified.\r
+ */\r
+ enum ESynCodes\r
+ {\r
+ noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" \r
+ noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"\r
+ noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"\r
+ noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a"\r
+ noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ...\r
+ noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" \r
+ noOPT = 1 << 6, ///< to avoid i.e. "(+)"\r
+ noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!"\r
+ noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4"\r
+ noEND = 1 << 9, ///< to avoid unexpected end of formula\r
+ noSTR = 1 << 10, ///< to block numeric arguments on string functions\r
+ noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7"\r
+ noIF = 1 << 12,\r
+ noELSE = 1 << 13,\r
+ sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,\r
+ noANY = ~0 ///< All of he above flags set\r
+ }; \r
+\r
+ ParserTokenReader(const ParserTokenReader &a_Reader);\r
+ ParserTokenReader& operator=(const ParserTokenReader &a_Reader);\r
+ void Assign(const ParserTokenReader &a_Reader);\r
+\r
+ void SetParent(ParserBase *a_pParent);\r
+ int ExtractToken(const char_type *a_szCharSet, \r
+ string_type &a_strTok, \r
+ int a_iPos) const;\r
+ int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;\r
+\r
+ bool IsBuiltIn(token_type &a_Tok);\r
+ bool IsArgSep(token_type &a_Tok);\r
+ bool IsEOF(token_type &a_Tok);\r
+ bool IsInfixOpTok(token_type &a_Tok);\r
+ bool IsFunTok(token_type &a_Tok);\r
+ bool IsPostOpTok(token_type &a_Tok);\r
+ bool IsOprt(token_type &a_Tok);\r
+ bool IsValTok(token_type &a_Tok);\r
+ bool IsVarTok(token_type &a_Tok);\r
+ bool IsStrVarTok(token_type &a_Tok);\r
+ bool IsUndefVarTok(token_type &a_Tok);\r
+ bool IsString(token_type &a_Tok);\r
+ void Error(EErrorCodes a_iErrc, \r
+ int a_iPos = -1, \r
+ const string_type &a_sTok = string_type() ) const;\r
+\r
+ token_type& SaveBeforeReturn(const token_type &tok);\r
+\r
+ ParserBase *m_pParser;\r
+ string_type m_strFormula;\r
+ int m_iPos;\r
+ int m_iSynFlags;\r
+ bool m_bIgnoreUndefVar;\r
+\r
+ const funmap_type *m_pFunDef;\r
+ const funmap_type *m_pPostOprtDef;\r
+ const funmap_type *m_pInfixOprtDef;\r
+ const funmap_type *m_pOprtDef;\r
+ const valmap_type *m_pConstDef;\r
+ const strmap_type *m_pStrVarDef;\r
+ varmap_type *m_pVarDef; ///< The only non const pointer to parser internals\r
+ facfun_type m_pFactory;\r
+ void *m_pFactoryData;\r
+ std::list<identfun_type> m_vIdentFun; ///< Value token identification function\r
+ varmap_type m_UsedVar;\r
+ value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables\r
+ int m_iBrackets;\r
+ token_type m_lastTok;\r
+ char_type m_cArgSep; ///< The character used for separating function arguments\r
+ };\r
+} // namespace mu\r
+\r
+#endif\r
+\r
+\r
--- /dev/null
+/* \r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+\r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include "muParser.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cmath>\r
+#include <algorithm>\r
+#include <numeric>\r
+\r
+/** \brief Pi (what else?). */\r
+#define PARSER_CONST_PI 3.141592653589793238462643\r
+\r
+/** \brief The eulerian number. */\r
+#define PARSER_CONST_E 2.718281828459045235360287\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief Implementation of the standard floating point parser.\r
+*/\r
+\r
+\r
+\r
+/** \brief Namespace for mathematical applications. */\r
+namespace mu\r
+{\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ // Trigonometric function\r
+ value_type Parser::Sin(value_type v) { return MathImpl<value_type>::Sin(v); }\r
+ value_type Parser::Cos(value_type v) { return MathImpl<value_type>::Cos(v); }\r
+ value_type Parser::Tan(value_type v) { return MathImpl<value_type>::Tan(v); }\r
+ value_type Parser::ASin(value_type v) { return MathImpl<value_type>::ASin(v); }\r
+ value_type Parser::ACos(value_type v) { return MathImpl<value_type>::ACos(v); }\r
+ value_type Parser::ATan(value_type v) { return MathImpl<value_type>::ATan(v); }\r
+ value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl<value_type>::ATan2(v1, v2); }\r
+ value_type Parser::Sinh(value_type v) { return MathImpl<value_type>::Sinh(v); }\r
+ value_type Parser::Cosh(value_type v) { return MathImpl<value_type>::Cosh(v); }\r
+ value_type Parser::Tanh(value_type v) { return MathImpl<value_type>::Tanh(v); }\r
+ value_type Parser::ASinh(value_type v) { return MathImpl<value_type>::ASinh(v); }\r
+ value_type Parser::ACosh(value_type v) { return MathImpl<value_type>::ACosh(v); }\r
+ value_type Parser::ATanh(value_type v) { return MathImpl<value_type>::ATanh(v); }\r
+\r
+ //---------------------------------------------------------------------------\r
+ // Logarithm functions\r
+\r
+ // Logarithm base 2\r
+ value_type Parser::Log2(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Log2"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log2(v); \r
+ } \r
+\r
+ // Logarithm base 10\r
+ value_type Parser::Log10(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Log10"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log10(v); \r
+ } \r
+\r
+// Logarithm base e (natural logarithm)\r
+ value_type Parser::Ln(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<=0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("Ln"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Log(v); \r
+ } \r
+\r
+ //---------------------------------------------------------------------------\r
+ // misc\r
+ value_type Parser::Exp(value_type v) { return MathImpl<value_type>::Exp(v); }\r
+ value_type Parser::Abs(value_type v) { return MathImpl<value_type>::Abs(v); }\r
+ value_type Parser::Sqrt(value_type v) \r
+ { \r
+ #ifdef MUP_MATH_EXCEPTIONS\r
+ if (v<0)\r
+ throw ParserError(ecDOMAIN_ERROR, _T("sqrt"));\r
+ #endif\r
+\r
+ return MathImpl<value_type>::Sqrt(v); \r
+ }\r
+ value_type Parser::Rint(value_type v) { return MathImpl<value_type>::Rint(v); }\r
+ value_type Parser::Sign(value_type v) { return MathImpl<value_type>::Sign(v); }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for the unary minus operator.\r
+ \param v The value to negate\r
+ \return -v\r
+ */\r
+ value_type Parser::UnaryMinus(value_type v) \r
+ { \r
+ return -v; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for adding multiple values. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for averaging multiple values. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];\r
+ return fRes/(value_type)a_iArgc;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for determining the minimum value out of a vector. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Min(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::min(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Callback for determining the maximum value out of a vector. \r
+ \param [in] a_afArg Vector with the function arguments\r
+ \param [in] a_iArgc The size of a_afArg\r
+ */\r
+ value_type Parser::Max(const value_type *a_afArg, int a_iArgc)\r
+ { \r
+ if (!a_iArgc) \r
+ throw exception_type(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Default value recognition callback. \r
+ \param [in] a_szExpr Pointer to the expression\r
+ \param [in, out] a_iPos Pointer to an index storing the current position within the expression\r
+ \param [out] a_fVal Pointer where the value should be stored in case one is found.\r
+ \return 1 if a value was found 0 otherwise.\r
+ */\r
+ int Parser::IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal)\r
+ {\r
+ value_type fVal(0);\r
+\r
+ stringstream_type stream(a_szExpr);\r
+ stream.seekg(0); // todo: check if this really is necessary\r
+ stream.imbue(Parser::s_locale);\r
+ stream >> fVal;\r
+ stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading\r
+\r
+ if (iEnd==(stringstream_type::pos_type)-1)\r
+ return 0;\r
+\r
+ *a_iPos += (int)iEnd;\r
+ *a_fVal = fVal;\r
+ return 1;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor. \r
+\r
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
+ */\r
+ Parser::Parser()\r
+ :ParserBase()\r
+ {\r
+ AddValIdent(IsVal);\r
+\r
+ InitCharSets();\r
+ InitFun();\r
+ InitConst();\r
+ InitOprt();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the character sets. \r
+ \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars\r
+ \r
+ This function is used for initializing the default character sets that define\r
+ the characters to be useable in function and variable names and operators.\r
+ */\r
+ void Parser::InitCharSets()\r
+ {\r
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
+ DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") );\r
+ DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the default functions. */\r
+ void Parser::InitFun()\r
+ {\r
+ if (mu::TypeInfo<mu::value_type>::IsInteger())\r
+ {\r
+ // When setting MUP_BASETYPE to an integer type\r
+ // Place functions for dealing with integer values here\r
+ // ...\r
+ // ...\r
+ // ...\r
+ }\r
+ else\r
+ {\r
+ // trigonometric functions\r
+ DefineFun(_T("sin"), Sin);\r
+ DefineFun(_T("cos"), Cos);\r
+ DefineFun(_T("tan"), Tan);\r
+ // arcus functions\r
+ DefineFun(_T("asin"), ASin);\r
+ DefineFun(_T("acos"), ACos);\r
+ DefineFun(_T("atan"), ATan);\r
+ DefineFun(_T("atan2"), ATan2);\r
+ // hyperbolic functions\r
+ DefineFun(_T("sinh"), Sinh);\r
+ DefineFun(_T("cosh"), Cosh);\r
+ DefineFun(_T("tanh"), Tanh);\r
+ // arcus hyperbolic functions\r
+ DefineFun(_T("asinh"), ASinh);\r
+ DefineFun(_T("acosh"), ACosh);\r
+ DefineFun(_T("atanh"), ATanh);\r
+ // Logarithm functions\r
+ DefineFun(_T("log2"), Log2);\r
+ DefineFun(_T("log10"), Log10);\r
+ DefineFun(_T("log"), Log10);\r
+ DefineFun(_T("ln"), Ln);\r
+ // misc\r
+ DefineFun(_T("exp"), Exp);\r
+ DefineFun(_T("sqrt"), Sqrt);\r
+ DefineFun(_T("sign"), Sign);\r
+ DefineFun(_T("rint"), Rint);\r
+ DefineFun(_T("abs"), Abs);\r
+ // Functions with variable number of arguments\r
+ DefineFun(_T("sum"), Sum);\r
+ DefineFun(_T("avg"), Avg);\r
+ DefineFun(_T("min"), Min);\r
+ DefineFun(_T("max"), Max);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize constants.\r
+ \r
+ By default the parser recognizes two constants. Pi ("pi") and the eulerian\r
+ number ("_e").\r
+ */\r
+ void Parser::InitConst()\r
+ {\r
+ DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);\r
+ DefineConst(_T("_e"), (value_type)PARSER_CONST_E);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize operators. \r
+ \r
+ By default only the unary minus operator is added.\r
+ */\r
+ void Parser::InitOprt()\r
+ {\r
+ DefineInfixOprt(_T("-"), UnaryMinus);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
+ {\r
+ // this is just sample code to illustrate modifying variable names on the fly.\r
+ // I'm not sure anyone really needs such a feature...\r
+ /*\r
+\r
+\r
+ string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd);\r
+ string sRepl = std::string("_") + sVar + "_";\r
+ \r
+ int nOrigVarEnd = nEnd;\r
+ cout << "variable detected!\n";\r
+ cout << " Expr: " << *pExpr << "\n";\r
+ cout << " Start: " << nStart << "\n";\r
+ cout << " End: " << nEnd << "\n";\r
+ cout << " Var: \"" << sVar << "\"\n";\r
+ cout << " Repl: \"" << sRepl << "\"\n";\r
+ nEnd = nStart + sRepl.length();\r
+ cout << " End: " << nEnd << "\n";\r
+ pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);\r
+ cout << " New expr: " << *pExpr << "\n";\r
+ */\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Numerically differentiate with regard to a variable. \r
+ \param [in] a_Var Pointer to the differentiation variable.\r
+ \param [in] a_fPos Position at which the differentiation should take place.\r
+ \param [in] a_fEpsilon Epsilon used for the numerical differentiation.\r
+\r
+ Numerical differentiation uses a 5 point operator yielding a 4th order \r
+ formula. The default value for epsilon is 0.00074 which is\r
+ numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muparser\r
+ forum:\r
+\r
+ http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843\r
+ */\r
+ value_type Parser::Diff(value_type *a_Var, \r
+ value_type a_fPos, \r
+ value_type a_fEpsilon) const\r
+ {\r
+ value_type fRes(0), \r
+ fBuf(*a_Var),\r
+ f[4] = {0,0,0,0},\r
+ fEpsilon(a_fEpsilon);\r
+\r
+ // Backwards compatible calculation of epsilon inc case the user doesnt provide\r
+ // his own epsilon\r
+ if (fEpsilon==0)\r
+ fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos;\r
+\r
+ *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval();\r
+ *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval();\r
+ *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval();\r
+ *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval();\r
+ *a_Var = fBuf; // restore variable\r
+\r
+ fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);\r
+ return fRes;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserBase.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+//--- Standard includes ------------------------------------------------------------------------\r
+#include <cassert>\r
+#include <cmath>\r
+#include <memory>\r
+#include <vector>\r
+#include <deque>\r
+#include <sstream>\r
+#include <locale>\r
+\r
+#ifdef MUP_USE_OPENMP\r
+ #include <omp.h>\r
+#endif\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief This file contains the basic implementation of the muparser engine.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));\r
+\r
+ bool ParserBase::g_DbgDumpCmdCode = false;\r
+ bool ParserBase::g_DbgDumpStack = false;\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Identifiers for built in binary operators. \r
+\r
+ When defining custom binary operators with #AddOprt(...) make sure not to choose \r
+ names conflicting with these definitions. \r
+ */\r
+ const char_type* ParserBase::c_DefaultOprt[] = \r
+ { \r
+ _T("<="), _T(">="), _T("!="), \r
+ _T("=="), _T("<"), _T(">"), \r
+ _T("+"), _T("-"), _T("*"), \r
+ _T("/"), _T("^"), _T("&&"), \r
+ _T("||"), _T("="), _T("("), \r
+ _T(")"), _T("?"), _T(":"), 0 \r
+ };\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Constructor.\r
+ \param a_szFormula the formula to interpret.\r
+ \throw ParserException if a_szFormula is null.\r
+ */\r
+ ParserBase::ParserBase()\r
+ :m_pParseFormula(&ParserBase::ParseString)\r
+ ,m_vRPN()\r
+ ,m_vStringBuf()\r
+ ,m_pTokenReader()\r
+ ,m_FunDef()\r
+ ,m_PostOprtDef()\r
+ ,m_InfixOprtDef()\r
+ ,m_OprtDef()\r
+ ,m_ConstDef()\r
+ ,m_StrVarDef()\r
+ ,m_VarDef()\r
+ ,m_bBuiltInOp(true)\r
+ ,m_sNameChars()\r
+ ,m_sOprtChars()\r
+ ,m_sInfixOprtChars()\r
+ ,m_nIfElseCounter(0)\r
+ ,m_vStackBuffer()\r
+ ,m_nFinalResultIdx(0)\r
+ {\r
+ InitTokenReader();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+\r
+ Tha parser can be safely copy constructed but the bytecode is reset during\r
+ copy construction.\r
+ */\r
+ ParserBase::ParserBase(const ParserBase &a_Parser)\r
+ :m_pParseFormula(&ParserBase::ParseString)\r
+ ,m_vRPN()\r
+ ,m_vStringBuf()\r
+ ,m_pTokenReader()\r
+ ,m_FunDef()\r
+ ,m_PostOprtDef()\r
+ ,m_InfixOprtDef()\r
+ ,m_OprtDef()\r
+ ,m_ConstDef()\r
+ ,m_StrVarDef()\r
+ ,m_VarDef()\r
+ ,m_bBuiltInOp(true)\r
+ ,m_sNameChars()\r
+ ,m_sOprtChars()\r
+ ,m_sInfixOprtChars()\r
+ ,m_nIfElseCounter(0)\r
+ {\r
+ m_pTokenReader.reset(new token_reader_type(this));\r
+ Assign(a_Parser);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserBase::~ParserBase()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator. \r
+\r
+ Implemented by calling Assign(a_Parser). Self assignement is suppressed.\r
+ \param a_Parser Object to copy to this.\r
+ \return *this\r
+ \throw nothrow\r
+ */\r
+ ParserBase& ParserBase::operator=(const ParserBase &a_Parser)\r
+ {\r
+ Assign(a_Parser);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy state of a parser object to this. \r
+\r
+ Clears Variables and Functions of this parser.\r
+ Copies the states of all internal variables.\r
+ Resets parse function to string parse mode.\r
+\r
+ \param a_Parser the source object.\r
+ */\r
+ void ParserBase::Assign(const ParserBase &a_Parser)\r
+ {\r
+ if (&a_Parser==this)\r
+ return;\r
+\r
+ // Don't copy bytecode instead cause the parser to create new bytecode\r
+ // by resetting the parse function.\r
+ ReInit();\r
+\r
+ m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants\r
+ m_VarDef = a_Parser.m_VarDef; // Copy user defined variables\r
+ m_bBuiltInOp = a_Parser.m_bBuiltInOp;\r
+ m_vStringBuf = a_Parser.m_vStringBuf;\r
+ m_vStackBuffer = a_Parser.m_vStackBuffer;\r
+ m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;\r
+ m_StrVarDef = a_Parser.m_StrVarDef;\r
+ m_vStringVarBuf = a_Parser.m_vStringVarBuf;\r
+ m_nIfElseCounter = a_Parser.m_nIfElseCounter;\r
+ m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));\r
+\r
+ // Copy function and operator callbacks\r
+ m_FunDef = a_Parser.m_FunDef; // Copy function definitions\r
+ m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators\r
+ m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation\r
+ m_OprtDef = a_Parser.m_OprtDef; // binary operators\r
+\r
+ m_sNameChars = a_Parser.m_sNameChars;\r
+ m_sOprtChars = a_Parser.m_sOprtChars;\r
+ m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set the decimal separator.\r
+ \param cDecSep Decimal separator as a character value.\r
+ \sa SetThousandsSep\r
+\r
+ By default muparser uses the "C" locale. The decimal separator of this\r
+ locale is overwritten by the one provided here.\r
+ */\r
+ void ParserBase::SetDecSep(char_type cDecSep)\r
+ {\r
+ char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Sets the thousands operator. \r
+ \param cThousandsSep The thousands separator as a character\r
+ \sa SetDecSep\r
+\r
+ By default muparser uses the "C" locale. The thousands separator of this\r
+ locale is overwritten by the one provided here.\r
+ */\r
+ void ParserBase::SetThousandsSep(char_type cThousandsSep)\r
+ {\r
+ char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Resets the locale. \r
+\r
+ The default locale used "." as decimal separator, no thousands separator and\r
+ "," as function argument separator.\r
+ */\r
+ void ParserBase::ResetLocale()\r
+ {\r
+ s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));\r
+ SetArgSep(',');\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the token reader. \r
+\r
+ Create new token reader object and submit pointers to function, operator,\r
+ constant and variable definitions.\r
+\r
+ \post m_pTokenReader.get()!=0\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::InitTokenReader()\r
+ {\r
+ m_pTokenReader.reset(new token_reader_type(this));\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Reset parser to string parsing mode and clear internal buffers.\r
+\r
+ Clear bytecode, reset the token reader.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ReInit() const\r
+ {\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_vStringBuf.clear();\r
+ m_vRPN.clear();\r
+ m_pTokenReader->ReInit();\r
+ m_nIfElseCounter = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the version of muparser. \r
+ \param eInfo A flag indicating whether the full version info should be \r
+ returned or not.\r
+\r
+ Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS\r
+ are returned only if eInfo==pviFULL.\r
+ */\r
+ string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const\r
+ {\r
+ string_type sCompileTimeSettings;\r
+ \r
+ stringstream_type ss;\r
+\r
+ ss << MUP_VERSION;\r
+\r
+ if (eInfo==pviFULL)\r
+ {\r
+ ss << _T(" (") << MUP_VERSION_DATE;\r
+ ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT");\r
+\r
+#ifdef _DEBUG\r
+ ss << _T("; DEBUG");\r
+#else \r
+ ss << _T("; RELEASE");\r
+#endif\r
+\r
+#ifdef _UNICODE\r
+ ss << _T("; UNICODE");\r
+#else\r
+ #ifdef _MBCS\r
+ ss << _T("; MBCS");\r
+ #else\r
+ ss << _T("; ASCII");\r
+ #endif\r
+#endif\r
+\r
+#ifdef MUP_USE_OPENMP\r
+ ss << _T("; OPENMP");\r
+//#else\r
+// ss << _T("; NO_OPENMP");\r
+#endif\r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ ss << _T("; MATHEXC");\r
+//#else\r
+// ss << _T("; NO_MATHEXC");\r
+#endif\r
+\r
+ ss << _T(")");\r
+ }\r
+\r
+ return ss.str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a value parsing function. \r
+ \r
+ When parsing an expression muParser tries to detect values in the expression\r
+ string using different valident callbacks. Thuis it's possible to parse\r
+ for hex values, binary values and floating point values. \r
+ */\r
+ void ParserBase::AddValIdent(identfun_type a_pCallback)\r
+ {\r
+ m_pTokenReader->AddValIdent(a_pCallback);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set a function that can create variable pointer for unknown expression variables. \r
+ \param a_pFactory A pointer to the variable factory.\r
+ \param pUserData A user defined context pointer.\r
+ */\r
+ void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData)\r
+ {\r
+ m_pTokenReader->SetVarCreator(a_pFactory, pUserData); \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a function or operator callback to the parser. */\r
+ void ParserBase::AddCallback( const string_type &a_strName,\r
+ const ParserCallback &a_Callback, \r
+ funmap_type &a_Storage,\r
+ const char_type *a_szCharSet )\r
+ {\r
+ if (a_Callback.GetAddr()==0)\r
+ Error(ecINVALID_FUN_PTR);\r
+\r
+ const funmap_type *pFunMap = &a_Storage;\r
+\r
+ // Check for conflicting operator or function names\r
+ if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )\r
+ Error(ecNAME_CONFLICT, -1, a_strName);\r
+\r
+ CheckOprt(a_strName, a_Callback, a_szCharSet);\r
+ a_Storage[a_strName] = a_Callback;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a name contains invalid characters. \r
+\r
+ \throw ParserException if the name contains invalid charakters.\r
+ */\r
+ void ParserBase::CheckOprt(const string_type &a_sName,\r
+ const ParserCallback &a_Callback,\r
+ const string_type &a_szCharSet) const\r
+ {\r
+ if ( !a_sName.length() ||\r
+ (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
+ (a_sName[0]>='0' && a_sName[0]<='9'))\r
+ {\r
+ switch(a_Callback.GetCode())\r
+ {\r
+ case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName);\r
+ case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName);\r
+ default: Error(ecINVALID_NAME, -1, a_sName);\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a name contains invalid characters. \r
+\r
+ \throw ParserException if the name contains invalid charakters.\r
+ */\r
+ void ParserBase::CheckName(const string_type &a_sName,\r
+ const string_type &a_szCharSet) const\r
+ {\r
+ if ( !a_sName.length() ||\r
+ (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||\r
+ (a_sName[0]>='0' && a_sName[0]<='9'))\r
+ {\r
+ Error(ecINVALID_NAME);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set the formula. \r
+ \param a_strFormula Formula as string_type\r
+ \throw ParserException in case of syntax errors.\r
+\r
+ Triggers first time calculation thus the creation of the bytecode and\r
+ scanning of used variables.\r
+ */\r
+ void ParserBase::SetExpr(const string_type &a_sExpr)\r
+ {\r
+ // Check locale compatibility\r
+ std::locale loc;\r
+ if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point())\r
+ Error(ecLOCALE);\r
+\r
+ // <ibg> 20060222: Bugfix for Borland-Kylix:\r
+ // adding a space to the expression will keep Borlands KYLIX from going wild\r
+ // when calling tellg on a stringstream created from the expression after \r
+ // reading a value at the end of an expression. (mu::Parser::IsVal function)\r
+ // (tellg returns -1 otherwise causing the parser to ignore the value)\r
+ string_type sBuf(a_sExpr + _T(" ") );\r
+ m_pTokenReader->SetFormula(sBuf);\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get the default symbols used for the built in operators. \r
+ \sa c_DefaultOprt\r
+ */\r
+ const char_type** ParserBase::GetOprtDef() const\r
+ {\r
+ return (const char_type **)(&c_DefaultOprt[0]);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ functions, variables, constants.\r
+ */\r
+ void ParserBase::DefineNameChars(const char_type *a_szCharset)\r
+ {\r
+ m_sNameChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ binary operators and postfix operators.\r
+ */\r
+ void ParserBase::DefineOprtChars(const char_type *a_szCharset)\r
+ {\r
+ m_sOprtChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define the set of valid characters to be used in names of\r
+ infix operators.\r
+ */\r
+ void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset)\r
+ {\r
+ m_sInfixOprtChars = a_szCharset;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in name identifiers. \r
+ \sa #ValidOprtChars, #ValidPrefixOprtChars\r
+ */ \r
+ const char_type* ParserBase::ValidNameChars() const\r
+ {\r
+ assert(m_sNameChars.size());\r
+ return m_sNameChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in operator definitions. \r
+ \sa #ValidNameChars, #ValidPrefixOprtChars\r
+ */\r
+ const char_type* ParserBase::ValidOprtChars() const\r
+ {\r
+ assert(m_sOprtChars.size());\r
+ return m_sOprtChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Virtual function that defines the characters allowed in infix operator definitions.\r
+ \sa #ValidNameChars, #ValidOprtChars\r
+ */\r
+ const char_type* ParserBase::ValidInfixOprtChars() const\r
+ {\r
+ assert(m_sInfixOprtChars.size());\r
+ return m_sInfixOprtChars.c_str();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined operator. \r
+ \post Will reset the Parser to string parsing mode.\r
+ */\r
+ void ParserBase::DefinePostfixOprt(const string_type &a_sName, \r
+ fun_type1 a_pFun,\r
+ bool a_bAllowOpt)\r
+ {\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX),\r
+ m_PostOprtDef, \r
+ ValidOprtChars() );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize user defined functions. \r
+ \r
+ Calls the virtual functions InitFun(), InitConst() and InitOprt().\r
+ */\r
+ void ParserBase::Init()\r
+ {\r
+ InitCharSets();\r
+ InitFun();\r
+ InitConst();\r
+ InitOprt();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined operator. \r
+ \post Will reset the Parser to string parsing mode.\r
+ \param [in] a_sName operator Identifier \r
+ \param [in] a_pFun Operator callback function\r
+ \param [in] a_iPrec Operator Precedence (default=prSIGN)\r
+ \param [in] a_bAllowOpt True if operator is volatile (default=false)\r
+ \sa EPrec\r
+ */\r
+ void ParserBase::DefineInfixOprt(const string_type &a_sName, \r
+ fun_type1 a_pFun, \r
+ int a_iPrec, \r
+ bool a_bAllowOpt)\r
+ {\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), \r
+ m_InfixOprtDef, \r
+ ValidInfixOprtChars() );\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define a binary operator. \r
+ \param [in] a_sName The identifier of the operator.\r
+ \param [in] a_pFun Pointer to the callback function.\r
+ \param [in] a_iPrec Precedence of the operator.\r
+ \param [in] a_eAssociativity The associativity of the operator.\r
+ \param [in] a_bAllowOpt If this is true the operator may be optimized away.\r
+ \r
+ Adds a new Binary operator the the parser instance. \r
+ */\r
+ void ParserBase::DefineOprt( const string_type &a_sName, \r
+ fun_type2 a_pFun, \r
+ unsigned a_iPrec, \r
+ EOprtAssociativity a_eAssociativity,\r
+ bool a_bAllowOpt )\r
+ {\r
+ // Check for conflicts with built in operator names\r
+ for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i)\r
+ if (a_sName == string_type(c_DefaultOprt[i]))\r
+ Error(ecBUILTIN_OVERLOAD, -1, a_sName);\r
+\r
+ AddCallback(a_sName, \r
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), \r
+ m_OprtDef, \r
+ ValidOprtChars() );\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Define a new string constant.\r
+ \param [in] a_strName The name of the constant.\r
+ \param [in] a_strVal the value of the constant. \r
+ */\r
+ void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)\r
+ {\r
+ // Test if a constant with that names already exists\r
+ if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())\r
+ Error(ecNAME_CONFLICT);\r
+\r
+ CheckName(a_strName, ValidNameChars());\r
+ \r
+ m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer\r
+ m_StrVarDef[a_strName] = m_vStringBuf.size(); // bind buffer index to variable name\r
+\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined variable. \r
+ \param [in] a_sName the variable name\r
+ \param [in] a_pVar A pointer to the variable vaule.\r
+ \post Will reset the Parser to string parsing mode.\r
+ \throw ParserException in case the name contains invalid signs or a_pVar is NULL.\r
+ */\r
+ void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar)\r
+ {\r
+ if (a_pVar==0)\r
+ Error(ecINVALID_VAR_PTR);\r
+\r
+ // Test if a constant with that names already exists\r
+ if (m_ConstDef.find(a_sName)!=m_ConstDef.end())\r
+ Error(ecNAME_CONFLICT);\r
+\r
+ CheckName(a_sName, ValidNameChars());\r
+ m_VarDef[a_sName] = a_pVar;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a user defined constant. \r
+ \param [in] a_sName The name of the constant.\r
+ \param [in] a_fVal the value of the constant.\r
+ \post Will reset the Parser to string parsing mode.\r
+ \throw ParserException in case the name contains invalid signs.\r
+ */\r
+ void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal)\r
+ {\r
+ CheckName(a_sName, ValidNameChars());\r
+ m_ConstDef[a_sName] = a_fVal;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get operator priority.\r
+ \throw ParserException if a_Oprt is no operator code\r
+ */\r
+ int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const\r
+ {\r
+ switch (a_Tok.GetCode())\r
+ {\r
+ // built in operators\r
+ case cmEND: return -5;\r
+ case cmARG_SEP: return -4;\r
+ case cmASSIGN: return -1; \r
+ case cmELSE:\r
+ case cmIF: return 0;\r
+ case cmLAND: return prLAND;\r
+ case cmLOR: return prLOR;\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ: return prCMP; \r
+ case cmADD:\r
+ case cmSUB: return prADD_SUB;\r
+ case cmMUL:\r
+ case cmDIV: return prMUL_DIV;\r
+ case cmPOW: return prPOW;\r
+\r
+ // user defined binary operators\r
+ case cmOPRT_INFIX: \r
+ case cmOPRT_BIN: return a_Tok.GetPri();\r
+ default: Error(ecINTERNAL_ERROR, 5);\r
+ return 999;\r
+ } \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get operator priority.\r
+ \throw ParserException if a_Oprt is no operator code\r
+ */\r
+ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const\r
+ {\r
+ switch (a_Tok.GetCode())\r
+ {\r
+ case cmASSIGN:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ: \r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV: return oaLEFT;\r
+ case cmPOW: return oaRIGHT;\r
+ case cmOPRT_BIN: return a_Tok.GetAssociativity();\r
+ default: return oaNONE;\r
+ } \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ const varmap_type& ParserBase::GetUsedVar() const\r
+ {\r
+ try\r
+ {\r
+ m_pTokenReader->IgnoreUndefVar(true);\r
+ CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it\r
+ // may contain references to nonexisting variables.\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_pTokenReader->IgnoreUndefVar(false);\r
+ }\r
+ catch(exception_type &e)\r
+ {\r
+ // Make sure to stay in string parse mode, dont call ReInit()\r
+ // because it deletes the array with the used variables\r
+ m_pParseFormula = &ParserBase::ParseString;\r
+ m_pTokenReader->IgnoreUndefVar(false);\r
+ throw e;\r
+ }\r
+ \r
+ return m_pTokenReader->GetUsedVar();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ const varmap_type& ParserBase::GetVar() const\r
+ {\r
+ return m_VarDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing all parser constants. */\r
+ const valmap_type& ParserBase::GetConst() const\r
+ {\r
+ return m_ConstDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return prototypes of all parser functions.\r
+ \return #m_FunDef\r
+ \sa FunProt\r
+ \throw nothrow\r
+ \r
+ The return type is a map of the public type #funmap_type containing the prototype\r
+ definitions for all numerical parser functions. String functions are not part of \r
+ this map. The Prototype definition is encapsulated in objects of the class FunProt\r
+ one per parser function each associated with function names via a map construct.\r
+ */\r
+ const funmap_type& ParserBase::GetFunDef() const\r
+ {\r
+ return m_FunDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Retrieve the formula. */\r
+ const string_type& ParserBase::GetExpr() const\r
+ {\r
+ return m_pTokenReader->GetExpr();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Execute a function that takes a single string argument.\r
+ \param a_FunTok Function token.\r
+ \throw exception_type If the function token is not a string function\r
+ */\r
+ ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok,\r
+ const std::vector<token_type> &a_vArg) const\r
+ {\r
+ if (a_vArg.back().GetCode()!=cmSTRING)\r
+ Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
+\r
+ token_type valTok;\r
+ generic_fun_type pFunc = a_FunTok.GetFuncAddr();\r
+ assert(pFunc);\r
+\r
+ try\r
+ {\r
+ // Check function arguments; write dummy value into valtok to represent the result\r
+ switch(a_FunTok.GetArgCount())\r
+ {\r
+ case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break;\r
+ case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break;\r
+ case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;\r
+ default: Error(ecINTERNAL_ERROR);\r
+ }\r
+ }\r
+ catch(ParserError& )\r
+ {\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());\r
+ }\r
+\r
+ // string functions won't be optimized\r
+ m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());\r
+ \r
+ // Push dummy value representing the function result to the stack\r
+ return valTok;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Apply a function token. \r
+ \param iArgCount Number of Arguments actually gathered used only for multiarg functions.\r
+ \post The result is pushed to the value stack\r
+ \post The function token is removed from the stack\r
+ \throw exception_type if Argument count does not mach function requirements.\r
+ */\r
+ void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal, \r
+ int a_iArgCount) const\r
+ { \r
+ assert(m_pTokenReader.get());\r
+\r
+ // Operator stack empty or does not contain tokens with callback functions\r
+ if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )\r
+ return;\r
+\r
+ token_type funTok = a_stOpt.pop();\r
+ assert(funTok.GetFuncAddr());\r
+\r
+ // Binary operators must rely on their internal operator number\r
+ // since counting of operators relies on commas for function arguments\r
+ // binary operators do not have commas in their expression\r
+ int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;\r
+\r
+ // determine how many parameters the function needs. To remember iArgCount includes the \r
+ // string parameter whilst GetArgCount() counts only numeric parameters.\r
+ int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0);\r
+\r
+ // Thats the number of numerical parameters\r
+ int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0);\r
+\r
+ if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1)\r
+ Error(ecINTERNAL_ERROR);\r
+\r
+ if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) \r
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ if (funTok.GetCode()!=cmOPRT_BIN && iArgCount<iArgRequired )\r
+ Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired )\r
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());\r
+\r
+ // Collect the numeric function arguments from the value stack and store them\r
+ // in a vector\r
+ std::vector<token_type> stArg; \r
+ for (int i=0; i<iArgNumerical; ++i)\r
+ {\r
+ stArg.push_back( a_stVal.pop() );\r
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+ }\r
+\r
+ switch(funTok.GetCode())\r
+ {\r
+ case cmFUNC_STR: \r
+ stArg.push_back(a_stVal.pop());\r
+ \r
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )\r
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+\r
+ ApplyStrFunc(funTok, stArg); \r
+ break;\r
+\r
+ case cmFUNC_BULK: \r
+ m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); \r
+ break;\r
+\r
+ case cmOPRT_BIN:\r
+ case cmOPRT_POSTFIX:\r
+ case cmOPRT_INFIX:\r
+ case cmFUNC:\r
+ if (funTok.GetArgCount()==-1 && iArgCount==0)\r
+ Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());\r
+\r
+ m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical);\r
+ break;\r
+ }\r
+\r
+ // Push dummy value representing the function result to the stack\r
+ token_type token;\r
+ token.SetVal(1); \r
+ a_stVal.push(token);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const\r
+ {\r
+ // Check if there is an if Else clause to be calculated\r
+ while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE)\r
+ {\r
+ token_type opElse = a_stOpt.pop();\r
+ MUP_ASSERT(a_stOpt.size()>0);\r
+\r
+ // Take the value associated with the else branch from the value stack\r
+ token_type vVal2 = a_stVal.pop();\r
+\r
+ MUP_ASSERT(a_stOpt.size()>0);\r
+ MUP_ASSERT(a_stVal.size()>=2);\r
+\r
+ // it then else is a ternary operator Pop all three values from the value s\r
+ // tack and just return the right value\r
+ token_type vVal1 = a_stVal.pop();\r
+ token_type vExpr = a_stVal.pop();\r
+\r
+ a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2);\r
+\r
+ token_type opIf = a_stOpt.pop();\r
+ MUP_ASSERT(opElse.GetCode()==cmELSE);\r
+ MUP_ASSERT(opIf.GetCode()==cmIF);\r
+\r
+ m_vRPN.AddIfElse(cmENDIF);\r
+ } // while pending if-else-clause found\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Performs the necessary steps to write code for\r
+ the execution of binary operators into the bytecode. \r
+ */\r
+ void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt,\r
+ ParserStack<token_type> &a_stVal) const\r
+ {\r
+ // is it a user defined binary operator?\r
+ if (a_stOpt.top().GetCode()==cmOPRT_BIN)\r
+ {\r
+ ApplyFunc(a_stOpt, a_stVal, 2);\r
+ }\r
+ else\r
+ {\r
+ MUP_ASSERT(a_stVal.size()>=2);\r
+ token_type valTok1 = a_stVal.pop(),\r
+ valTok2 = a_stVal.pop(),\r
+ optTok = a_stOpt.pop(),\r
+ resTok; \r
+\r
+ if ( valTok1.GetType()!=valTok2.GetType() || \r
+ (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) )\r
+ Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());\r
+\r
+ if (optTok.GetCode()==cmASSIGN)\r
+ {\r
+ if (valTok2.GetCode()!=cmVAR)\r
+ Error(ecUNEXPECTED_OPERATOR, -1, _T("="));\r
+ \r
+ m_vRPN.AddAssignOp(valTok2.GetVar());\r
+ }\r
+ else\r
+ m_vRPN.AddOp(optTok.GetCode());\r
+\r
+ resTok.SetVal(1);\r
+ a_stVal.push(resTok);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Apply a binary operator. \r
+ \param a_stOpt The operator stack\r
+ \param a_stVal The value stack\r
+ */\r
+ void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,\r
+ ParserStack<token_type> &stVal) const\r
+ {\r
+ while (stOpt.size() && \r
+ stOpt.top().GetCode() != cmBO &&\r
+ stOpt.top().GetCode() != cmIF)\r
+ {\r
+ token_type tok = stOpt.top();\r
+ switch (tok.GetCode())\r
+ {\r
+ case cmOPRT_INFIX:\r
+ case cmOPRT_BIN:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmASSIGN:\r
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
+ ApplyFunc(stOpt, stVal, 1);\r
+ else\r
+ ApplyBinOprt(stOpt, stVal);\r
+ break;\r
+\r
+ case cmELSE:\r
+ ApplyIfElse(stOpt, stVal);\r
+ break;\r
+\r
+ default:\r
+ Error(ecINTERNAL_ERROR);\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Parse the command code.\r
+ \sa ParseString(...)\r
+\r
+ Command code contains precalculated stack positions of the values and the\r
+ associated operators. The Stack is filled beginning from index one the \r
+ value at index zero is not used at all.\r
+ */\r
+ value_type ParserBase::ParseCmdCode() const\r
+ {\r
+ return ParseCmdCodeBulk(0, 0);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate the RPN. \r
+ \param nOffset The offset added to variable addresses (for bulk mode)\r
+ \param nThreadID OpenMP Thread id of the calling thread\r
+ */\r
+ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const\r
+ {\r
+ assert(nThreadID<=s_MaxNumOpenMPThreads);\r
+\r
+ // Note: The check for nOffset==0 and nThreadID here is not necessary but \r
+ // brings a minor performance gain when not in bulk mode.\r
+ value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];\r
+ value_type buf;\r
+ int sidx(0);\r
+ for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok)\r
+ {\r
+ switch (pTok->Cmd)\r
+ {\r
+ // built in binary operators\r
+ case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue;\r
+ case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue;\r
+ case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue;\r
+ case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue;\r
+ case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue;\r
+ case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue;\r
+ case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue;\r
+ case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue;\r
+ case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue;\r
+ case cmDIV: --sidx;\r
+\r
+ #if defined(MUP_MATH_EXCEPTIONS)\r
+ if (Stack[1+sidx]==0)\r
+ Error(ecDIV_BY_ZERO);\r
+ #endif\r
+ Stack[sidx] /= Stack[1+sidx]; \r
+ continue;\r
+\r
+ case cmPOW: \r
+ --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]);\r
+ continue;\r
+\r
+ case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue;\r
+ case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue;\r
+\r
+ case cmASSIGN: \r
+ --sidx; Stack[sidx] = *pTok->u.Oprt.ptr = Stack[sidx+1]; continue;\r
+\r
+ //case cmBO: // unused, listed for compiler optimization purposes\r
+ //case cmBC:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ case cmIF:\r
+ if (Stack[sidx--]==0)\r
+ pTok += pTok->u.Oprt.offset;\r
+ continue;\r
+\r
+ case cmELSE:\r
+ pTok += pTok->u.Oprt.offset;\r
+ continue;\r
+\r
+ case cmENDIF:\r
+ continue;\r
+\r
+ //case cmARG_SEP:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ // value and variable tokens\r
+ case cmVAR: Stack[++sidx] = *(pTok->u.Val.ptr + nOffset); continue;\r
+ case cmVAL: Stack[++sidx] = pTok->u.Val.data2; continue;\r
+ \r
+ case cmVARPOW2: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf;\r
+ continue;\r
+\r
+ case cmVARPOW3: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf*buf;\r
+ continue;\r
+\r
+ case cmVARPOW4: buf = *(pTok->u.Val.ptr + nOffset);\r
+ Stack[++sidx] = buf*buf*buf*buf;\r
+ continue;\r
+ \r
+ case cmVARMUL: Stack[++sidx] = *(pTok->u.Val.ptr + nOffset) * pTok->u.Val.data + pTok->u.Val.data2;\r
+ continue;\r
+\r
+ // Next is treatment of numeric functions\r
+ case cmFUNC:\r
+ {\r
+ int iArgCount = pTok->u.Fun.argc;\r
+\r
+ // switch according to argument count\r
+ switch(iArgCount) \r
+ {\r
+ case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->u.Fun.ptr)(); continue;\r
+ case 1: Stack[sidx] = (*(fun_type1)pTok->u.Fun.ptr)(Stack[sidx]); continue;\r
+ case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue;\r
+ case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
+ case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
+ case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
+ case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
+ case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
+ case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
+ case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
+ case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->u.Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
+ default:\r
+ if (iArgCount>0) // function with variable arguments store the number as a negative value\r
+ Error(ecINTERNAL_ERROR, 1);\r
+\r
+ sidx -= -iArgCount - 1;\r
+ Stack[sidx] =(*(multfun_type)pTok->u.Fun.ptr)(&Stack[sidx], -iArgCount);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ // Next is treatment of string functions\r
+ case cmFUNC_STR:\r
+ {\r
+ sidx -= pTok->u.Fun.argc -1;\r
+\r
+ // The index of the string argument in the string table\r
+ int iIdxStack = pTok->u.Fun.idx; \r
+ MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() );\r
+\r
+ switch(pTok->u.Fun.argc) // switch according to argument count\r
+ {\r
+ case 0: Stack[sidx] = (*(strfun_type1)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;\r
+ case 1: Stack[sidx] = (*(strfun_type2)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;\r
+ case 2: Stack[sidx] = (*(strfun_type3)pTok->u.Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue;\r
+ }\r
+\r
+ continue;\r
+ }\r
+\r
+ case cmFUNC_BULK:\r
+ {\r
+ int iArgCount = pTok->u.Fun.argc;\r
+\r
+ // switch according to argument count\r
+ switch(iArgCount) \r
+ {\r
+ case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->u.Fun.ptr)(nOffset, nThreadID); continue;\r
+ case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue;\r
+ case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue;\r
+ case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue;\r
+ case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue;\r
+ case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue;\r
+ case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue;\r
+ case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue;\r
+ case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue;\r
+ case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue;\r
+ case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->u.Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue;\r
+ default:\r
+ Error(ecINTERNAL_ERROR, 2);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //case cmSTRING:\r
+ //case cmOPRT_BIN:\r
+ //case cmOPRT_POSTFIX:\r
+ //case cmOPRT_INFIX:\r
+ // MUP_FAIL(INVALID_CODE_IN_BYTECODE);\r
+ // continue;\r
+\r
+ //case cmEND:\r
+ // return Stack[m_nFinalResultIdx]; \r
+\r
+ default:\r
+ Error(ecINTERNAL_ERROR, 3);\r
+ return 0;\r
+ } // switch CmdCode\r
+ } // for all bytecode tokens\r
+\r
+ return Stack[m_nFinalResultIdx]; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::CreateRPN() const\r
+ {\r
+ if (!m_pTokenReader->GetExpr().length())\r
+ Error(ecUNEXPECTED_EOF, 0);\r
+\r
+ ParserStack<token_type> stOpt, stVal;\r
+ ParserStack<int> stArgCount;\r
+ token_type opta, opt; // for storing operators\r
+ token_type val, tval; // for storing value\r
+ string_type strBuf; // buffer for string function arguments\r
+\r
+ ReInit();\r
+ \r
+ // The outermost counter counts the number of seperated items\r
+ // such as in "a=10,b=20,c=c+a"\r
+ stArgCount.push(1);\r
+ \r
+ for(;;)\r
+ {\r
+ opt = m_pTokenReader->ReadNextToken();\r
+\r
+ switch (opt.GetCode())\r
+ {\r
+ //\r
+ // Next three are different kind of value entries\r
+ //\r
+ case cmSTRING:\r
+ opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token \r
+ stVal.push(opt);\r
+ m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer\r
+ break;\r
+ \r
+ case cmVAR:\r
+ stVal.push(opt);\r
+ m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) );\r
+ break;\r
+\r
+ case cmVAL:\r
+ stVal.push(opt);\r
+ m_vRPN.AddVal( opt.GetVal() );\r
+ break;\r
+\r
+ case cmELSE:\r
+ m_nIfElseCounter--;\r
+ if (m_nIfElseCounter<0)\r
+ Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());\r
+\r
+ ApplyRemainingOprt(stOpt, stVal);\r
+ m_vRPN.AddIfElse(cmELSE);\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+\r
+ case cmARG_SEP:\r
+ if (stArgCount.empty())\r
+ Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());\r
+\r
+ ++stArgCount.top();\r
+ // fallthrough intentional (no break!)\r
+\r
+ case cmEND:\r
+ ApplyRemainingOprt(stOpt, stVal);\r
+ break;\r
+\r
+ case cmBC:\r
+ {\r
+ // The argument count for parameterless functions is zero\r
+ // by default an opening bracket sets parameter count to 1\r
+ // in preparation of arguments to come. If the last token\r
+ // was an opening bracket we know better...\r
+ if (opta.GetCode()==cmBO)\r
+ --stArgCount.top();\r
+ \r
+ ApplyRemainingOprt(stOpt, stVal);\r
+\r
+ // Check if the bracket content has been evaluated completely\r
+ if (stOpt.size() && stOpt.top().GetCode()==cmBO)\r
+ {\r
+ // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check\r
+ // if there is either a function or a sign pending\r
+ // neither the opening nor the closing bracket will be pushed back to\r
+ // the operator stack\r
+ // Check if a function is standing in front of the opening bracket, \r
+ // if yes evaluate it afterwards check for infix operators\r
+ assert(stArgCount.size());\r
+ int iArgCount = stArgCount.pop();\r
+ \r
+ stOpt.pop(); // Take opening bracket from stack\r
+\r
+ if (iArgCount>1 && ( stOpt.size()==0 || \r
+ (stOpt.top().GetCode()!=cmFUNC && \r
+ stOpt.top().GetCode()!=cmFUNC_BULK && \r
+ stOpt.top().GetCode()!=cmFUNC_STR) ) )\r
+ Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());\r
+ \r
+ // The opening bracket was popped from the stack now check if there\r
+ // was a function before this bracket\r
+ if (stOpt.size() && \r
+ stOpt.top().GetCode()!=cmOPRT_INFIX && \r
+ stOpt.top().GetCode()!=cmOPRT_BIN && \r
+ stOpt.top().GetFuncAddr()!=0)\r
+ {\r
+ ApplyFunc(stOpt, stVal, iArgCount);\r
+ }\r
+ }\r
+ } // if bracket content is evaluated\r
+ break;\r
+\r
+ //\r
+ // Next are the binary operator entries\r
+ //\r
+ //case cmAND: // built in binary operators\r
+ //case cmOR:\r
+ //case cmXOR:\r
+ case cmIF:\r
+ m_nIfElseCounter++;\r
+ // fallthrough intentional (no break!)\r
+\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ:\r
+ case cmEQ:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmASSIGN:\r
+ case cmOPRT_BIN:\r
+\r
+ // A binary operator (user defined or built in) has been found. \r
+ while ( stOpt.size() && \r
+ stOpt.top().GetCode() != cmBO &&\r
+ stOpt.top().GetCode() != cmELSE &&\r
+ stOpt.top().GetCode() != cmIF)\r
+ {\r
+ int nPrec1 = GetOprtPrecedence(stOpt.top()),\r
+ nPrec2 = GetOprtPrecedence(opt);\r
+\r
+ if (stOpt.top().GetCode()==opt.GetCode())\r
+ {\r
+\r
+ // Deal with operator associativity\r
+ EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);\r
+ if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || \r
+ (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) )\r
+ {\r
+ break;\r
+ }\r
+ }\r
+ else if (nPrec1 < nPrec2)\r
+ {\r
+ // In case the operators are not equal the precedence decides alone...\r
+ break;\r
+ }\r
+ \r
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)\r
+ ApplyFunc(stOpt, stVal, 1);\r
+ else\r
+ ApplyBinOprt(stOpt, stVal);\r
+ } // while ( ... )\r
+\r
+ if (opt.GetCode()==cmIF)\r
+ m_vRPN.AddIfElse(opt.GetCode());\r
+\r
+ // The operator can't be evaluated right now, push back to the operator stack\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ //\r
+ // Last section contains functions and operators implicitely mapped to functions\r
+ //\r
+ case cmBO:\r
+ stArgCount.push(1);\r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ case cmOPRT_INFIX:\r
+ case cmFUNC:\r
+ case cmFUNC_BULK:\r
+ case cmFUNC_STR: \r
+ stOpt.push(opt);\r
+ break;\r
+\r
+ case cmOPRT_POSTFIX:\r
+ stOpt.push(opt);\r
+ ApplyFunc(stOpt, stVal, 1); // this is the postfix operator\r
+ break;\r
+\r
+ default: Error(ecINTERNAL_ERROR, 3);\r
+ } // end of switch operator-token\r
+\r
+ opta = opt;\r
+\r
+ if ( opt.GetCode() == cmEND )\r
+ {\r
+ m_vRPN.Finalize();\r
+ break;\r
+ }\r
+\r
+ if (ParserBase::g_DbgDumpStack)\r
+ {\r
+ StackDump(stVal, stOpt);\r
+ m_vRPN.AsciiDump();\r
+ }\r
+ } // while (true)\r
+\r
+ if (ParserBase::g_DbgDumpCmdCode)\r
+ m_vRPN.AsciiDump();\r
+\r
+ if (m_nIfElseCounter>0)\r
+ Error(ecMISSING_ELSE_CLAUSE);\r
+\r
+ // get the last value (= final result) from the stack\r
+ MUP_ASSERT(stArgCount.size()==1);\r
+ m_nFinalResultIdx = stArgCount.top();\r
+ if (m_nFinalResultIdx==0)\r
+ Error(ecINTERNAL_ERROR, 9);\r
+\r
+ if (stVal.size()==0)\r
+ Error(ecEMPTY_EXPRESSION);\r
+\r
+ if (stVal.top().GetType()!=tpDBL)\r
+ Error(ecSTR_RESULT);\r
+\r
+ m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief One of the two main parse functions.\r
+ \sa ParseCmdCode(...)\r
+\r
+ Parse expression from input string. Perform syntax checking and create \r
+ bytecode. After parsing the string and creating the bytecode the function \r
+ pointer #m_pParseFormula will be changed to the second parse routine the \r
+ uses bytecode instead of string parsing.\r
+ */\r
+ value_type ParserBase::ParseString() const\r
+ {\r
+ try\r
+ {\r
+ CreateRPN();\r
+ m_pParseFormula = &ParserBase::ParseCmdCode;\r
+ return (this->*m_pParseFormula)(); \r
+ }\r
+ catch(ParserError &exc)\r
+ {\r
+ exc.SetFormula(m_pTokenReader->GetExpr());\r
+ throw;\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create an error containing the parse error position.\r
+\r
+ This function will create an Parser Exception object containing the error text and\r
+ its position.\r
+\r
+ \param a_iErrc [in] The error code of type #EErrorCodes.\r
+ \param a_iPos [in] The position where the error was detected.\r
+ \param a_strTok [in] The token string representation associated with the error.\r
+ \throw ParserException always throws thats the only purpose of this function.\r
+ */\r
+ void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const\r
+ {\r
+ throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined variables.\r
+ \throw nothrow\r
+\r
+ Resets the parser to string parsing mode by calling #ReInit.\r
+ */\r
+ void ParserBase::ClearVar()\r
+ {\r
+ m_VarDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Remove a variable from internal storage.\r
+ \throw nothrow\r
+\r
+ Removes a variable if it exists. If the Variable does not exist nothing will be done.\r
+ */\r
+ void ParserBase::RemoveVar(const string_type &a_strVarName)\r
+ {\r
+ varmap_type::iterator item = m_VarDef.find(a_strVarName);\r
+ if (item!=m_VarDef.end())\r
+ {\r
+ m_VarDef.erase(item);\r
+ ReInit();\r
+ }\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all functions.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearFun()\r
+ {\r
+ m_FunDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined constants.\r
+\r
+ Both numeric and string constants will be removed from the internal storage.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearConst()\r
+ {\r
+ m_ConstDef.clear();\r
+ m_StrVarDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined postfix operators.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearPostfixOprt()\r
+ {\r
+ m_PostOprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear all user defined binary operators.\r
+ \post Resets the parser to string parsing mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearOprt()\r
+ {\r
+ m_OprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Clear the user defined Prefix operators. \r
+ \post Resets the parser to string parser mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::ClearInfixOprt()\r
+ {\r
+ m_InfixOprtDef.clear();\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Enable or disable the formula optimization feature. \r
+ \post Resets the parser to string parser mode.\r
+ \throw nothrow\r
+ */\r
+ void ParserBase::EnableOptimizer(bool a_bIsOn)\r
+ {\r
+ m_vRPN.EnableOptimizer(a_bIsOn);\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Enable the dumping of bytecode amd stack content on the console. \r
+ \param bDumpCmd Flag to enable dumping of the current bytecode to the console.\r
+ \param bDumpStack Flag to enable dumping of the stack content is written to the console.\r
+\r
+ This function is for debug purposes only!\r
+ */\r
+ void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)\r
+ {\r
+ ParserBase::g_DbgDumpCmdCode = bDumpCmd;\r
+ ParserBase::g_DbgDumpStack = bDumpStack;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Enable or disable the built in binary operators.\r
+ \throw nothrow\r
+ \sa m_bBuiltInOp, ReInit()\r
+\r
+ If you disable the built in binary operators there will be no binary operators\r
+ defined. Thus you must add them manually one by one. It is not possible to\r
+ disable built in operators selectively. This function will Reinitialize the\r
+ parser by calling ReInit().\r
+ */\r
+ void ParserBase::EnableBuiltInOprt(bool a_bIsOn)\r
+ {\r
+ m_bBuiltInOp = a_bIsOn;\r
+ ReInit();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Query status of built in variables.\r
+ \return #m_bBuiltInOp; true if built in operators are enabled.\r
+ \throw nothrow\r
+ */\r
+ bool ParserBase::HasBuiltInOprt() const\r
+ {\r
+ return m_bBuiltInOp;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Get the argument separator character. \r
+ */\r
+ char_type ParserBase::GetArgSep() const\r
+ {\r
+ return m_pTokenReader->GetArgSep();\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set argument separator. \r
+ \param cArgSep the argument separator character.\r
+ */\r
+ void ParserBase::SetArgSep(char_type cArgSep)\r
+ {\r
+ m_pTokenReader->SetArgSep(cArgSep);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Dump stack content. \r
+\r
+ This function is used for debugging only.\r
+ */\r
+ void ParserBase::StackDump(const ParserStack<token_type> &a_stVal, \r
+ const ParserStack<token_type> &a_stOprt) const\r
+ {\r
+ ParserStack<token_type> stOprt(a_stOprt), \r
+ stVal(a_stVal);\r
+\r
+ mu::console() << _T("\nValue stack:\n");\r
+ while ( !stVal.empty() ) \r
+ {\r
+ token_type val = stVal.pop();\r
+ if (val.GetType()==tpSTR)\r
+ mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");\r
+ else\r
+ mu::console() << _T(" ") << val.GetVal() << _T(" ");\r
+ }\r
+ mu::console() << "\nOperator stack:\n";\r
+\r
+ while ( !stOprt.empty() )\r
+ {\r
+ if (stOprt.top().GetCode()<=cmASSIGN) \r
+ {\r
+ mu::console() << _T("OPRT_INTRNL \"")\r
+ << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] \r
+ << _T("\" \n");\r
+ }\r
+ else\r
+ {\r
+ switch(stOprt.top().GetCode())\r
+ {\r
+ case cmVAR: mu::console() << _T("VAR\n"); break;\r
+ case cmVAL: mu::console() << _T("VAL\n"); break;\r
+ case cmFUNC: mu::console() << _T("FUNC \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"")\r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") \r
+ << stOprt.top().GetAsString() \r
+ << _T("\"\n"); break;\r
+ case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break;\r
+ case cmEND: mu::console() << _T("END\n"); break;\r
+ case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break;\r
+ case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break;\r
+ case cmBC: mu::console() << _T("BRACKET \")\"\n"); break;\r
+ case cmIF: mu::console() << _T("IF\n"); break;\r
+ case cmELSE: mu::console() << _T("ELSE\n"); break;\r
+ case cmENDIF: mu::console() << _T("ENDIF\n"); break;\r
+ default: mu::console() << stOprt.top().GetCode() << _T(" "); break;\r
+ }\r
+ } \r
+ stOprt.pop();\r
+ }\r
+\r
+ mu::console() << dec << endl;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Evaluate an expression containing comma seperated subexpressions \r
+ \param [out] nStackSize The total number of results available\r
+ \return Pointer to the array containing all expression results\r
+\r
+ This member function can be used to retriev all results of an expression\r
+ made up of multiple comma seperated subexpressions (i.e. "x+y,sin(x),cos(y)")\r
+ */\r
+ value_type* ParserBase::Eval(int &nStackSize) const\r
+ {\r
+ (this->*m_pParseFormula)(); \r
+ nStackSize = m_nFinalResultIdx;\r
+\r
+ // (for historic reasons the stack starts at position 1)\r
+ return &m_vStackBuffer[1];\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the number of results on the calculation stack. \r
+ \r
+ If the expression contains comma seperated subexpressions (i.e. "sin(y), x+y"). \r
+ There mey be more than one return value. This function returns the number of \r
+ available results.\r
+ */\r
+ int ParserBase::GetNumResults() const\r
+ {\r
+ return m_nFinalResultIdx;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Calculate the result.\r
+\r
+ A note on const correctness: \r
+ I consider it important that Calc is a const function.\r
+ Due to caching operations Calc changes only the state of internal variables with one exception\r
+ m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making\r
+ Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update. \r
+\r
+ \pre A formula must be set.\r
+ \pre Variables must have been set (if needed)\r
+\r
+ \sa #m_pParseFormula\r
+ \return The evaluation result\r
+ \throw ParseException if no Formula is set or in case of any other error related to the formula.\r
+ */\r
+ value_type ParserBase::Eval() const\r
+ {\r
+ return (this->*m_pParseFormula)(); \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserBase::Eval(value_type *results, int nBulkSize)\r
+ {\r
+ CreateRPN();\r
+\r
+ int i = 0;\r
+\r
+#ifdef MUP_USE_OPENMP\r
+//#define DEBUG_OMP_STUFF\r
+ #ifdef DEBUG_OMP_STUFF\r
+ int *pThread = new int[nBulkSize];\r
+ int *pIdx = new int[nBulkSize];\r
+ #endif\r
+\r
+ int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);\r
+ int nThreadID, ct=0;\r
+ omp_set_num_threads(nMaxThreads);\r
+\r
+ #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ nThreadID = omp_get_thread_num();\r
+ results[i] = ParseCmdCodeBulk(i, nThreadID);\r
+\r
+ #ifdef DEBUG_OMP_STUFF\r
+ #pragma omp critical\r
+ {\r
+ pThread[ct] = nThreadID; \r
+ pIdx[ct] = i; \r
+ ct++;\r
+ }\r
+ #endif\r
+ }\r
+\r
+#ifdef DEBUG_OMP_STUFF\r
+ FILE *pFile = fopen("bulk_dbg.txt", "w");\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]);\r
+ }\r
+ \r
+ delete [] pIdx;\r
+ delete [] pThread;\r
+\r
+ fclose(pFile);\r
+#endif\r
+\r
+#else\r
+ for (i=0; i<nBulkSize; ++i)\r
+ {\r
+ results[i] = ParseCmdCodeBulk(i, 0);\r
+ }\r
+#endif\r
+\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserBytecode.h"\r
+\r
+#include <cassert>\r
+#include <string>\r
+#include <stack>\r
+#include <vector>\r
+#include <iostream>\r
+#include <algorithm>\r
+\r
+#include "muParserDef.h"\r
+#include "muParserError.h"\r
+#include "muParserToken.h"\r
+#include "muParserStack.h"\r
+#include "muParserTemplateMagic.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Bytecode default constructor. */\r
+ ParserByteCode::ParserByteCode()\r
+ :m_iStackPos(0)\r
+ ,m_iMaxStackSize(0)\r
+ ,m_vRPN()\r
+ ,m_bEnableOptimizer(true)\r
+ {\r
+ m_vRPN.reserve(50);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+ \r
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
+ */\r
+ ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)\r
+ {\r
+ Assign(a_ByteCode);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignment operator.\r
+ \r
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)\r
+ */\r
+ ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)\r
+ {\r
+ Assign(a_ByteCode);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::EnableOptimizer(bool bStat)\r
+ {\r
+ m_bEnableOptimizer = bStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy state of another object to this. \r
+ \r
+ \throw nowthrow\r
+ */\r
+ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)\r
+ {\r
+ if (this==&a_ByteCode) \r
+ return;\r
+\r
+ m_iStackPos = a_ByteCode.m_iStackPos;\r
+ m_vRPN = a_ByteCode.m_vRPN;\r
+ m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a Variable pointer to bytecode. \r
+ \param a_pVar Pointer to be added.\r
+ \throw nothrow\r
+ */\r
+ void ParserByteCode::AddVar(value_type *a_pVar)\r
+ {\r
+ ++m_iStackPos;\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ // optimization does not apply\r
+ SToken tok;\r
+ tok.Cmd = cmVAR;\r
+ tok.u.Val.ptr = a_pVar;\r
+ tok.u.Val.data = 1;\r
+ tok.u.Val.data2 = 0;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a Variable pointer to bytecode. \r
+\r
+ Value entries in byte code consist of:\r
+ <ul>\r
+ <li>value array position of the value</li>\r
+ <li>the operator code according to ParserToken::cmVAL</li>\r
+ <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>\r
+ </ul>\r
+\r
+ \param a_pVal Value to be added.\r
+ \throw nothrow\r
+ */\r
+ void ParserByteCode::AddVal(value_type a_fVal)\r
+ {\r
+ ++m_iStackPos;\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ // If optimization does not apply\r
+ SToken tok;\r
+ tok.Cmd = cmVAL;\r
+ tok.u.Val.ptr = NULL;\r
+ tok.u.Val.data = 0;\r
+ tok.u.Val.data2 = a_fVal;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)\r
+ {\r
+ std::size_t sz = m_vRPN.size();\r
+ value_type &x = m_vRPN[sz-2].u.Val.data2,\r
+ &y = m_vRPN[sz-1].u.Val.data2;\r
+ switch (a_Oprt)\r
+ {\r
+ case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;\r
+ case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break;\r
+ case cmLT: x = x < y; m_vRPN.pop_back(); break;\r
+ case cmGT: x = x > y; m_vRPN.pop_back(); break;\r
+ case cmLE: x = x <= y; m_vRPN.pop_back(); break;\r
+ case cmGE: x = x >= y; m_vRPN.pop_back(); break;\r
+ case cmNEQ: x = x != y; m_vRPN.pop_back(); break;\r
+ case cmEQ: x = x == y; m_vRPN.pop_back(); break;\r
+ case cmADD: x = x + y; m_vRPN.pop_back(); break;\r
+ case cmSUB: x = x - y; m_vRPN.pop_back(); break;\r
+ case cmMUL: x = x * y; m_vRPN.pop_back(); break;\r
+ case cmDIV: \r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ if (y==0)\r
+ throw ParserError(ecDIV_BY_ZERO, _T("0"));\r
+#endif\r
+\r
+ x = x / y; \r
+ m_vRPN.pop_back();\r
+ break;\r
+\r
+ case cmPOW: x = MathImpl<value_type>::Pow(x, y); \r
+ m_vRPN.pop_back();\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ } // switch opcode\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add an operator identifier to bytecode. \r
+ \r
+ Operator entries in byte code consist of:\r
+ <ul>\r
+ <li>value array position of the result</li>\r
+ <li>the operator code according to ParserToken::ECmdCode</li>\r
+ </ul>\r
+\r
+ \sa ParserToken::ECmdCode\r
+ */\r
+ void ParserByteCode::AddOp(ECmdCode a_Oprt)\r
+ {\r
+ bool bOptimized = false;\r
+\r
+ if (m_bEnableOptimizer)\r
+ {\r
+ std::size_t sz = m_vRPN.size();\r
+\r
+ // Check for foldable constants like:\r
+ // cmVAL cmVAL cmADD \r
+ // where cmADD can stand fopr any binary operator applied to\r
+ // two constant values.\r
+ if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ ConstantFolding(a_Oprt);\r
+ bOptimized = true;\r
+ }\r
+ else\r
+ {\r
+ switch(a_Oprt)\r
+ {\r
+ case cmPOW:\r
+ // Optimization for ploynomials of low order\r
+ if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ if (m_vRPN[sz-1].u.Val.data2==2)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW2;\r
+ else if (m_vRPN[sz-1].u.Val.data2==3)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW3;\r
+ else if (m_vRPN[sz-1].u.Val.data2==4)\r
+ m_vRPN[sz-2].Cmd = cmVARPOW4;\r
+ else\r
+ break;\r
+\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+\r
+ case cmSUB:\r
+ case cmADD:\r
+ // Simple optimization based on pattern recognition for a shitload of different\r
+ // bytecode combinations of addition/subtraction\r
+ if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || \r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) )\r
+ {\r
+ assert( (m_vRPN[sz-2].u.Val.ptr==NULL && m_vRPN[sz-1].u.Val.ptr!=NULL) ||\r
+ (m_vRPN[sz-2].u.Val.ptr!=NULL && m_vRPN[sz-1].u.Val.ptr==NULL) || \r
+ (m_vRPN[sz-2].u.Val.ptr == m_vRPN[sz-1].u.Val.ptr) );\r
+\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr)); // variable\r
+ m_vRPN[sz-2].u.Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data2; // offset\r
+ m_vRPN[sz-2].u.Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].u.Val.data; // multiplikatior\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ } \r
+ break;\r
+\r
+ case cmMUL:\r
+ if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) \r
+ {\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
+ m_vRPN[sz-2].u.Val.data = m_vRPN[sz-2].u.Val.data2 + m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 = 0;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ } \r
+ else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||\r
+ (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )\r
+ {\r
+ // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2\r
+ m_vRPN[sz-2].Cmd = cmVARMUL;\r
+ m_vRPN[sz-2].u.Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].u.Val.ptr) | (long long)(m_vRPN[sz-1].u.Val.ptr));\r
+ if (m_vRPN[sz-1].Cmd == cmVAL)\r
+ {\r
+ m_vRPN[sz-2].u.Val.data *= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 *= m_vRPN[sz-1].u.Val.data2;\r
+ }\r
+ else\r
+ {\r
+ m_vRPN[sz-2].u.Val.data = m_vRPN[sz-1].u.Val.data * m_vRPN[sz-2].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 = m_vRPN[sz-1].u.Val.data2 * m_vRPN[sz-2].u.Val.data2;\r
+ }\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&\r
+ m_vRPN[sz-1].u.Val.ptr == m_vRPN[sz-2].u.Val.ptr)\r
+ {\r
+ // Optimization: a*a -> a^2\r
+ m_vRPN[sz-2].Cmd = cmVARPOW2;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+\r
+ case cmDIV:\r
+ if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].u.Val.data2!=0)\r
+ {\r
+ // Optimization: 4*a/2 -> 2*a\r
+ m_vRPN[sz-2].u.Val.data /= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN[sz-2].u.Val.data2 /= m_vRPN[sz-1].u.Val.data2;\r
+ m_vRPN.pop_back();\r
+ bOptimized = true;\r
+ }\r
+ break;\r
+ \r
+ } // switch a_Oprt\r
+ }\r
+ }\r
+\r
+ // If optimization can't be applied just write the value\r
+ if (!bOptimized)\r
+ {\r
+ --m_iStackPos;\r
+ SToken tok;\r
+ tok.Cmd = a_Oprt;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserByteCode::AddIfElse(ECmdCode a_Oprt)\r
+ {\r
+ SToken tok;\r
+ tok.Cmd = a_Oprt;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add an assignement operator\r
+ \r
+ Operator entries in byte code consist of:\r
+ <ul>\r
+ <li>cmASSIGN code</li>\r
+ <li>the pointer of the destination variable</li>\r
+ </ul>\r
+\r
+ \sa ParserToken::ECmdCode\r
+ */\r
+ void ParserByteCode::AddAssignOp(value_type *a_pVar)\r
+ {\r
+ --m_iStackPos;\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmASSIGN;\r
+ tok.u.Val.ptr = a_pVar;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add function to bytecode. \r
+\r
+ \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
+ \param a_pFun Pointer to function callback.\r
+ */\r
+ void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)\r
+ {\r
+ if (a_iArgc>=0)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1; \r
+ }\r
+ else\r
+ {\r
+ // function with unlimited number of arguments\r
+ m_iStackPos = m_iStackPos + a_iArgc + 1; \r
+ }\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add a bulk function to bytecode. \r
+\r
+ \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.\r
+ \param a_pFun Pointer to function callback.\r
+ */\r
+ void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1; \r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC_BULK;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add Strung function entry to the parser bytecode. \r
+ \throw nothrow\r
+\r
+ A string function entry consists of the stack position of the return value,\r
+ followed by a cmSTRFUNC code, the function pointer and an index into the \r
+ string buffer maintained by the parser.\r
+ */\r
+ void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)\r
+ {\r
+ m_iStackPos = m_iStackPos - a_iArgc + 1;\r
+\r
+ SToken tok;\r
+ tok.Cmd = cmFUNC_STR;\r
+ tok.u.Fun.argc = a_iArgc;\r
+ tok.u.Fun.idx = a_iIdx;\r
+ tok.u.Fun.ptr = a_pFun;\r
+ m_vRPN.push_back(tok);\r
+\r
+ m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Add end marker to bytecode.\r
+ \r
+ \throw nothrow \r
+ */\r
+ void ParserByteCode::Finalize()\r
+ {\r
+ SToken tok;\r
+ tok.Cmd = cmEND;\r
+ m_vRPN.push_back(tok);\r
+ rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit\r
+\r
+ // Determine the if-then-else jump offsets\r
+ ParserStack<int> stIf, stElse;\r
+ int idx;\r
+ for (int i=0; i<(int)m_vRPN.size(); ++i)\r
+ {\r
+ switch(m_vRPN[i].Cmd)\r
+ {\r
+ case cmIF:\r
+ stIf.push(i);\r
+ break;\r
+\r
+ case cmELSE:\r
+ stElse.push(i);\r
+ idx = stIf.pop();\r
+ m_vRPN[idx].u.Oprt.offset = i - idx;\r
+ break;\r
+ \r
+ case cmENDIF:\r
+ idx = stElse.pop();\r
+ m_vRPN[idx].u.Oprt.offset = i - idx;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ const SToken* ParserByteCode::GetBase() const\r
+ {\r
+ if (m_vRPN.size()==0)\r
+ throw ParserError(ecINTERNAL_ERROR);\r
+ else\r
+ return &m_vRPN[0];\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ std::size_t ParserByteCode::GetMaxStackSize() const\r
+ {\r
+ return m_iMaxStackSize+1;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the number of entries in the bytecode. */\r
+ std::size_t ParserByteCode::GetSize() const\r
+ {\r
+ return m_vRPN.size();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Delete the bytecode. \r
+ \r
+ \throw nothrow\r
+\r
+ The name of this function is a violation of my own coding guidelines\r
+ but this way it's more in line with the STL functions thus more \r
+ intuitive.\r
+ */\r
+ void ParserByteCode::clear()\r
+ {\r
+ m_vRPN.clear();\r
+ m_iStackPos = 0;\r
+ m_iMaxStackSize = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Dump bytecode (for debugging only!). */\r
+ void ParserByteCode::AsciiDump()\r
+ {\r
+ if (!m_vRPN.size()) \r
+ {\r
+ mu::console() << _T("No bytecode available\n");\r
+ return;\r
+ }\r
+\r
+ mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");\r
+ for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)\r
+ {\r
+ mu::console() << std::dec << i << _T(" : \t");\r
+ switch (m_vRPN[i].Cmd)\r
+ {\r
+ case cmVAL: mu::console() << _T("VAL \t");\r
+ mu::console() << _T("[") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
+ break;\r
+\r
+ case cmVAR: mu::console() << _T("VAR \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW2: mu::console() << _T("VARPOW2 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW3: mu::console() << _T("VARPOW3 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARPOW4: mu::console() << _T("VARPOW4 \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmVARMUL: mu::console() << _T("VARMUL \t");\r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Val.ptr << _T("]"); \r
+ mu::console() << _T(" * [") << m_vRPN[i].u.Val.data << _T("]");\r
+ mu::console() << _T(" + [") << m_vRPN[i].u.Val.data2 << _T("]\n");\r
+ break;\r
+\r
+ case cmFUNC: mu::console() << _T("CALL\t");\r
+ mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]"); \r
+ mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].u.Fun.ptr << _T("]"); \r
+ mu::console() << _T("\n");\r
+ break;\r
+\r
+ case cmFUNC_STR:\r
+ mu::console() << _T("CALL STRFUNC\t");\r
+ mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].u.Fun.argc << _T("]");\r
+ mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].u.Fun.idx << _T("]");\r
+ mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Fun.ptr << _T("]\n"); \r
+ break;\r
+\r
+ case cmLT: mu::console() << _T("LT\n"); break;\r
+ case cmGT: mu::console() << _T("GT\n"); break;\r
+ case cmLE: mu::console() << _T("LE\n"); break;\r
+ case cmGE: mu::console() << _T("GE\n"); break;\r
+ case cmEQ: mu::console() << _T("EQ\n"); break;\r
+ case cmNEQ: mu::console() << _T("NEQ\n"); break;\r
+ case cmADD: mu::console() << _T("ADD\n"); break;\r
+ case cmLAND: mu::console() << _T("&&\n"); break;\r
+ case cmLOR: mu::console() << _T("||\n"); break;\r
+ case cmSUB: mu::console() << _T("SUB\n"); break;\r
+ case cmMUL: mu::console() << _T("MUL\n"); break;\r
+ case cmDIV: mu::console() << _T("DIV\n"); break;\r
+ case cmPOW: mu::console() << _T("POW\n"); break;\r
+\r
+ case cmIF: mu::console() << _T("IF\t");\r
+ mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
+ break;\r
+\r
+ case cmELSE: mu::console() << _T("ELSE\t");\r
+ mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].u.Oprt.offset << _T("]\n");\r
+ break;\r
+\r
+ case cmENDIF: mu::console() << _T("ENDIF\n"); break;\r
+\r
+ case cmASSIGN: \r
+ mu::console() << _T("ASSIGN\t");\r
+ mu::console() << _T("[ADDR: 0x") << m_vRPN[i].u.Oprt.ptr << _T("]\n"); \r
+ break; \r
+\r
+ default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n"); \r
+ break;\r
+ } // switch cmdCode\r
+ } // while bytecode\r
+\r
+ mu::console() << _T("END") << std::endl;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserCallback.h"\r
+\r
+/** \file\r
+ \brief Implementation of the parser callback class.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(a_iPrec)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(a_iCode)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing binary operator callbacks. \r
+ \param a_pFun Pointer to a static function taking two arguments\r
+ \param a_bAllowOpti A flag indicating this funcation can be optimized\r
+ \param a_iPrec The operator precedence\r
+ \param a_eOprtAsct The operators associativity\r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(fun_type2 a_pFun, \r
+ bool a_bAllowOpti, \r
+ int a_iPrec, \r
+ EOprtAssociativity a_eOprtAsct)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(a_iPrec)\r
+ ,m_eOprtAsct(a_eOprtAsct)\r
+ ,m_iCode(cmOPRT_BIN)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(3)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(4)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(5)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(6)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(7)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(8)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(9)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(10)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor for constructing funcstion callbacks taking two arguments. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(3)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(4)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(5)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(6)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(7)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(8)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(9)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(10)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_BULK)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(-1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC)\r
+ ,m_iType(tpDBL)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(1)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)\r
+ :m_pFun((void*)a_pFun)\r
+ ,m_iArgc(2)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmFUNC_STR)\r
+ ,m_iType(tpSTR)\r
+ ,m_bAllowOpti(a_bAllowOpti)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Default constructor. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback()\r
+ :m_pFun(0)\r
+ ,m_iArgc(0)\r
+ ,m_iPri(-1)\r
+ ,m_eOprtAsct(oaNONE)\r
+ ,m_iCode(cmUNKNOWN)\r
+ ,m_iType(tpVOID)\r
+ ,m_bAllowOpti(0)\r
+ {}\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor. \r
+ \throw nothrow\r
+ */\r
+ ParserCallback::ParserCallback(const ParserCallback &ref)\r
+ {\r
+ m_pFun = ref.m_pFun;\r
+ m_iArgc = ref.m_iArgc;\r
+ m_bAllowOpti = ref.m_bAllowOpti;\r
+ m_iCode = ref.m_iCode;\r
+ m_iType = ref.m_iType;\r
+ m_iPri = ref.m_iPri;\r
+ m_eOprtAsct = ref.m_eOprtAsct;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Clone this instance and return a pointer to the new instance. */\r
+ ParserCallback* ParserCallback::Clone() const\r
+ {\r
+ return new ParserCallback(*this);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return tru if the function is conservative.\r
+\r
+ Conservative functions return always the same result for the same argument.\r
+ \throw nothrow\r
+ */\r
+ bool ParserCallback::IsOptimizable() const \r
+ { \r
+ return m_bAllowOpti; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Get the callback address for the parser function. \r
+ \r
+ The type of the address is void. It needs to be recasted according to the\r
+ argument number to the right type.\r
+\r
+ \throw nothrow\r
+ \return #pFun\r
+ */\r
+ void* ParserCallback::GetAddr() const \r
+ { \r
+ return m_pFun; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the callback code. */\r
+ ECmdCode ParserCallback::GetCode() const \r
+ { \r
+ return m_iCode; \r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ ETypeCode ParserCallback::GetType() const \r
+ { \r
+ return m_iType; \r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the operator precedence. \r
+ \throw nothrown\r
+\r
+ Only valid if the callback token is an operator token (binary or infix).\r
+ */\r
+ int ParserCallback::GetPri() const \r
+ { \r
+ return m_iPri; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the operators associativity. \r
+ \throw nothrown\r
+\r
+ Only valid if the callback token is a binary operator token.\r
+ */\r
+ EOprtAssociativity ParserCallback::GetAssociativity() const\r
+ {\r
+ return m_eOprtAsct;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Returns the number of function Arguments. */\r
+ int ParserCallback::GetArgc() const \r
+ { \r
+ return m_iArgc; \r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2004-2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#if defined(MUPARSER_DLL) \r
+\r
+#if defined(_WIN32)\r
+ #define WIN32_LEAN_AND_MEAN\r
+ #include <windows.h>\r
+#endif\r
+\r
+#include "muParserDLL.h"\r
+#include "muParser.h"\r
+#include "muParserInt.h"\r
+#include "muParserError.h"\r
+\r
+\r
+#define MU_TRY \\r
+ try \\r
+ {\r
+\r
+#define MU_CATCH \\r
+ } \\r
+ catch(muError_t &e) \\r
+ { \\r
+ ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \\r
+ pTag->exc = e; \\r
+ pTag->bError = true; \\r
+ if (pTag->errHandler) \\r
+ (pTag->errHandler)(a_hParser); \\r
+ } \\r
+ catch(...) \\r
+ { \\r
+ ParserTag *pTag = static_cast<ParserTag*>(a_hParser); \\r
+ pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \\r
+ pTag->bError = true; \\r
+ if (pTag->errHandler) \\r
+ (pTag->errHandler)(a_hParser); \\r
+ }\r
+\r
+/** \file \r
+ \brief This file contains the implementation of the DLL interface of muparser.\r
+*/\r
+\r
+//---------------------------------------------------------------------------\r
+// private types\r
+typedef mu::ParserBase::exception_type muError_t;\r
+typedef mu::ParserBase muParser_t;\r
+\r
+int g_nBulkSize;\r
+\r
+//---------------------------------------------------------------------------\r
+class ParserTag\r
+{\r
+public:\r
+ ParserTag(int nType)\r
+ :pParser( (nType==muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() : \r
+ (nType==muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL)\r
+ ,exc()\r
+ ,errHandler(NULL)\r
+ ,bError(false)\r
+ ,m_nParserType(nType)\r
+ {}\r
+ \r
+ ~ParserTag()\r
+ {\r
+ delete pParser;\r
+ }\r
+\r
+ mu::ParserBase *pParser;\r
+ mu::ParserBase::exception_type exc;\r
+ muErrorHandler_t errHandler;\r
+ bool bError;\r
+\r
+private:\r
+ ParserTag(const ParserTag &ref);\r
+ ParserTag& operator=(const ParserTag &ref);\r
+\r
+ int m_nParserType;\r
+};\r
+\r
+static muChar_t s_tmpOutBuf[2048];\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+//\r
+// unexported functions\r
+//\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+//---------------------------------------------------------------------------\r
+muParser_t* AsParser(muParserHandle_t a_hParser)\r
+{\r
+ return static_cast<ParserTag*>(a_hParser)->pParser;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+ParserTag* AsParserTag(muParserHandle_t a_hParser)\r
+{\r
+ return static_cast<ParserTag*>(a_hParser);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+#if defined(_WIN32)\r
+ #define _CRT_SECURE_NO_DEPRECATE\r
+\r
+ BOOL APIENTRY DllMain( HANDLE /*hModule*/, \r
+ DWORD ul_reason_for_call, \r
+ LPVOID /*lpReserved*/ )\r
+ {\r
+ switch (ul_reason_for_call)\r
+ {\r
+ case DLL_PROCESS_ATTACH:\r
+ break;\r
+\r
+ case DLL_THREAD_ATTACH:\r
+ case DLL_THREAD_DETACH:\r
+ case DLL_PROCESS_DETACH:\r
+ break;\r
+ }\r
+\r
+ return TRUE;\r
+ }\r
+\r
+#endif\r
+\r
+//---------------------------------------------------------------------------\r
+//\r
+//\r
+// exported functions\r
+//\r
+//\r
+//---------------------------------------------------------------------------\r
+\r
+API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->SetVarFactory(a_pFactory, pUserData);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Create a new Parser instance and return its handle.\r
+*/\r
+API_EXPORT(muParserHandle_t) mupCreate(int nBaseType)\r
+{\r
+ switch(nBaseType)\r
+ {\r
+ case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT));\r
+ case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT));\r
+ default: return NULL;\r
+ }\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release the parser instance related with a parser handle.\r
+*/\r
+API_EXPORT(void) mupRelease(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ ParserTag* p = static_cast<ParserTag*>(a_hParser);\r
+ delete p;\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str());\r
+ return s_tmpOutBuf;\r
+ MU_CATCH\r
+\r
+ return "";\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Evaluate the expression.\r
+*/\r
+API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ return p->Eval();\r
+ MU_CATCH\r
+\r
+ return 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum)\r
+{\r
+ MU_TRY\r
+ assert(nNum!=NULL);\r
+\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ return p->Eval(*nNum);\r
+ MU_CATCH\r
+\r
+ return 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->Eval(a_res, nSize);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetExpr(a_szExpr);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->RemoveVar( a_szName );\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release all parser variables.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearVar();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Release all parser variables.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearConst();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Clear all user defined operators.\r
+ \param a_hParser Handle to the parser instance.\r
+*/\r
+API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearOprt();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ClearFun();\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun0( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun0_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun1( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun1_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun2( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun3( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun3_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun4( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun4_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun5( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun5_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun6( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun6_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun7( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun7_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun8( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun8_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun9( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun9_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineFun10( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFun10_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun0_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun1_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muBulkFun2_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun3_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun4_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun5_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun6_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun7_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun8_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun9_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkFun10( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muBulkFun10_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun1( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muStrFun1_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun2( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muStrFun2_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrFun3( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muStrFun3_t a_pFun )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, false);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muMultFun_t a_pFun, \r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szName, \r
+ muFun2_t a_pFun, \r
+ muInt_t a_nPrec, \r
+ muInt_t a_nOprtAsct,\r
+ muBool_t a_bAllowOpt)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineOprt(a_szName, \r
+ a_pFun, \r
+ a_nPrec, \r
+ (mu::EOprtAssociativity)a_nOprtAsct, \r
+ a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t *a_pVar)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineVar(a_szName, a_pVar);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t *a_pVar)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineVar(a_szName, a_pVar);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ muFloat_t a_fVal)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineConst(a_szName, a_fVal);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szName, \r
+ const muChar_t *a_szVal)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineStrConst(a_szName, a_szVal);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str());\r
+ return s_tmpOutBuf;\r
+ \r
+ MU_CATCH\r
+\r
+ return "";\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser,\r
+ const muChar_t* a_szName,\r
+ muFun1_t a_pOprt,\r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser,\r
+ const muChar_t* a_szName,\r
+ muFun1_t a_pOprt,\r
+ muBool_t a_bAllowOpt )\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);\r
+ MU_CATCH\r
+}\r
+\r
+// Define character sets for identifiers\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineNameChars( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szCharset )\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineNameChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineOprtChars( muParserHandle_t a_hParser, \r
+ const muChar_t* a_szCharset )\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineOprtChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, \r
+ const muChar_t *a_szCharset)\r
+{\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->DefineInfixOprtChars(a_szCharset);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Get the number of variables defined in the parser.\r
+ \param a_hParser [in] Must be a valid parser handle.\r
+ \return The number of used variables.\r
+ \sa mupGetExprVar\r
+*/\r
+API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetVar();\r
+ return (int)VarMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return a variable that is used in an expression.\r
+ \param a_hParser [in] A valid parser handle.\r
+ \param a_iVar [in] The index of the variable to return.\r
+ \param a_szName [out] Pointer to the variable name.\r
+ \param a_pVar [out] Pointer to the variable.\r
+ \throw nothrow\r
+\r
+ Prior to calling this function call mupGetExprVarNum in order to get the\r
+ number of variables in the expression. If the parameter a_iVar is greater\r
+ than the number of variables both a_szName and a_pVar will be set to zero.\r
+ As a side effect this function will trigger an internal calculation of the\r
+ expression undefined variables will be set to zero during this calculation.\r
+ During the calculation user defined callback functions present in the expression\r
+ will be called, this is unavoidable.\r
+*/\r
+API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, \r
+ unsigned a_iVar, \r
+ const muChar_t **a_szName, \r
+ muFloat_t **a_pVar)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetVar();\r
+\r
+ if (a_iVar>=VarMap.size())\r
+ {\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+ return;\r
+ }\r
+ mu::varmap_type::const_iterator item;\r
+\r
+ item = VarMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_szName = &szName[0];\r
+ *a_pVar = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Get the number of variables used in the expression currently set in the parser.\r
+ \param a_hParser [in] Must be a valid parser handle.\r
+ \return The number of used variables.\r
+ \sa mupGetExprVar\r
+*/\r
+API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetUsedVar();\r
+ return (int)VarMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return a variable that is used in an expression.\r
+\r
+ Prior to calling this function call mupGetExprVarNum in order to get the\r
+ number of variables in the expression. If the parameter a_iVar is greater\r
+ than the number of variables both a_szName and a_pVar will be set to zero.\r
+ As a side effect this function will trigger an internal calculation of the\r
+ expression undefined variables will be set to zero during this calculation.\r
+ During the calculation user defined callback functions present in the expression\r
+ will be called, this is unavoidable.\r
+\r
+ \param a_hParser [in] A valid parser handle.\r
+ \param a_iVar [in] The index of the variable to return.\r
+ \param a_szName [out] Pointer to the variable name.\r
+ \param a_pVar [out] Pointer to the variable.\r
+ \throw nothrow\r
+*/\r
+API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, \r
+ unsigned a_iVar, \r
+ const muChar_t **a_szName, \r
+ muFloat_t **a_pVar)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::varmap_type VarMap = p->GetUsedVar();\r
+\r
+ if (a_iVar>=VarMap.size())\r
+ {\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+ return;\r
+ }\r
+ mu::varmap_type::const_iterator item;\r
+\r
+ item = VarMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_szName = &szName[0];\r
+ *a_pVar = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_szName = 0;\r
+ *a_pVar = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the number of constants defined in a parser. */\r
+API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::valmap_type ValMap = p->GetConst();\r
+ return (int)ValMap.size();\r
+ MU_CATCH\r
+\r
+ return 0; // never reached\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetArgSep(cArgSep);\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->ResetLocale();\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetDecSep(cDecSep);\r
+ MU_CATCH\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep)\r
+{\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ p->SetThousandsSep(cThousandsSep);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Retrieve name and value of a single parser constant.\r
+ \param a_hParser [in] a valid parser handle\r
+ \param a_iVar [in] Index of the constant to query\r
+ \param a_pszName [out] pointer to a null terminated string with the constant name\r
+ \param [out] The constant value\r
+*/\r
+API_EXPORT(void) mupGetConst( muParserHandle_t a_hParser, \r
+ unsigned a_iVar,\r
+ const muChar_t **a_pszName, \r
+ muFloat_t *a_fVal)\r
+{\r
+ // A static buffer is needed for the name since i cant return the\r
+ // pointer from the map.\r
+ static muChar_t szName[1024];\r
+\r
+ MU_TRY\r
+ muParser_t* const p(AsParser(a_hParser));\r
+ const mu::valmap_type ValMap = p->GetConst();\r
+\r
+ if (a_iVar>=ValMap.size())\r
+ {\r
+ *a_pszName = 0;\r
+ *a_fVal = 0;\r
+ return;\r
+ }\r
+\r
+ mu::valmap_type::const_iterator item;\r
+ item = ValMap.begin();\r
+ for (unsigned i=0; i<a_iVar; ++i)\r
+ item++;\r
+\r
+ strncpy(szName, item->first.c_str(), sizeof(szName));\r
+ szName[sizeof(szName)-1] = 0;\r
+\r
+ *a_pszName = &szName[0];\r
+ *a_fVal = item->second;\r
+ return;\r
+\r
+ MU_CATCH\r
+\r
+ *a_pszName = 0;\r
+ *a_fVal = 0;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Add a custom value regognition function.\r
+*/\r
+API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, \r
+ muIdentFun_t a_pFun)\r
+{\r
+ MU_TRY\r
+ muParser_t* p(AsParser(a_hParser));\r
+ p->AddValIdent(a_pFun);\r
+ MU_CATCH\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Query if an error occured.\r
+\r
+ After querying the internal error bit will be reset. So a consecutive call\r
+ will return false.\r
+*/\r
+API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser)\r
+{\r
+ bool bError( AsParserTag(a_hParser)->bError );\r
+ AsParserTag(a_hParser)->bError = false;\r
+ return bError;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Reset the internal error flag.\r
+*/\r
+API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser)\r
+{\r
+ AsParserTag(a_hParser)->bError = false;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler)\r
+{\r
+ AsParserTag(a_hParser)->errHandler = a_pHandler;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the message associated with the last error.\r
+*/\r
+API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser)\r
+{\r
+ ParserTag* const p(AsParserTag(a_hParser));\r
+ const muChar_t *pMsg = p->exc.GetMsg().c_str();\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", pMsg);\r
+ return s_tmpOutBuf;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the message associated with the last error.\r
+*/\r
+API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser)\r
+{\r
+ ParserTag* const p(AsParserTag(a_hParser));\r
+ const muChar_t *pToken = p->exc.GetToken().c_str();\r
+\r
+ // C# explodes when pMsg is returned directly. For some reason it can't access\r
+ // the memory where the message lies directly.\r
+ sprintf(s_tmpOutBuf, "%s", pToken);\r
+ return s_tmpOutBuf;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the code associated with the last error.\r
+*/\r
+API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser)\r
+{\r
+ return AsParserTag(a_hParser)->exc.GetCode();\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Return the postion associated with the last error. */\r
+API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser)\r
+{\r
+ return (int)AsParserTag(a_hParser)->exc.GetPos();\r
+}\r
+\r
+////-----------------------------------------------------------------------------------------------------\r
+//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser)\r
+//{\r
+// return AsParserTag(a_hParser)->exc.GetExpr().c_str();\r
+//}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(muFloat_t*) mupCreateVar()\r
+{\r
+ return new muFloat_t(0);\r
+}\r
+\r
+//-----------------------------------------------------------------------------------------------------\r
+API_EXPORT(void) mupReleaseVar(muFloat_t *ptr)\r
+{\r
+ delete ptr;\r
+}\r
+\r
+#endif // MUPARSER_DLL\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include "muParserError.h"\r
+\r
+\r
+namespace mu\r
+{\r
+ const ParserErrorMsg ParserErrorMsg::m_Instance;\r
+\r
+ //------------------------------------------------------------------------------\r
+ const ParserErrorMsg& ParserErrorMsg::Instance()\r
+ {\r
+ return m_Instance;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ string_type ParserErrorMsg::operator[](unsigned a_iIdx) const\r
+ {\r
+ return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::~ParserErrorMsg()\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator is deactivated.\r
+ */\r
+ ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )\r
+ {\r
+ assert(false);\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)\r
+ {}\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserErrorMsg::ParserErrorMsg()\r
+ :m_vErrMsg(0)\r
+ {\r
+ m_vErrMsg.resize(ecCOUNT);\r
+\r
+ m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$.");\r
+ m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");\r
+ m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\".");\r
+ m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");\r
+ m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");\r
+ m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");\r
+ m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");\r
+ m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");\r
+ m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");\r
+ m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at expression position $POS$");\r
+ m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at expression position $POS$");\r
+ m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");\r
+ m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");\r
+ m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");\r
+ m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");\r
+ m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("user defined binary operator \"$TOK$\" conflicts with a built in operator.");\r
+ m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");\r
+ m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");\r
+ m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");\r
+ m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");\r
+ m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");\r
+ m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string.");\r
+ m_vErrMsg[ecGENERIC] = _T("Parser error.");\r
+ m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator.");\r
+ m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$TOK$\" operator must be preceeded by a closing bracket.");\r
+ m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause");\r
+ m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$");\r
+\r
+ #if defined(_DEBUG)\r
+ for (int i=0; i<ecCOUNT; ++i)\r
+ if (!m_vErrMsg[i].length())\r
+ assert(false);\r
+ #endif\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ //\r
+ // ParserError class\r
+ //\r
+ //---------------------------------------------------------------------------\r
+\r
+ /** \brief Default constructor. */\r
+ ParserError::ParserError()\r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok()\r
+ ,m_iPos(-1)\r
+ ,m_iErrc(ecUNDEFINED)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief This Constructor is used for internal exceptions only. \r
+ \r
+ It does not contain any information but the error code.\r
+ */\r
+ ParserError::ParserError(EErrorCodes a_iErrc) \r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok()\r
+ ,m_iPos(-1)\r
+ ,m_iErrc(a_iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error from a message text. */\r
+ ParserError::ParserError(const string_type &sMsg) \r
+ :m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ Reset();\r
+ m_strMsg = sMsg;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] a_iErrc the error code.\r
+ \param [in] sTok The token string related to this error.\r
+ \param [in] sExpr The expression related to the error.\r
+ \param [in] a_iPos the position in the expression where the error occured. \r
+ */\r
+ ParserError::ParserError( EErrorCodes iErrc,\r
+ const string_type &sTok,\r
+ const string_type &sExpr,\r
+ int iPos )\r
+ :m_strMsg()\r
+ ,m_strFormula(sExpr)\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] iErrc the error code.\r
+ \param [in] iPos the position in the expression where the error occured. \r
+ \param [in] sTok The token string related to this error.\r
+ */\r
+ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) \r
+ :m_strMsg()\r
+ ,m_strFormula()\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ m_strMsg = m_ErrMsg[m_iErrc];\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Construct an error object. \r
+ \param [in] szMsg The error message text.\r
+ \param [in] iPos the position related to the error.\r
+ \param [in] sTok The token string related to this error.\r
+ */\r
+ ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) \r
+ :m_strMsg(szMsg)\r
+ ,m_strFormula()\r
+ ,m_strTok(sTok)\r
+ ,m_iPos(iPos)\r
+ ,m_iErrc(ecGENERIC)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ stringstream_type stream;\r
+ stream << (int)m_iPos;\r
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());\r
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Copy constructor. */\r
+ ParserError::ParserError(const ParserError &a_Obj)\r
+ :m_strMsg(a_Obj.m_strMsg)\r
+ ,m_strFormula(a_Obj.m_strFormula)\r
+ ,m_strTok(a_Obj.m_strTok)\r
+ ,m_iPos(a_Obj.m_iPos)\r
+ ,m_iErrc(a_Obj.m_iErrc)\r
+ ,m_ErrMsg(ParserErrorMsg::Instance())\r
+ {\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Assignment operator. */\r
+ ParserError& ParserError::operator=(const ParserError &a_Obj)\r
+ {\r
+ if (this==&a_Obj)\r
+ return *this;\r
+\r
+ m_strMsg = a_Obj.m_strMsg;\r
+ m_strFormula = a_Obj.m_strFormula;\r
+ m_strTok = a_Obj.m_strTok;\r
+ m_iPos = a_Obj.m_iPos;\r
+ m_iErrc = a_Obj.m_iErrc;\r
+ return *this;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ ParserError::~ParserError()\r
+ {}\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Replace all ocuurences of a substring with another string. \r
+ \param strFind The string that shall be replaced.\r
+ \param strReplaceWith The string that should be inserted instead of strFind\r
+ */\r
+ void ParserError::ReplaceSubString( string_type &strSource,\r
+ const string_type &strFind,\r
+ const string_type &strReplaceWith)\r
+ {\r
+ string_type strResult;\r
+ string_type::size_type iPos(0), iNext(0);\r
+\r
+ for(;;)\r
+ {\r
+ iNext = strSource.find(strFind, iPos);\r
+ strResult.append(strSource, iPos, iNext-iPos);\r
+\r
+ if( iNext==string_type::npos )\r
+ break;\r
+\r
+ strResult.append(strReplaceWith);\r
+ iPos = iNext + strFind.length();\r
+ } \r
+\r
+ strSource.swap(strResult);\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Reset the erro object. */\r
+ void ParserError::Reset()\r
+ {\r
+ m_strMsg = _T("");\r
+ m_strFormula = _T("");\r
+ m_strTok = _T("");\r
+ m_iPos = -1;\r
+ m_iErrc = ecUNDEFINED;\r
+ }\r
+ \r
+ //------------------------------------------------------------------------------\r
+ /** \brief Set the expression related to this error. */\r
+ void ParserError::SetFormula(const string_type &a_strFormula)\r
+ {\r
+ m_strFormula = a_strFormula;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief gets the expression related tp this error.*/\r
+ const string_type& ParserError::GetExpr() const \r
+ {\r
+ return m_strFormula;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Returns the message string for this error. */\r
+ const string_type& ParserError::GetMsg() const\r
+ {\r
+ return m_strMsg;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the formula position related to the error. \r
+\r
+ If the error is not related to a distinct position this will return -1\r
+ */\r
+ std::size_t ParserError::GetPos() const\r
+ {\r
+ return m_iPos;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return string related with this token (if available). */\r
+ const string_type& ParserError::GetToken() const\r
+ {\r
+ return m_strTok;\r
+ }\r
+\r
+ //------------------------------------------------------------------------------\r
+ /** \brief Return the error code. */\r
+ EErrorCodes ParserError::GetCode() const\r
+ {\r
+ return m_iErrc;\r
+ }\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2011 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserInt.h"\r
+\r
+#include <cmath>\r
+#include <algorithm>\r
+#include <numeric>\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief Implementation of a parser using integer value.\r
+*/\r
+\r
+/** \brief Namespace for mathematical applications. */\r
+namespace mu\r
+{\r
+value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); }\r
+value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }\r
+value_type ParserInt::Ite(value_type v1, \r
+ value_type v2, \r
+ value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }\r
+value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }\r
+value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }\r
+value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }\r
+value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }\r
+value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }\r
+value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }\r
+value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }\r
+value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }\r
+value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }\r
+value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }\r
+value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }\r
+value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }\r
+value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }\r
+value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }\r
+value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }\r
+value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }\r
+value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }\r
+value_type ParserInt::Not(value_type v) { return !Round(v); }\r
+\r
+value_type ParserInt::Pow(value_type v1, value_type v2) \r
+{ \r
+ return std::pow((double)Round(v1), (double)Round(v2)); \r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+// Unary operator Callbacks: Infix operators\r
+value_type ParserInt::UnaryMinus(value_type v) \r
+{ \r
+ return -Round(v); \r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError(_T("too few arguments for function sum."));\r
+\r
+ value_type fRes=0;\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes += a_afArg[i];\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError( _T("too few arguments for function min.") );\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::min(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)\r
+{ \r
+ if (!a_iArgc) \r
+ throw ParserError(_T("too few arguments for function min."));\r
+\r
+ value_type fRes=a_afArg[0];\r
+ for (int i=0; i<a_iArgc; ++i) \r
+ fRes = std::max(fRes, a_afArg[i]);\r
+\r
+ return fRes;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+// Default value recognition callback\r
+int ParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ string_type buf(a_szExpr);\r
+ std::size_t pos = buf.find_first_not_of(_T("0123456789"));\r
+\r
+ if (pos==std::string::npos)\r
+ return 0;\r
+\r
+ stringstream_type stream( buf.substr(0, pos ) );\r
+ int iVal(0);\r
+\r
+ stream >> iVal;\r
+ if (stream.fail())\r
+ return 0;\r
+ \r
+ stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading\r
+ if (stream.fail())\r
+ iEnd = stream.str().length(); \r
+\r
+ if (iEnd==(stringstream_type::pos_type)-1)\r
+ return 0;\r
+\r
+ *a_iPos += (int)iEnd;\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Check a given position in the expression for the presence of \r
+ a hex value. \r
+ \param a_szExpr Pointer to the expression string\r
+ \param [in/out] a_iPos Pointer to an interger value holding the current parsing \r
+ position in the expression.\r
+ \param [out] a_fVal Pointer to the position where the detected value shall be stored.\r
+\r
+ Hey values must be prefixed with "0x" in order to be detected properly.\r
+*/\r
+int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
+ return 0;\r
+\r
+ unsigned iVal(0);\r
+\r
+ // New code based on streams for UNICODE compliance:\r
+ stringstream_type::pos_type nPos(0);\r
+ stringstream_type ss(a_szExpr + 2);\r
+ ss >> std::hex >> iVal;\r
+ nPos = ss.tellg();\r
+\r
+ if (nPos==(stringstream_type::pos_type)0)\r
+ return 1;\r
+\r
+ *a_iPos += (int)(2 + nPos);\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+{\r
+ if (a_szExpr[0]!='#') \r
+ return 0;\r
+\r
+ unsigned iVal(0), \r
+ iBits(sizeof(iVal)*8),\r
+ i(0);\r
+\r
+ for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)\r
+ iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);\r
+\r
+ if (i==0) \r
+ return 0;\r
+\r
+ if (i==iBits)\r
+ throw exception_type(_T("Binary to integer conversion error (overflow)."));\r
+\r
+ *a_fVal = (unsigned)(iVal >> (iBits-i) );\r
+ *a_iPos += i+1;\r
+\r
+ return 1;\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Constructor. \r
+\r
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.\r
+*/\r
+ParserInt::ParserInt()\r
+ :ParserBase()\r
+{\r
+ AddValIdent(IsVal); // lowest priority\r
+ AddValIdent(IsBinVal);\r
+ AddValIdent(IsHexVal); // highest priority\r
+\r
+ InitCharSets();\r
+ InitFun();\r
+ InitOprt();\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+void ParserInt::InitConst()\r
+{\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+void ParserInt::InitCharSets()\r
+{\r
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );\r
+ DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );\r
+ DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Initialize the default functions. */\r
+void ParserInt::InitFun()\r
+{\r
+ DefineFun( _T("sign"), Sign);\r
+ DefineFun( _T("abs"), Abs);\r
+ DefineFun( _T("if"), Ite);\r
+ DefineFun( _T("sum"), Sum);\r
+ DefineFun( _T("min"), Min);\r
+ DefineFun( _T("max"), Max);\r
+}\r
+\r
+//---------------------------------------------------------------------------\r
+/** \brief Initialize operators. */\r
+void ParserInt::InitOprt()\r
+{\r
+ // disable all built in operators, not all of them usefull for integer numbers\r
+ // (they don't do rounding of values)\r
+ EnableBuiltInOprt(false);\r
+\r
+ // Disable all built in operators, they wont work with integer numbers\r
+ // since they are designed for floating point numbers\r
+ DefineInfixOprt( _T("-"), UnaryMinus);\r
+ DefineInfixOprt( _T("!"), Not);\r
+\r
+ DefineOprt( _T("&"), LogAnd, prLOGIC);\r
+ DefineOprt( _T("|"), LogOr, prLOGIC);\r
+ DefineOprt( _T("&&"), And, prLOGIC);\r
+ DefineOprt( _T("||"), Or, prLOGIC);\r
+\r
+ DefineOprt( _T("<"), Less, prCMP);\r
+ DefineOprt( _T(">"), Greater, prCMP);\r
+ DefineOprt( _T("<="), LessEq, prCMP);\r
+ DefineOprt( _T(">="), GreaterEq, prCMP);\r
+ DefineOprt( _T("=="), Equal, prCMP);\r
+ DefineOprt( _T("!="), NotEqual, prCMP);\r
+\r
+ DefineOprt( _T("+"), Add, prADD_SUB);\r
+ DefineOprt( _T("-"), Sub, prADD_SUB);\r
+\r
+ DefineOprt( _T("*"), Mul, prMUL_DIV);\r
+ DefineOprt( _T("/"), Div, prMUL_DIV);\r
+ DefineOprt( _T("%"), Mod, prMUL_DIV);\r
+\r
+ DefineOprt( _T("^"), Pow, prPOW, oaRIGHT);\r
+ DefineOprt( _T(">>"), Shr, prMUL_DIV+1);\r
+ DefineOprt( _T("<<"), Shl, prMUL_DIV+1);\r
+}\r
+\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+\r
+#include "muParserTest.h"\r
+\r
+#include <cstdio>\r
+#include <cmath>\r
+#include <iostream>\r
+#include <limits>\r
+\r
+#define PARSER_CONST_PI 3.141592653589793238462643\r
+#define PARSER_CONST_E 2.718281828459045235360287\r
+\r
+using namespace std;\r
+\r
+/** \file\r
+ \brief This file contains the implementation of parser test cases.\r
+*/\r
+\r
+namespace mu\r
+{\r
+ namespace Test\r
+ {\r
+ int ParserTester::c_iCount = 0;\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ ParserTester::ParserTester()\r
+ :m_vTestFun()\r
+ {\r
+ AddTest(&ParserTester::TestNames);\r
+ AddTest(&ParserTester::TestSyntax);\r
+ AddTest(&ParserTester::TestPostFix);\r
+ AddTest(&ParserTester::TestInfixOprt);\r
+ AddTest(&ParserTester::TestVarConst);\r
+ AddTest(&ParserTester::TestMultiArg);\r
+ AddTest(&ParserTester::TestExpression);\r
+ AddTest(&ParserTester::TestIfThenElse);\r
+ AddTest(&ParserTester::TestInterface);\r
+ AddTest(&ParserTester::TestBinOprt);\r
+ AddTest(&ParserTester::TestException);\r
+ AddTest(&ParserTester::TestStrArg);\r
+\r
+ ParserTester::c_iCount = 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal)\r
+ {\r
+ if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) \r
+ return 0;\r
+\r
+ unsigned iVal(0);\r
+\r
+ // New code based on streams for UNICODE compliance:\r
+ stringstream_type::pos_type nPos(0);\r
+ stringstream_type ss(a_szExpr + 2);\r
+ ss >> std::hex >> iVal;\r
+ nPos = ss.tellg();\r
+\r
+ if (nPos==(stringstream_type::pos_type)0)\r
+ return 1;\r
+\r
+ *a_iPos += (int)(2 + nPos);\r
+ *a_fVal = (value_type)iVal;\r
+ return 1;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestInterface()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing member functions...");\r
+ \r
+ // Test RemoveVar\r
+ value_type afVal[3] = {1,2,3};\r
+ Parser p;\r
+ \r
+ try\r
+ {\r
+ p.DefineVar( _T("a"), &afVal[0]);\r
+ p.DefineVar( _T("b"), &afVal[1]);\r
+ p.DefineVar( _T("c"), &afVal[2]);\r
+ p.SetExpr( _T("a+b+c") );\r
+ p.Eval();\r
+ }\r
+ catch(...)\r
+ {\r
+ iStat += 1; // this is not supposed to happen \r
+ }\r
+\r
+ try\r
+ {\r
+ p.RemoveVar( _T("c") );\r
+ p.Eval();\r
+ iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...\r
+ }\r
+ catch(...)\r
+ {\r
+ // failure is expected...\r
+ }\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestStrArg()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing string arguments...");\r
+ \r
+ iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash\r
+ iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true);\r
+ iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);\r
+ // use in expressions with variables\r
+ iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);\r
+ iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);\r
+ // string + numeric arguments\r
+ iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);\r
+ iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);\r
+ iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ int ParserTester::TestBinOprt()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing binary operators...");\r
+ \r
+ // built in operators\r
+ // xor operator\r
+ //iStat += EqnTest(_T("1 xor 2"), 3, true); \r
+ //iStat += EqnTest(_T("a xor b"), 3, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("1 xor 2 xor 3"), 0, true); \r
+ //iStat += EqnTest(_T("a xor b xor 3"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("a xor b xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("(1 xor 2) xor 3"), 0, true); \r
+ //iStat += EqnTest(_T("(a xor b) xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("(a) xor (b) xor c"), 0, true); // with a=1 and b=2\r
+ //iStat += EqnTest(_T("1 or 2"), 3, true); \r
+ //iStat += EqnTest(_T("a or b"), 3, true); // with a=1 and b=2\r
+ iStat += EqnTest(_T("a++b"), 3, true);\r
+ iStat += EqnTest(_T("a ++ b"), 3, true);\r
+ iStat += EqnTest(_T("1++2"), 3, true);\r
+ iStat += EqnTest(_T("1 ++ 2"), 3, true);\r
+ iStat += EqnTest(_T("a add b"), 3, true);\r
+ iStat += EqnTest(_T("1 add 2"), 3, true);\r
+ iStat += EqnTest(_T("a<b"), 1, true);\r
+ iStat += EqnTest(_T("b>a"), 1, true);\r
+ iStat += EqnTest(_T("a>a"), 0, true);\r
+ iStat += EqnTest(_T("a<a"), 0, true);\r
+ iStat += EqnTest(_T("a>a"), 0, true);\r
+ iStat += EqnTest(_T("a<=a"), 1, true);\r
+ iStat += EqnTest(_T("a<=b"), 1, true);\r
+ iStat += EqnTest(_T("b<=a"), 0, true);\r
+ iStat += EqnTest(_T("a>=a"), 1, true);\r
+ iStat += EqnTest(_T("b>=a"), 1, true);\r
+ iStat += EqnTest(_T("a>=b"), 0, true);\r
+\r
+ // Test logical operators, expecially if user defined "&" and the internal "&&" collide\r
+ iStat += EqnTest(_T("1 && 1"), 1, true); \r
+ iStat += EqnTest(_T("1 && 0"), 0, true); \r
+ iStat += EqnTest(_T("(a<b) && (b>a)"), 1, true); \r
+ iStat += EqnTest(_T("(a<b) && (a>b)"), 0, true); \r
+ //iStat += EqnTest(_T("12 and 255"), 12, true); \r
+ //iStat += EqnTest(_T("12 and 0"), 0, true); \r
+ iStat += EqnTest(_T("12 & 255"), 12, true); \r
+ iStat += EqnTest(_T("12 & 0"), 0, true); \r
+ iStat += EqnTest(_T("12&255"), 12, true); \r
+ iStat += EqnTest(_T("12&0"), 0, true); \r
+\r
+ // Assignement operator\r
+ iStat += EqnTest(_T("a = b"), 2, true); \r
+ iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); \r
+ iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);\r
+ iStat += EqnTest(_T("(a=b)*2"), 4, true);\r
+ iStat += EqnTest(_T("2*(a=b)"), 4, true);\r
+ iStat += EqnTest(_T("2*(a=b+1)"), 6, true);\r
+ iStat += EqnTest(_T("(a=b+1)*2"), 6, true);\r
+\r
+ iStat += EqnTest(_T("2^2^3"), 256, true); \r
+ iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); \r
+\r
+ // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3\r
+ iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); \r
+\r
+ // Test user defined binary operators\r
+ iStat += EqnTestInt(_T("1 | 2"), 3, true); \r
+ iStat += EqnTestInt(_T("1 || 2"), 1, true); \r
+ iStat += EqnTestInt(_T("123 & 456"), 72, true); \r
+ iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);\r
+ iStat += EqnTestInt(_T("1 && 0"), 0, true); \r
+ iStat += EqnTestInt(_T("123 && 456"), 1, true); \r
+ iStat += EqnTestInt(_T("1 << 3"), 8, true); \r
+ iStat += EqnTestInt(_T("8 >> 3"), 1, true); \r
+ iStat += EqnTestInt(_T("9 / 4"), 2, true); \r
+ iStat += EqnTestInt(_T("9 % 4"), 1, true); \r
+ iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);\r
+ iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);\r
+ iStat += EqnTestInt(_T("-10+1"), -9, true);\r
+ iStat += EqnTestInt(_T("1+2*3"), 7, true);\r
+ iStat += EqnTestInt(_T("const1 != const2"), 1, true);\r
+ iStat += EqnTestInt(_T("const1 != const2"), 0, false);\r
+ iStat += EqnTestInt(_T("const1 == const2"), 0, true);\r
+ iStat += EqnTestInt(_T("const1 == 1"), 1, true);\r
+ iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);\r
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);\r
+ iStat += EqnTestInt(_T("const1 < const2"), 1, true);\r
+ iStat += EqnTestInt(_T("const2 > const1"), 1, true);\r
+ iStat += EqnTestInt(_T("const1 <= 1"), 1, true);\r
+ iStat += EqnTestInt(_T("const2 >= 2"), 1, true);\r
+ iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);\r
+ iStat += EqnTestInt(_T("a != b"), 1, true);\r
+ iStat += EqnTestInt(_T("a != b"), 0, false);\r
+ iStat += EqnTestInt(_T("a == b"), 0, true);\r
+ iStat += EqnTestInt(_T("a == 1"), 1, true);\r
+ iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);\r
+ iStat += EqnTestInt(_T("2*(a | b)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(a | b)"), 7, false);\r
+ iStat += EqnTestInt(_T("a < b"), 1, true);\r
+ iStat += EqnTestInt(_T("b > a"), 1, true);\r
+ iStat += EqnTestInt(_T("a <= 1"), 1, true);\r
+ iStat += EqnTestInt(_T("b >= 2"), 1, true);\r
+ iStat += EqnTestInt(_T("2*(a + b)"), 6, true);\r
+ iStat += EqnTestInt(_T("2*(a - b)"), -2, true);\r
+ iStat += EqnTestInt(_T("a + (a << b)"), 5, true);\r
+ iStat += EqnTestInt(_T("-2^2"), -4, true);\r
+ iStat += EqnTestInt(_T("3--a"), 4, true);\r
+ iStat += EqnTestInt(_T("3+-3^2"), -6, true);\r
+\r
+ // Test reading of hex values:\r
+ iStat += EqnTestInt(_T("0xff"), 255, true);\r
+ iStat += EqnTestInt(_T("10+0xff"), 265, true);\r
+ iStat += EqnTestInt(_T("0xff+10"), 265, true);\r
+ iStat += EqnTestInt(_T("10*0xff"), 2550, true);\r
+ iStat += EqnTestInt(_T("0xff*10"), 2550, true);\r
+ iStat += EqnTestInt(_T("10+0xff+1"), 266, true);\r
+ iStat += EqnTestInt(_T("1+0xff+10"), 266, true);\r
+\r
+// incorrect: '^' is yor here, not power\r
+// iStat += EqnTestInt("-(1+2)^2", -9, true);\r
+// iStat += EqnTestInt("-1^3", -1, true); \r
+\r
+ // Test precedence\r
+ // a=1, b=2, c=3\r
+ iStat += EqnTestInt(_T("a + b * c"), 7, true);\r
+ iStat += EqnTestInt(_T("a * b + c"), 5, true);\r
+ iStat += EqnTestInt(_T("a<b && b>10"), 0, true);\r
+ iStat += EqnTestInt(_T("a<b && b<10"), 1, true);\r
+\r
+ iStat += EqnTestInt(_T("a + b << c"), 17, true);\r
+ iStat += EqnTestInt(_T("a << b + c"), 7, true);\r
+ iStat += EqnTestInt(_T("c * b < a"), 0, true);\r
+ iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);\r
+ iStat += EqnTestInt(_T("2^2^3"), 256, true); \r
+\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------------------------\r
+ /** \brief Check muParser name restriction enforcement. */\r
+ int ParserTester::TestNames()\r
+ {\r
+ int iStat= 0,\r
+ iErr = 0;\r
+\r
+ mu::console() << "testing name restriction enforcement...";\r
+ \r
+ Parser p;\r
+\r
+ #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \\r
+ iErr = 0; \\r
+ ParserTester::c_iCount++; \\r
+ try \\r
+ { \\r
+ p.Define##DOMAIN(EXPR, ARG); \\r
+ } \\r
+ catch(Parser::exception_type&) \\r
+ { \\r
+ iErr = (FAIL==false) ? 0 : 1; \\r
+ } \\r
+ iStat += iErr; \r
+ \r
+ // constant names\r
+ PARSER_THROWCHECK(Const, false, _T("0a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("9a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("+a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("-a"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a-"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a*"), 1)\r
+ PARSER_THROWCHECK(Const, false, _T("a?"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)\r
+ PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)\r
+ // variable names\r
+ value_type a;\r
+ p.ClearConst();\r
+ PARSER_THROWCHECK(Var, false, _T("123abc"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("9a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("0a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("+a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("-a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("?a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("!a"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a+"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a-"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a*"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a?"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)\r
+ PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)\r
+ PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)\r
+ // Postfix operators\r
+ // fail\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)\r
+ // pass\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("_"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("#"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&&"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("||"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("|"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("++"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("--"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?>"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)\r
+ PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1)\r
+ // Binary operator\r
+ // The following must fail with builtin operators activated\r
+ // p.EnableBuiltInOp(true); -> this is the default\r
+ p.ClearPostfixOprt();\r
+ PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2)\r
+ // without activated built in operators it should work\r
+ p.EnableBuiltInOprt(false);\r
+ PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2)\r
+ PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2)\r
+ #undef PARSER_THROWCHECK\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestSyntax()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing syntax engine...");\r
+\r
+ iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+ iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition\r
+\r
+ iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula\r
+ iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets\r
+ iStat += EqnTest(_T("sqrt((2)+2)"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt(2+(2))"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt(a+(3))"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("sqrt((3)+a)"), 2, true);// Multiple brackets\r
+ iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or"\r
+ iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket \r
+ iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator\r
+ iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator\r
+ iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("--2"), 0, false); // double sign\r
+ iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function\r
+ iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function\r
+ iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function\r
+ iStat += EqnTest(_T("5t6"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token\r
+ iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula\r
+ iStat += EqnTest(_T(",3"), 0, false); // unexpected comma\r
+ iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma\r
+ iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args\r
+ iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args\r
+ iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket\r
+ iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestVarConst()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing variable/constant detection...");\r
+\r
+ // Test if the result changes when a variable changes\r
+ iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 );\r
+ iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 );\r
+\r
+ // distinguish constants with same basename\r
+ iStat += EqnTest( _T("const"), 1, true);\r
+ iStat += EqnTest( _T("const1"), 2, true);\r
+ iStat += EqnTest( _T("const2"), 3, true);\r
+ iStat += EqnTest( _T("2*const"), 2, true);\r
+ iStat += EqnTest( _T("2*const1"), 4, true);\r
+ iStat += EqnTest( _T("2*const2"), 6, true);\r
+ iStat += EqnTest( _T("2*const+1"), 3, true);\r
+ iStat += EqnTest( _T("2*const1+1"), 5, true);\r
+ iStat += EqnTest( _T("2*const2+1"), 7, true);\r
+ iStat += EqnTest( _T("const"), 0, false);\r
+ iStat += EqnTest( _T("const1"), 0, false);\r
+ iStat += EqnTest( _T("const2"), 0, false);\r
+\r
+ // distinguish variables with same basename\r
+ iStat += EqnTest( _T("a"), 1, true);\r
+ iStat += EqnTest( _T("aa"), 2, true);\r
+ iStat += EqnTest( _T("2*a"), 2, true);\r
+ iStat += EqnTest( _T("2*aa"), 4, true);\r
+ iStat += EqnTest( _T("2*a-1"), 1, true);\r
+ iStat += EqnTest( _T("2*aa-1"), 3, true);\r
+\r
+ // custom value recognition\r
+ iStat += EqnTest( _T("0xff"), 255, true);\r
+ iStat += EqnTest( _T("0x97 + 0xff"), 406, true);\r
+\r
+ // Finally test querying of used variables\r
+ try\r
+ {\r
+ int idx;\r
+ mu::Parser p;\r
+ mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};\r
+ p.DefineVar( _T("a"), &vVarVal[0]);\r
+ p.DefineVar( _T("b"), &vVarVal[1]);\r
+ p.DefineVar( _T("c"), &vVarVal[2]);\r
+ p.DefineVar( _T("d"), &vVarVal[3]);\r
+ p.DefineVar( _T("e"), &vVarVal[4]);\r
+\r
+ // Test lookup of defined variables\r
+ // 4 used variables\r
+ p.SetExpr( _T("a+b+c+d") );\r
+ mu::varmap_type UsedVar = p.GetUsedVar();\r
+ int iCount = (int)UsedVar.size();\r
+ if (iCount!=4) \r
+ throw false;\r
+ \r
+ // the next check will fail if the parser \r
+ // erroneousely creates new variables internally\r
+ if (p.GetVar().size()!=5)\r
+ throw false;\r
+\r
+ mu::varmap_type::const_iterator item = UsedVar.begin();\r
+ for (idx=0; item!=UsedVar.end(); ++item)\r
+ {\r
+ if (&vVarVal[idx++]!=item->second) \r
+ throw false;\r
+ }\r
+\r
+ // Test lookup of undefined variables\r
+ p.SetExpr( _T("undef1+undef2+undef3") );\r
+ UsedVar = p.GetUsedVar();\r
+ iCount = (int)UsedVar.size();\r
+ if (iCount!=3) \r
+ throw false;\r
+\r
+ // the next check will fail if the parser \r
+ // erroneousely creates new variables internally\r
+ if (p.GetVar().size()!=5)\r
+ throw false;\r
+\r
+ for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)\r
+ {\r
+ if (item->second!=0) \r
+ throw false; // all pointers to undefined variables must be null\r
+ }\r
+\r
+ // 1 used variables\r
+ p.SetExpr( _T("a+b") );\r
+ UsedVar = p.GetUsedVar();\r
+ iCount = (int)UsedVar.size();\r
+ if (iCount!=2) throw false;\r
+ item = UsedVar.begin();\r
+ for (idx=0; item!=UsedVar.end(); ++item)\r
+ if (&vVarVal[idx++]!=item->second) throw false;\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ iStat += 1;\r
+ }\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestMultiArg()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing multiarg functions...");\r
+ \r
+ // Compound expressions\r
+ iStat += EqnTest( _T("1,2,3"), 3, true);\r
+ iStat += EqnTest( _T("a,b,c"), 3, true);\r
+ iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true);\r
+ iStat += EqnTest( _T("1,\n2,\n3"), 3, true);\r
+ iStat += EqnTest( _T("a,\nb,\nc"), 3, true);\r
+ iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true);\r
+ iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true);\r
+ iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true);\r
+ iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true);\r
+\r
+ // picking the right argument\r
+ iStat += EqnTest( _T("f1of1(1)"), 1, true);\r
+ iStat += EqnTest( _T("f1of2(1, 2)"), 1, true);\r
+ iStat += EqnTest( _T("f2of2(1, 2)"), 2, true);\r
+ iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true);\r
+ iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true);\r
+ iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true);\r
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true);\r
+ iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true);\r
+ iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true);\r
+ iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true);\r
+ iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true);\r
+ iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true);\r
+ iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true);\r
+ iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true);\r
+ iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true);\r
+ // Too few arguments / Too many arguments\r
+ iStat += EqnTest( _T("1+ping()"), 11, true);\r
+ iStat += EqnTest( _T("ping()+1"), 11, true);\r
+ iStat += EqnTest( _T("2*ping()"), 20, true);\r
+ iStat += EqnTest( _T("ping()*2"), 20, true);\r
+ iStat += EqnTest( _T("ping(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("1+ping(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("f1of1(1,2)"), 0, false);\r
+ iStat += EqnTest( _T("f1of1()"), 0, false);\r
+ iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false);\r
+ iStat += EqnTest( _T("f1of2(1)"), 0, false);\r
+ iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false);\r
+ iStat += EqnTest( _T("f1of3(1)"), 0, false);\r
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false);\r
+ iStat += EqnTest( _T("f1of4(1)"), 0, false);\r
+ iStat += EqnTest( _T("(1,2,3)"), 0, false);\r
+ iStat += EqnTest( _T("1,2,3"), 0, false);\r
+ iStat += EqnTest( _T("(1*a,2,3)"), 0, false);\r
+ iStat += EqnTest( _T("1,2*a,3"), 0, false);\r
+ \r
+ // correct calculation of arguments\r
+ iStat += EqnTest( _T("min(a, 1)"), 1, true);\r
+ iStat += EqnTest( _T("min(3*2, 1)"), 1, true);\r
+ iStat += EqnTest( _T("min(3*2, 1)"), 6, false);\r
+ iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true);\r
+ iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true);\r
+ iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true);\r
+ iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true);\r
+ iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true);\r
+ iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true);\r
+\r
+ // functions with Variable argument count\r
+ iStat += EqnTest( _T("sum(a)"), 1, true);\r
+ iStat += EqnTest( _T("sum(1,2,3)"), 6, true);\r
+ iStat += EqnTest( _T("sum(a,b,c)"), 6, true);\r
+ iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true);\r
+ iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true);\r
+ iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true);\r
+ iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true);\r
+ iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true);\r
+ iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true);\r
+ iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true);\r
+ iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true);\r
+ iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);\r
+\r
+ // some failures\r
+ iStat += EqnTest( _T("sum()"), 0, false);\r
+ iStat += EqnTest( _T("sum(,)"), 0, false);\r
+ iStat += EqnTest( _T("sum(1,2,)"), 0, false);\r
+ iStat += EqnTest( _T("sum(,1,2)"), 0, false);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+ \r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestInfixOprt()\r
+ {\r
+ int iStat(0);\r
+ mu::console() << "testing infix operators...";\r
+\r
+ iStat += EqnTest( _T("-1"), -1, true);\r
+ iStat += EqnTest( _T("-(-1)"), 1, true);\r
+ iStat += EqnTest( _T("-(-1)*2"), 2, true);\r
+ iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true);\r
+ iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true);\r
+ iStat += EqnTest( _T("-a"), -1, true);\r
+ iStat += EqnTest( _T("-(a)"), -1, true);\r
+ iStat += EqnTest( _T("-(-a)"), 1, true);\r
+ iStat += EqnTest( _T("-(-a)*2"), 2, true);\r
+ iStat += EqnTest( _T("-(8)"), -8, true);\r
+ iStat += EqnTest( _T("-8"), -8, true);\r
+ iStat += EqnTest( _T("-(2+1)"), -3, true);\r
+ iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true);\r
+ iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true);\r
+ iStat += EqnTest( _T("-sin(8)"), -0.989358, true);\r
+ iStat += EqnTest( _T("3-(-a)"), 4, true);\r
+ iStat += EqnTest( _T("3--a"), 4, true);\r
+ iStat += EqnTest( _T("-1*3"), -3, true);\r
+\r
+ // Postfix / infix priorities\r
+ iStat += EqnTest( _T("~2#"), 8, true);\r
+ iStat += EqnTest( _T("~f1of1(2)#"), 8, true);\r
+ iStat += EqnTest( _T("~(b)#"), 8, true);\r
+ iStat += EqnTest( _T("(~b)#"), 12, true);\r
+ iStat += EqnTest( _T("~(2#)"), 8, true);\r
+ iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true);\r
+ //\r
+ iStat += EqnTest( _T("-2^2"),-4, true);\r
+ iStat += EqnTest( _T("-(a+b)^2"),-9, true);\r
+ iStat += EqnTest( _T("(-3)^2"),9, true);\r
+ iStat += EqnTest( _T("-(-2^2)"),4, true);\r
+ iStat += EqnTest( _T("3+-3^2"),-6, true);\r
+ // The following assumes use of sqr as postfix operator ("§") together\r
+ // with a sign operator of low priority:\r
+ iStat += EqnTest( _T("-2'"), -4, true);\r
+ iStat += EqnTest( _T("-(1+1)'"),-4, true);\r
+ iStat += EqnTest( _T("2+-(1+1)'"),-2, true);\r
+ iStat += EqnTest( _T("2+-2'"), -2, true);\r
+ // This is the classic behaviour of the infix sign operator (here: "$") which is\r
+ // now deprecated:\r
+ iStat += EqnTest( _T("$2^2"),4, true);\r
+ iStat += EqnTest( _T("$(a+b)^2"),9, true);\r
+ iStat += EqnTest( _T("($3)^2"),9, true);\r
+ iStat += EqnTest( _T("$($2^2)"),-4, true);\r
+ iStat += EqnTest( _T("3+$3^2"),12, true);\r
+\r
+ // infix operators sharing the first few characters\r
+ iStat += EqnTest( _T("~ 123"), 123+2, true);\r
+ iStat += EqnTest( _T("~~ 123"), 123+2, true);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestPostFix()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing postfix operators...");\r
+\r
+ // application\r
+ iStat += EqnTest( _T("3{m}+5"), 5.003, true);\r
+ iStat += EqnTest( _T("1000{m}"), 1, true);\r
+ iStat += EqnTest( _T("1000 {m}"), 1, true);\r
+ iStat += EqnTest( _T("(a){m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("a{m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("a {m}"), 1e-3, true);\r
+ iStat += EqnTest( _T("-(a){m}"), -1e-3, true);\r
+ iStat += EqnTest( _T("-2{m}"), -2e-3, true);\r
+ iStat += EqnTest( _T("-2 {m}"), -2e-3, true);\r
+ iStat += EqnTest( _T("f1of1(1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true);\r
+ iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true);\r
+ iStat += EqnTest( _T("2+(a*1000){m}"), 3, true);\r
+\r
+ // can postfix operators "m" und "meg" be told apart properly?\r
+ iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true); \r
+\r
+ // some incorrect results\r
+ iStat += EqnTest( _T("1000{m}"), 0.1, false);\r
+ iStat += EqnTest( _T("(a){m}"), 2, false);\r
+ // failure due to syntax checking\r
+ iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition\r
+ iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);\r
+ iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS);\r
+ \r
+ iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN);\r
+\r
+ if (iStat==0)\r
+ mu::console() << _T("passed") << endl;\r
+ else\r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestExpression()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing expression samples...");\r
+\r
+ value_type b = 2;\r
+\r
+ // Optimization\r
+ iStat += EqnTest( _T("2*b*5"), 20, true);\r
+ iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true);\r
+ iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true);\r
+\r
+ // Addition auf cmVARMUL \r
+ iStat += EqnTest( _T("3+b"), b+3, true);\r
+ iStat += EqnTest( _T("b+3"), b+3, true);\r
+ iStat += EqnTest( _T("b*3+2"), b*3+2, true);\r
+ iStat += EqnTest( _T("3*b+2"), b*3+2, true);\r
+ iStat += EqnTest( _T("2+b*3"), b*3+2, true);\r
+ iStat += EqnTest( _T("2+3*b"), b*3+2, true);\r
+ iStat += EqnTest( _T("b+3*b"), b+3*b, true);\r
+ iStat += EqnTest( _T("3*b+b"), b+3*b, true);\r
+\r
+ iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true);\r
+ iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true);\r
+\r
+ iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true);\r
+ iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true);\r
+\r
+ // operator precedencs\r
+ iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true);\r
+ iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true);\r
+ iStat += EqnTest( _T("1+2*3"), 7, true);\r
+ iStat += EqnTest( _T("1+2*3"), 7, true);\r
+ iStat += EqnTest( _T("(1+2)*3"), 9, true);\r
+ iStat += EqnTest( _T("(1+2)*(-3)"), -9, true);\r
+ iStat += EqnTest( _T("2/4"), 0.5, true);\r
+\r
+ iStat += EqnTest( _T("exp(ln(7))"), 7, true);\r
+ iStat += EqnTest( _T("e^ln(7)"), 7, true);\r
+ iStat += EqnTest( _T("e^(ln(7))"), 7, true);\r
+ iStat += EqnTest( _T("(e^(ln(7)))"), 7, true);\r
+ iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true);\r
+ iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true);\r
+ iStat += EqnTest( _T("10^log(5)"), 5, true);\r
+ iStat += EqnTest( _T("10^log10(5)"), 5, true);\r
+ iStat += EqnTest( _T("2^log2(4)"), 4, true);\r
+ iStat += EqnTest( _T("-(sin(0)+1)"), -1, true);\r
+ iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true);\r
+\r
+ iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true);\r
+ iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true);\r
+ iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true);\r
+ iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest(\r
+ _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))")\r
+ _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/")\r
+ _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-")\r
+ _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6")\r
+ _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e")\r
+ _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest(\r
+ _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e")\r
+ _T(")+a)))*2.77)"), -2.16995656, true);\r
+\r
+ // long formula (Reference: Matlab)\r
+ iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);\r
+ \r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl; \r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestIfThenElse()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing if-then-else operator...");\r
+\r
+ // Test error detection\r
+ iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); \r
+ iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); \r
+ iStat += ThrowTest(_T("(a<b) ? (b<c) ? 1 : 2"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? 1"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? a"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("(a<b) ? a+b"), ecMISSING_ELSE_CLAUSE); \r
+ iStat += ThrowTest(_T("a : b"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("1 : 2"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("(1) ? 1 : 2 : 3"), ecMISPLACED_COLON); \r
+ iStat += ThrowTest(_T("(true) ? 1 : 2 : 3"), ecUNASSIGNABLE_TOKEN); \r
+\r
+ iStat += EqnTest(_T("1 ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("a<b ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(a<b) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(1) ? 10 : 11"), 10, true);\r
+ iStat += EqnTest(_T("(0) ? 10 : 11"), 11, true);\r
+ iStat += EqnTest(_T("(1) ? a+b : c+d"), 3, true);\r
+ iStat += EqnTest(_T("(0) ? a+b : c+d"), 1, true);\r
+ iStat += EqnTest(_T("(1) ? 0 : 1"), 0, true);\r
+ iStat += EqnTest(_T("(0) ? 0 : 1"), 1, true);\r
+ iStat += EqnTest(_T("(a<b) ? 10 : 11"), 10, true);\r
+ iStat += EqnTest(_T("(a>b) ? 10 : 11"), 11, true);\r
+ iStat += EqnTest(_T("(a<b) ? c : d"), 3, true);\r
+ iStat += EqnTest(_T("(a>b) ? c : d"), -2, true);\r
+\r
+ iStat += EqnTest(_T("(a>b) ? 1 : 0"), 0, true);\r
+ iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true);\r
+ iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true);\r
+ iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true);\r
+\r
+ iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true);\r
+ iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true);\r
+ iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true);\r
+ iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true);\r
+ iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true);\r
+ iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)"), 6, true);\r
+ iStat += EqnTest(_T("10*sum(3, (a>b) ? 3 : 10)"), 130, true);\r
+ iStat += EqnTest(_T("10*sum(3, (a<b) ? 3 : 10)"), 60, true);\r
+ iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)*10"), 130, true);\r
+ iStat += EqnTest(_T("sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
+ iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 60, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10)*10 : 99"), 99, true);\r
+ iStat += EqnTest(_T("(a<b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 360, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : 99"), 99, true);\r
+ iStat += EqnTest(_T("(a>b) ? sum(3, (a<b) ? 3 : 10,10,20)*10 : sum(3, (a<b) ? 3 : 10)*10"), 60, true);\r
+\r
+ // todo: auch für muParserX hinzufügen!\r
+ iStat += EqnTest(_T("(a<b)&&(a<b) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(a>b)&&(a<b) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("(1<2)&&(1<2) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("(1>2)&&(1<2) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true);\r
+ iStat += EqnTest(_T("((a<b)&&(a<b)) ? 128 : 255"), 128, true);\r
+ iStat += EqnTest(_T("((a>b)&&(a<b)) ? 128 : 255"), 255, true);\r
+\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true);\r
+ iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true);\r
+ iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true);\r
+ iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true);\r
+ iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true);\r
+ iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true);\r
+\r
+ // assignment operators\r
+ iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true);\r
+ iStat += EqnTest(_T("a=((a>b)&&(a<b)) ? 128 : 255, a"), 255, true);\r
+ iStat += EqnTest(_T("c=(a<b)&&(a<b) ? 128 : 255, c"), 128, true);\r
+ iStat += EqnTest(_T("0 ? a=a+1 : 666, a"), 1, true);\r
+ iStat += EqnTest(_T("1?a=10:a=20, a"), 10, true);\r
+ iStat += EqnTest(_T("0?a=10:a=20, a"), 20, true);\r
+ iStat += EqnTest(_T("0?a=sum(3,4):10, a"), 1, true); // a should not change its value due to lazy calculation\r
+ \r
+ iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true);\r
+ iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true);\r
+ iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true);\r
+ iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true);\r
+\r
+ iStat += EqnTest(_T("a=1?5:b=1?3:4, a"), 5, true);\r
+ iStat += EqnTest(_T("a=1?5:b=1?3:4, b"), 2, true);\r
+ iStat += EqnTest(_T("a=0?5:b=1?3:4, a"), 3, true);\r
+ iStat += EqnTest(_T("a=0?5:b=1?3:4, b"), 3, true);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl; \r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::TestException()\r
+ {\r
+ int iStat = 0;\r
+ mu::console() << _T("testing error codes...");\r
+\r
+ iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);\r
+ iStat += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("3+()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest(_T("sin(3,4)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest(_T("(1+2"), ecMISSING_PARENS);\r
+ iStat += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL);\r
+ iStat += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN);\r
+ iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);\r
+ iStat += ThrowTest(_T("a+b+c=10"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest(_T("a=b=3"), ecUNEXPECTED_OPERATOR);\r
+\r
+#if defined(MUP_MATH_EXCEPTIONS)\r
+ // divide by zero whilst constant folding\r
+ iStat += ThrowTest(_T("1/0"), ecDIV_BY_ZERO);\r
+ // square root of a negative number\r
+ iStat += ThrowTest(_T("sqrt(-1)"), ecDOMAIN_ERROR);\r
+ // logarithms of zero\r
+ iStat += ThrowTest(_T("ln(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log2(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log10(0)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log(0)"), ecDOMAIN_ERROR);\r
+ // logarithms of negative values\r
+ iStat += ThrowTest(_T("ln(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log2(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log10(-1)"), ecDOMAIN_ERROR);\r
+ iStat += ThrowTest(_T("log(-1)"), ecDOMAIN_ERROR);\r
+#endif\r
+\r
+ // functions without parameter\r
+ iStat += ThrowTest( _T("3+ping(2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(a+2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(sin(a)+2)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("3+ping(1+sin(a))"), ecTOO_MANY_PARAMS);\r
+\r
+ // String function related\r
+ iStat += ThrowTest( _T("valueof(\"xxx\")"), 999, false);\r
+ iStat += ThrowTest( _T("valueof()"), ecUNEXPECTED_PARENS);\r
+ iStat += ThrowTest( _T("1+valueof(\"abc\""), ecMISSING_PARENS);\r
+ iStat += ThrowTest( _T("valueof(\"abc\""), ecMISSING_PARENS);\r
+ iStat += ThrowTest( _T("valueof(\"abc"), ecUNTERMINATED_STRING);\r
+ iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("valueof(3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("sin(\"abc\")"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"), 999, false);\r
+ iStat += ThrowTest( _T("\"hello world\""), ecSTR_RESULT);\r
+ iStat += ThrowTest( _T("(\"hello world\")"), ecSTR_RESULT);\r
+ iStat += ThrowTest( _T("\"abcd\"+100"), ecOPRT_TYPE_CONFLICT);\r
+ iStat += ThrowTest( _T("\"a\"+\"b\""), ecOPRT_TYPE_CONFLICT);\r
+ iStat += ThrowTest( _T("strfun1(\"100\",3)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(\"100\",3,5)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(\"100\")"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(\"100\",6)"), ecTOO_FEW_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(1,1)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun2(a,1)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun2(1,1,1)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun2(a,1,1)"), ecTOO_MANY_PARAMS);\r
+ iStat += ThrowTest( _T("strfun3(1,2,3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(1, \"100\",3)"), ecSTRING_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"), ecVAL_EXPECTED);\r
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"), ecTOO_MANY_PARAMS);\r
+\r
+ // assignement operator\r
+ iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR);\r
+\r
+ // <ibg 20090529>\r
+ // this is now legal, for reference see:\r
+ // https://sourceforge.net/forum/message.php?msg_id=7411373\r
+ // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); \r
+ // </ibg>\r
+\r
+ iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR);\r
+ iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);\r
+\r
+ if (iStat==0) \r
+ mu::console() << _T("passed") << endl;\r
+ else \r
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;\r
+\r
+ return iStat;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTester::AddTest(testfun_type a_pFun)\r
+ {\r
+ m_vTestFun.push_back(a_pFun);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTester::Run()\r
+ {\r
+ int iStat = 0;\r
+ try\r
+ {\r
+ for (int i=0; i<(int)m_vTestFun.size(); ++i)\r
+ iStat += (this->*m_vTestFun[i])();\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ mu::console() << "\n" << e.GetMsg() << endl;\r
+ mu::console() << e.GetToken() << endl;\r
+ Abort();\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << e.what() << endl;\r
+ Abort();\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << "Internal error";\r
+ Abort();\r
+ }\r
+\r
+ if (iStat==0) \r
+ {\r
+ mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl;\r
+ }\r
+ else \r
+ {\r
+ mu::console() << "Test failed with " << iStat \r
+ << " errors (" << ParserTester::c_iCount \r
+ << " expressions)" << endl;\r
+ }\r
+ ParserTester::c_iCount = 0;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)\r
+ {\r
+ ParserTester::c_iCount++;\r
+\r
+ try\r
+ {\r
+ value_type fVal[] = {1,1,1};\r
+ Parser p;\r
+\r
+ p.DefineVar( _T("a"), &fVal[0]);\r
+ p.DefineVar( _T("b"), &fVal[1]);\r
+ p.DefineVar( _T("c"), &fVal[2]);\r
+ p.DefinePostfixOprt( _T("{m}"), Milli);\r
+ p.DefinePostfixOprt( _T("m"), Milli);\r
+ p.DefineFun( _T("ping"), Ping);\r
+ p.DefineFun( _T("valueof"), ValueOf);\r
+ p.DefineFun( _T("strfun1"), StrFun1);\r
+ p.DefineFun( _T("strfun2"), StrFun2);\r
+ p.DefineFun( _T("strfun3"), StrFun3);\r
+ p.SetExpr(a_str);\r
+ p.Eval();\r
+ }\r
+ catch(ParserError &e)\r
+ {\r
+ // output the formula in case of an failed test\r
+ if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )\r
+ {\r
+ mu::console() << _T("\n ") \r
+ << _T("Expression: ") << a_str \r
+ << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")")\r
+ << _T(" Expected:") << a_iErrc;\r
+ }\r
+\r
+ return (a_iErrc==e.GetCode()) ? 0 : 1;\r
+ }\r
+\r
+ // if a_bFail==false no exception is expected\r
+ bool bRet((a_bFail==false) ? 0 : 1);\r
+ if (bRet==1)\r
+ {\r
+ mu::console() << _T("\n ") \r
+ << _T("Expression: ") << a_str \r
+ << _T(" did evaluate; Expected error:") << a_iErrc;\r
+ }\r
+\r
+ return bRet; \r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate a tet expression. \r
+\r
+ \return 1 in case of a failure, 0 otherwise.\r
+ */\r
+ int ParserTester::EqnTestWithVarChange(const string_type &a_str, \r
+ double a_fVar1, \r
+ double a_fRes1, \r
+ double a_fVar2, \r
+ double a_fRes2)\r
+ {\r
+ ParserTester::c_iCount++;\r
+ value_type fVal[2] = {-999, -999 }; // should be equalinitially\r
+\r
+ try\r
+ {\r
+ Parser p;\r
+\r
+ // variable\r
+ value_type var = 0;\r
+ p.DefineVar( _T("a"), &var);\r
+ p.SetExpr(a_str);\r
+\r
+ var = a_fVar1;\r
+ fVal[0] = p.Eval();\r
+\r
+ var = a_fVar2;\r
+ fVal[1] = p.Eval();\r
+ \r
+ if ( fabs(a_fRes1-fVal[0]) > 0.0000000001)\r
+ throw std::runtime_error("incorrect result (first pass)");\r
+\r
+ if ( fabs(a_fRes2-fVal[1]) > 0.0000000001)\r
+ throw std::runtime_error("incorrect result (second pass)");\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
+ return 1;\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
+ return 1; // always return a failure since this exception is not expected\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ return 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Evaluate a tet expression. \r
+\r
+ \return 1 in case of a failure, 0 otherwise.\r
+ */\r
+ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)\r
+ {\r
+ ParserTester::c_iCount++;\r
+ int iRet(0);\r
+ value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different\r
+\r
+ try\r
+ {\r
+ std::auto_ptr<Parser> p1;\r
+ Parser p2, p3; // three parser objects\r
+ // they will be used for testing copy and assihnment operators\r
+ // p1 is a pointer since i'm going to delete it in order to test if\r
+ // parsers after copy construction still refer to members of it.\r
+ // !! If this is the case this function will crash !!\r
+ \r
+ p1.reset(new mu::Parser()); \r
+ // Add constants\r
+ p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI);\r
+ p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E);\r
+ p1->DefineConst( _T("const"), 1);\r
+ p1->DefineConst( _T("const1"), 2);\r
+ p1->DefineConst( _T("const2"), 3);\r
+ // variables\r
+ value_type vVarVal[] = { 1, 2, 3, -2};\r
+ p1->DefineVar( _T("a"), &vVarVal[0]);\r
+ p1->DefineVar( _T("aa"), &vVarVal[1]);\r
+ p1->DefineVar( _T("b"), &vVarVal[1]);\r
+ p1->DefineVar( _T("c"), &vVarVal[2]);\r
+ p1->DefineVar( _T("d"), &vVarVal[3]);\r
+ \r
+ // custom value ident functions\r
+ p1->AddValIdent(&ParserTester::IsHexVal); \r
+\r
+ // functions\r
+ p1->DefineFun( _T("ping"), Ping);\r
+ p1->DefineFun( _T("f1of1"), f1of1); // one parameter\r
+ p1->DefineFun( _T("f1of2"), f1of2); // two parameter\r
+ p1->DefineFun( _T("f2of2"), f2of2);\r
+ p1->DefineFun( _T("f1of3"), f1of3); // three parameter\r
+ p1->DefineFun( _T("f2of3"), f2of3);\r
+ p1->DefineFun( _T("f3of3"), f3of3);\r
+ p1->DefineFun( _T("f1of4"), f1of4); // four parameter\r
+ p1->DefineFun( _T("f2of4"), f2of4);\r
+ p1->DefineFun( _T("f3of4"), f3of4);\r
+ p1->DefineFun( _T("f4of4"), f4of4);\r
+ p1->DefineFun( _T("f1of5"), f1of5); // five parameter\r
+ p1->DefineFun( _T("f2of5"), f2of5);\r
+ p1->DefineFun( _T("f3of5"), f3of5);\r
+ p1->DefineFun( _T("f4of5"), f4of5);\r
+ p1->DefineFun( _T("f5of5"), f5of5);\r
+\r
+ // binary operators\r
+ p1->DefineOprt( _T("add"), add, 0);\r
+ p1->DefineOprt( _T("++"), add, 0);\r
+ p1->DefineOprt( _T("&"), land, prLAND);\r
+\r
+ // sample functions\r
+ p1->DefineFun( _T("min"), Min);\r
+ p1->DefineFun( _T("max"), Max);\r
+ p1->DefineFun( _T("sum"), Sum);\r
+ p1->DefineFun( _T("valueof"), ValueOf);\r
+ p1->DefineFun( _T("atof"), StrToFloat);\r
+ p1->DefineFun( _T("strfun1"), StrFun1);\r
+ p1->DefineFun( _T("strfun2"), StrFun2);\r
+ p1->DefineFun( _T("strfun3"), StrFun3);\r
+ p1->DefineFun( _T("lastArg"), LastArg);\r
+ p1->DefineFun( _T("firstArg"), FirstArg);\r
+ p1->DefineFun( _T("order"), FirstArg);\r
+\r
+ // infix / postfix operator\r
+ // Note: Identifiers used here do not have any meaning \r
+ // they are mere placeholders to test certain features.\r
+ p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority\r
+ p1->DefineInfixOprt( _T("~"), plus2); // high priority\r
+ p1->DefineInfixOprt( _T("~~"), plus2);\r
+ p1->DefinePostfixOprt( _T("{m}"), Milli);\r
+ p1->DefinePostfixOprt( _T("{M}"), Mega);\r
+ p1->DefinePostfixOprt( _T("m"), Milli);\r
+ p1->DefinePostfixOprt( _T("meg"), Mega);\r
+ p1->DefinePostfixOprt( _T("#"), times3);\r
+ p1->DefinePostfixOprt( _T("'"), sqr); \r
+ p1->SetExpr(a_str);\r
+\r
+ // Test bytecode integrity\r
+ // String parsing and bytecode parsing must yield the same result\r
+ fVal[0] = p1->Eval(); // result from stringparsing\r
+ fVal[1] = p1->Eval(); // result from bytecode\r
+ if (fVal[0]!=fVal[1])\r
+ throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") );\r
+\r
+ // Test copy and assignement operators\r
+ try\r
+ {\r
+ // Test copy constructor\r
+ std::vector<mu::Parser> vParser;\r
+ vParser.push_back(*(p1.get()));\r
+ mu::Parser p2 = vParser[0]; // take parser from vector\r
+ \r
+ // destroy the originals from p2\r
+ vParser.clear(); // delete the vector\r
+ p1.reset(0);\r
+\r
+ fVal[2] = p2.Eval();\r
+\r
+ // Test assignement operator\r
+ // additionally disable Optimizer this time\r
+ mu::Parser p3;\r
+ p3 = p2;\r
+ p3.EnableOptimizer(false);\r
+ fVal[3] = p3.Eval();\r
+\r
+ // Test Eval function for multiple return values\r
+ // use p2 since it has the optimizer enabled!\r
+ int nNum;\r
+ value_type *v = p2.Eval(nNum);\r
+ fVal[4] = v[nNum-1];\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n ") << e.what() << _T("\n");\r
+ }\r
+\r
+ // limited floating point accuracy requires the following test\r
+ bool bCloseEnough(true);\r
+ for (unsigned i=0; i<sizeof(fVal)/sizeof(value_type); ++i)\r
+ {\r
+ bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.00001));\r
+\r
+ // The tests equations never result in infinity, if they do thats a bug.\r
+ // reference:\r
+ // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825\r
+ if (numeric_limits<value_type>::has_infinity)\r
+ bCloseEnough &= (fabs(fVal[i]) != numeric_limits<value_type>::infinity());\r
+ }\r
+\r
+ iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;\r
+ \r
+ \r
+ if (iRet==1)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() \r
+ << _T(" (incorrect result; expected: ") << a_fRes\r
+ << _T(" ;calculated: ") << fVal[0] << _T(",") \r
+ << fVal[1] << _T(",")\r
+ << fVal[2] << _T(",")\r
+ << fVal[3] << _T(",")\r
+ << fVal[4] << _T(").");\r
+ }\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ if (a_fPass)\r
+ {\r
+ if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)");\r
+ else\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");\r
+ return 1;\r
+ }\r
+ }\r
+ catch(std::exception &e)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");\r
+ return 1; // always return a failure since this exception is not expected\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ return 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return iRet;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)\r
+ {\r
+ ParserTester::c_iCount++;\r
+\r
+ value_type vVarVal[] = {1, 2, 3}; // variable values\r
+ value_type fVal[2] = {-99, -999}; // results: initially should be different\r
+ int iRet(0);\r
+\r
+ try\r
+ {\r
+ ParserInt p;\r
+ p.DefineConst( _T("const1"), 1);\r
+ p.DefineConst( _T("const2"), 2);\r
+ p.DefineVar( _T("a"), &vVarVal[0]);\r
+ p.DefineVar( _T("b"), &vVarVal[1]);\r
+ p.DefineVar( _T("c"), &vVarVal[2]);\r
+\r
+ p.SetExpr(a_str);\r
+ fVal[0] = p.Eval(); // result from stringparsing\r
+ fVal[1] = p.Eval(); // result from bytecode\r
+\r
+ if (fVal[0]!=fVal[1])\r
+ throw Parser::exception_type( _T("Bytecode corrupt.") );\r
+\r
+ iRet = ( (a_fRes==fVal[0] && a_fPass) || \r
+ (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;\r
+ if (iRet==1)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() \r
+ << _T(" (incorrect result; expected: ") << a_fRes \r
+ << _T(" ;calculated: ") << fVal[0]<< _T(").");\r
+ }\r
+ }\r
+ catch(Parser::exception_type &e)\r
+ {\r
+ if (a_fPass)\r
+ {\r
+ mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg();\r
+ iRet = 1;\r
+ }\r
+ }\r
+ catch(...)\r
+ {\r
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");\r
+ iRet = 1; // exceptions other than ParserException are not allowed\r
+ }\r
+\r
+ return iRet;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Internal error in test class Test is going to be aborted. */\r
+ void ParserTester::Abort() const\r
+ {\r
+ mu::console() << _T("Test failed (internal error in test class)") << endl;\r
+ while (!getchar());\r
+ exit(-1);\r
+ }\r
+ } // namespace test\r
+} // namespace mu\r
--- /dev/null
+/*\r
+ __________ \r
+ _____ __ __\______ \_____ _______ ______ ____ _______ \r
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \\r
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/\r
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| \r
+ \/ \/ \/ \/ \r
+ Copyright (C) 2013 Ingo Berg\r
+\r
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this \r
+ software and associated documentation files (the "Software"), to deal in the Software\r
+ without restriction, including without limitation the rights to use, copy, modify, \r
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to \r
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:\r
+\r
+ The above copyright notice and this permission notice shall be included in all copies or \r
+ substantial portions of the Software.\r
+\r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\r
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \r
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \r
+*/\r
+#include <cassert>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <map>\r
+#include <stack>\r
+#include <string>\r
+\r
+#include "muParserTokenReader.h"\r
+#include "muParserBase.h"\r
+\r
+/** \file\r
+ \brief This file contains the parser token reader implementation.\r
+*/\r
+\r
+\r
+namespace mu\r
+{\r
+\r
+ // Forward declaration\r
+ class ParserBase;\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Copy constructor.\r
+\r
+ \sa Assign\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) \r
+ { \r
+ Assign(a_Reader);\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assignement operator.\r
+\r
+ Self assignement will be suppressed otherwise #Assign is called.\r
+\r
+ \param a_Reader Object to copy to this token reader.\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) \r
+ {\r
+ if (&a_Reader!=this)\r
+ Assign(a_Reader);\r
+\r
+ return *this;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Assign state of a token reader to this token reader. \r
+ \r
+ \param a_Reader Object from which the state should be copied.\r
+ \throw nothrow\r
+ */\r
+ void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)\r
+ {\r
+ m_pParser = a_Reader.m_pParser;\r
+ m_strFormula = a_Reader.m_strFormula;\r
+ m_iPos = a_Reader.m_iPos;\r
+ m_iSynFlags = a_Reader.m_iSynFlags;\r
+ \r
+ m_UsedVar = a_Reader.m_UsedVar;\r
+ m_pFunDef = a_Reader.m_pFunDef;\r
+ m_pConstDef = a_Reader.m_pConstDef;\r
+ m_pVarDef = a_Reader.m_pVarDef;\r
+ m_pStrVarDef = a_Reader.m_pStrVarDef;\r
+ m_pPostOprtDef = a_Reader.m_pPostOprtDef;\r
+ m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;\r
+ m_pOprtDef = a_Reader.m_pOprtDef;\r
+ m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;\r
+ m_vIdentFun = a_Reader.m_vIdentFun;\r
+ m_pFactory = a_Reader.m_pFactory;\r
+ m_pFactoryData = a_Reader.m_pFactoryData;\r
+ m_iBrackets = a_Reader.m_iBrackets;\r
+ m_cArgSep = a_Reader.m_cArgSep;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Constructor. \r
+ \r
+ Create a Token reader and bind it to a parser object. \r
+\r
+ \pre [assert] a_pParser may not be NULL\r
+ \post #m_pParser==a_pParser\r
+ \param a_pParent Parent parser object of the token reader.\r
+ */\r
+ ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)\r
+ :m_pParser(a_pParent)\r
+ ,m_strFormula()\r
+ ,m_iPos(0)\r
+ ,m_iSynFlags(0)\r
+ ,m_bIgnoreUndefVar(false)\r
+ ,m_pFunDef(NULL)\r
+ ,m_pPostOprtDef(NULL)\r
+ ,m_pInfixOprtDef(NULL)\r
+ ,m_pOprtDef(NULL)\r
+ ,m_pConstDef(NULL)\r
+ ,m_pStrVarDef(NULL)\r
+ ,m_pVarDef(NULL)\r
+ ,m_pFactory(NULL)\r
+ ,m_pFactoryData(NULL)\r
+ ,m_vIdentFun()\r
+ ,m_UsedVar()\r
+ ,m_fZero(0)\r
+ ,m_iBrackets(0)\r
+ ,m_lastTok()\r
+ ,m_cArgSep(',')\r
+ {\r
+ assert(m_pParser);\r
+ SetParent(m_pParser);\r
+ }\r
+ \r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create instance of a ParserTokenReader identical with this \r
+ and return its pointer. \r
+\r
+ This is a factory method the calling function must take care of the object destruction.\r
+\r
+ \return A new ParserTokenReader object.\r
+ \throw nothrow\r
+ */\r
+ ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const\r
+ {\r
+ std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));\r
+ ptr->SetParent(a_pParent);\r
+ return ptr.release();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok)\r
+ {\r
+ m_lastTok = tok;\r
+ return m_lastTok;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::AddValIdent(identfun_type a_pCallback)\r
+ {\r
+ // Use push_front is used to give user defined callbacks a higher priority than\r
+ // the built in ones. Otherwise reading hex numbers would not work\r
+ // since the "0" in "0xff" would always be read first making parsing of \r
+ // the rest impossible.\r
+ // reference:\r
+ // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956\r
+ m_vIdentFun.push_front(a_pCallback);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)\r
+ {\r
+ m_pFactory = a_pFactory;\r
+ m_pFactoryData = pUserData;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return the current position of the token reader in the formula string. \r
+\r
+ \return #m_iPos\r
+ \throw nothrow\r
+ */\r
+ int ParserTokenReader::GetPos() const\r
+ {\r
+ return m_iPos;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a reference to the formula. \r
+\r
+ \return #m_strFormula\r
+ \throw nothrow\r
+ */\r
+ const string_type& ParserTokenReader::GetExpr() const\r
+ {\r
+ return m_strFormula;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Return a map containing the used variables only. */\r
+ varmap_type& ParserTokenReader::GetUsedVar() \r
+ {\r
+ return m_UsedVar;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Initialize the token Reader. \r
+ \r
+ Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.\r
+ \pre [assert] triggered if a_szFormula==0\r
+ */\r
+ void ParserTokenReader::SetFormula(const string_type &a_strFormula)\r
+ {\r
+ m_strFormula = a_strFormula;\r
+ ReInit();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found. \r
+ \r
+ If true, the parser does not throw an exception if an undefined variable is found. \r
+ otherwise it does. This variable is used internally only!\r
+ It supresses a "undefined variable" exception in GetUsedVar(). \r
+ Those function should return a complete list of variables including \r
+ those the are not defined by the time of it's call.\r
+ */\r
+ void ParserTokenReader::IgnoreUndefVar(bool bIgnore)\r
+ {\r
+ m_bIgnoreUndefVar = bIgnore;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Reset the token reader to the start of the formula. \r
+\r
+ The syntax flags will be reset to a value appropriate for the \r
+ start of a formula.\r
+ \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR\r
+ \throw nothrow\r
+ \sa ESynCodes\r
+ */\r
+ void ParserTokenReader::ReInit()\r
+ {\r
+ m_iPos = 0;\r
+ m_iSynFlags = sfSTART_OF_LINE;\r
+ m_iBrackets = 0;\r
+ m_UsedVar.clear();\r
+ m_lastTok = token_type();\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Read the next token from the string. */ \r
+ ParserTokenReader::token_type ParserTokenReader::ReadNextToken()\r
+ {\r
+ assert(m_pParser);\r
+\r
+ std::stack<int> FunArgs;\r
+ const char_type *szFormula = m_strFormula.c_str();\r
+ token_type tok;\r
+\r
+ // Ignore all non printable characters when reading the expression\r
+ while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) \r
+ ++m_iPos;\r
+\r
+ if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula\r
+ if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator\r
+ if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token\r
+ if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens\r
+ if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators\r
+ if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens\r
+ if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens\r
+ if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables\r
+ if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens\r
+ if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators\r
+ if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators\r
+\r
+ // Check String for undefined variable token. Done only if a \r
+ // flag is set indicating to ignore undefined variables.\r
+ // This is a way to conditionally avoid an error if \r
+ // undefined variables occur. \r
+ // (The GetUsedVar function must suppress the error for\r
+ // undefined variables in order to collect all variable \r
+ // names including the undefined ones.)\r
+ if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) \r
+ return SaveBeforeReturn(tok);\r
+\r
+ // Check for unknown token\r
+ // \r
+ // !!! From this point on there is no exit without an exception possible...\r
+ // \r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd!=m_iPos)\r
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);\r
+\r
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));\r
+ return token_type(); // never reached\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetParent(ParserBase *a_pParent)\r
+ {\r
+ m_pParser = a_pParent; \r
+ m_pFunDef = &a_pParent->m_FunDef;\r
+ m_pOprtDef = &a_pParent->m_OprtDef;\r
+ m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;\r
+ m_pPostOprtDef = &a_pParent->m_PostOprtDef;\r
+ m_pVarDef = &a_pParent->m_VarDef;\r
+ m_pStrVarDef = &a_pParent->m_StrVarDef;\r
+ m_pConstDef = &a_pParent->m_ConstDef;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Extract all characters that belong to a certain charset.\r
+\r
+ \param a_szCharSet [in] Const char array of the characters allowed in the token. \r
+ \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.\r
+ \param a_iPos [in] Position in the string from where to start reading.\r
+ \return The Position of the first character not listed in a_szCharSet.\r
+ \throw nothrow\r
+ */\r
+ int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, \r
+ string_type &a_sTok, \r
+ int a_iPos) const\r
+ {\r
+ int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);\r
+\r
+ if (iEnd==(int)string_type::npos)\r
+ iEnd = (int)m_strFormula.length();\r
+ \r
+ // Assign token string if there was something found\r
+ if (a_iPos!=iEnd)\r
+ a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);\r
+\r
+ return iEnd;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check Expression for the presence of a binary operator token.\r
+ \r
+ Userdefined binary operator "++" gives inconsistent parsing result for\r
+ the equations "a++b" and "a ++ b" if alphabetic characters are allowed\r
+ in operator tokens. To avoid this this function checks specifically\r
+ for operator tokens.\r
+ */\r
+ int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, \r
+ int a_iPos) const\r
+ {\r
+ int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidInfixOprtChars(), a_iPos);\r
+ if (iEnd==(int)string_type::npos)\r
+ iEnd = (int)m_strFormula.length();\r
+\r
+ // Assign token string if there was something found\r
+ if (a_iPos!=iEnd)\r
+ {\r
+ a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);\r
+ return iEnd;\r
+ }\r
+ else\r
+ {\r
+ // There is still the chance of having to deal with an operator consisting exclusively\r
+ // of alphabetic characters.\r
+ return ExtractToken(MUP_CHARS, a_sTok, a_iPos);\r
+ }\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a built in operator or other token can be found\r
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
+ \return true if an operator token has been found.\r
+ */\r
+ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)\r
+ {\r
+ const char_type **const pOprtDef = m_pParser->GetOprtDef(),\r
+ *const szFormula = m_strFormula.c_str();\r
+\r
+ // Compare token with function and operator strings\r
+ // check string for operator/function\r
+ for (int i=0; pOprtDef[i]; i++)\r
+ {\r
+ std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );\r
+ if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )\r
+ {\r
+ switch(i)\r
+ {\r
+ //case cmAND:\r
+ //case cmOR:\r
+ //case cmXOR:\r
+ case cmLAND:\r
+ case cmLOR:\r
+ case cmLT:\r
+ case cmGT:\r
+ case cmLE:\r
+ case cmGE:\r
+ case cmNEQ: \r
+ case cmEQ:\r
+ case cmADD:\r
+ case cmSUB:\r
+ case cmMUL:\r
+ case cmDIV:\r
+ case cmPOW:\r
+ case cmASSIGN:\r
+ //if (len!=sTok.length())\r
+ // continue;\r
+\r
+ // The assignement operator need special treatment\r
+ if (i==cmASSIGN && m_iSynFlags & noASSIGN)\r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
+\r
+ if (!m_pParser->HasBuiltInOprt()) continue;\r
+ if (m_iSynFlags & noOPT) \r
+ {\r
+ // Maybe its an infix operator not an operator\r
+ // Both operator types can share characters in \r
+ // their identifiers\r
+ if ( IsInfixOpTok(a_Tok) ) \r
+ return true;\r
+\r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);\r
+ }\r
+\r
+ m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;\r
+ m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;\r
+ break;\r
+\r
+ case cmBO:\r
+ if (m_iSynFlags & noBO)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+ \r
+ if (m_lastTok.GetCode()==cmFUNC)\r
+ m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;\r
+ else\r
+ m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE;\r
+\r
+ ++m_iBrackets;\r
+ break;\r
+\r
+ case cmBC:\r
+ if (m_iSynFlags & noBC)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;\r
+\r
+ if (--m_iBrackets<0)\r
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);\r
+ break;\r
+\r
+ case cmELSE:\r
+ if (m_iSynFlags & noELSE)\r
+ Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
+ break;\r
+\r
+ case cmIF:\r
+ if (m_iSynFlags & noIF)\r
+ Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);\r
+\r
+ m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;\r
+ break;\r
+\r
+ default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...\r
+ Error(ecINTERNAL_ERROR);\r
+ } // switch operator id\r
+\r
+ m_iPos += (int)len;\r
+ a_Tok.Set( (ECmdCode)i, pOprtDef[i] );\r
+ return true;\r
+ } // if operator string found\r
+ } // end of for all operator strings\r
+ \r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ bool ParserTokenReader::IsArgSep(token_type &a_Tok)\r
+ {\r
+ const char_type* szFormula = m_strFormula.c_str();\r
+\r
+ if (szFormula[m_iPos]==m_cArgSep)\r
+ {\r
+ // copy the separator into null terminated string\r
+ char_type szSep[2];\r
+ szSep[0] = m_cArgSep;\r
+ szSep[1] = 0;\r
+\r
+ if (m_iSynFlags & noARG_SEP)\r
+ Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);\r
+\r
+ m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;\r
+ m_iPos++;\r
+ a_Tok.Set(cmARG_SEP, szSep);\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check for End of Formula.\r
+\r
+ \return true if an end of formula is found false otherwise.\r
+ \param a_Tok [out] If an eof is found the corresponding token will be stored there.\r
+ \throw nothrow\r
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok\r
+ */\r
+ bool ParserTokenReader::IsEOF(token_type &a_Tok)\r
+ {\r
+ const char_type* szFormula = m_strFormula.c_str();\r
+\r
+ // check for EOF\r
+ if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)\r
+ {\r
+ if ( m_iSynFlags & noEND )\r
+ Error(ecUNEXPECTED_EOF, m_iPos);\r
+\r
+ if (m_iBrackets>0)\r
+ Error(ecMISSING_PARENS, m_iPos, _T(")"));\r
+\r
+ m_iSynFlags = 0;\r
+ a_Tok.Set(cmEND);\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a unary infix operator. \r
+ \return true if a function token has been found false otherwise.\r
+ */\r
+ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)\r
+ {\r
+ string_type sTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // iteraterate over all postfix operator strings\r
+ funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();\r
+ for ( ; it!=m_pInfixOprtDef->rend(); ++it)\r
+ {\r
+ if (sTok.find(it->first)!=0)\r
+ continue;\r
+\r
+ a_Tok.Set(it->second, it->first);\r
+ m_iPos += (int)it->first.length();\r
+\r
+ if (m_iSynFlags & noINFIXOP) \r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+\r
+/*\r
+ a_Tok.Set(item->second, sTok);\r
+ m_iPos = (int)iEnd;\r
+\r
+ if (m_iSynFlags & noINFIXOP) \r
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; \r
+ return true;\r
+*/\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check whether the token at a given position is a function token.\r
+ \param a_Tok [out] If a value token is found it will be placed here.\r
+ \throw ParserException if Syntaxflags do not allow a function at a_iPos\r
+ \return true if a function token has been found false otherwise.\r
+ \pre [assert] m_pParser!=0\r
+ */\r
+ bool ParserTokenReader::IsFunTok(token_type &a_Tok)\r
+ {\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ funmap_type::const_iterator item = m_pFunDef->find(strTok);\r
+ if (item==m_pFunDef->end())\r
+ return false;\r
+\r
+ // Check if the next sign is an opening bracket\r
+ const char_type *szFormula = m_strFormula.c_str();\r
+ if (szFormula[iEnd]!='(')\r
+ return false;\r
+\r
+ a_Tok.Set(item->second, strTok);\r
+\r
+ m_iPos = (int)iEnd;\r
+ if (m_iSynFlags & noFUN)\r
+ Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());\r
+\r
+ m_iSynFlags = noANY ^ noBO;\r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a binary operator.\r
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.\r
+ \return true if an operator token has been found.\r
+ */\r
+ bool ParserTokenReader::IsOprt(token_type &a_Tok)\r
+ {\r
+ const char_type *const szExpr = m_strFormula.c_str();\r
+ string_type strTok;\r
+\r
+ int iEnd = ExtractOperatorToken(strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // Check if the operator is a built in operator, if so ignore it here\r
+ const char_type **const pOprtDef = m_pParser->GetOprtDef();\r
+ for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)\r
+ {\r
+ if (string_type(pOprtDef[i])==strTok)\r
+ return false;\r
+ }\r
+\r
+ // Note:\r
+ // All tokens in oprt_bin_maptype are have been sorted by their length\r
+ // Long operators must come first! Otherwise short names (like: "add") that\r
+ // are part of long token names (like: "add123") will be found instead \r
+ // of the long ones.\r
+ // Length sorting is done with ascending length so we use a reverse iterator here.\r
+ funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();\r
+ for ( ; it!=m_pOprtDef->rend(); ++it)\r
+ {\r
+ const string_type &sID = it->first;\r
+ if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )\r
+ {\r
+ a_Tok.Set(it->second, strTok);\r
+\r
+ // operator was found\r
+ if (m_iSynFlags & noOPT) \r
+ {\r
+ // An operator was found but is not expected to occur at\r
+ // this position of the formula, maybe it is an infix \r
+ // operator, not a binary operator. Both operator types\r
+ // can share characters in their identifiers.\r
+ if ( IsInfixOpTok(a_Tok) ) \r
+ return true;\r
+ else\r
+ {\r
+ // nope, no infix operator\r
+ return false;\r
+ //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); \r
+ }\r
+\r
+ }\r
+\r
+ m_iPos += (int)sID.length();\r
+ m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noBC | noASSIGN;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check if a string position contains a unary post value operator. */\r
+ bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)\r
+ {\r
+ // <ibg 20110629> Do not check for postfix operators if they are not allowed at\r
+ // the current expression index.\r
+ //\r
+ // This will fix the bug reported here: \r
+ //\r
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979\r
+ //\r
+ if (m_iSynFlags & noPOSTOP)\r
+ return false;\r
+ // </ibg>\r
+\r
+ // Tricky problem with equations like "3m+5":\r
+ // m is a postfix operator, + is a valid sign for postfix operators and \r
+ // for binary operators parser detects "m+" as operator string and \r
+ // finds no matching postfix operator.\r
+ // \r
+ // This is a special case so this routine slightly differs from the other\r
+ // token readers.\r
+ \r
+ // Test if there could be a postfix operator\r
+ string_type sTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ // iteraterate over all postfix operator strings\r
+ funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();\r
+ for ( ; it!=m_pPostOprtDef->rend(); ++it)\r
+ {\r
+ if (sTok.find(it->first)!=0)\r
+ continue;\r
+\r
+ a_Tok.Set(it->second, sTok);\r
+ m_iPos += (int)it->first.length();\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check whether the token at a given position is a value token.\r
+\r
+ Value tokens are either values or constants.\r
+\r
+ \param a_Tok [out] If a value token is found it will be placed here.\r
+ \return true if a value token has been found.\r
+ */\r
+ bool ParserTokenReader::IsValTok(token_type &a_Tok)\r
+ {\r
+ assert(m_pConstDef);\r
+ assert(m_pParser);\r
+\r
+ string_type strTok;\r
+ value_type fVal(0);\r
+ int iEnd(0);\r
+ \r
+ // 2.) Check for user defined constant\r
+ // Read everything that could be a constant name\r
+ iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd!=m_iPos)\r
+ {\r
+ valmap_type::const_iterator item = m_pConstDef->find(strTok);\r
+ if (item!=m_pConstDef->end())\r
+ {\r
+ m_iPos = iEnd;\r
+ a_Tok.SetVal(item->second, strTok);\r
+\r
+ if (m_iSynFlags & noVAL)\r
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
+ return true;\r
+ }\r
+ }\r
+\r
+ // 3.call the value recognition functions provided by the user\r
+ // Call user defined value recognition functions\r
+ std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();\r
+ for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)\r
+ {\r
+ int iStart = m_iPos;\r
+ if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )\r
+ {\r
+ strTok.assign(m_strFormula.c_str(), iStart, m_iPos);\r
+ if (m_iSynFlags & noVAL)\r
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);\r
+\r
+ a_Tok.SetVal(fVal, strTok);\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is a variable token. \r
+ \param a_Tok [out] If a variable token has been found it will be placed here.\r
+ \return true if a variable token has been found.\r
+ */\r
+ bool ParserTokenReader::IsVarTok(token_type &a_Tok)\r
+ {\r
+ if (!m_pVarDef->size())\r
+ return false;\r
+\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ varmap_type::const_iterator item = m_pVarDef->find(strTok);\r
+ if (item==m_pVarDef->end())\r
+ return false;\r
+\r
+ if (m_iSynFlags & noVAR)\r
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
+\r
+ m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd);\r
+\r
+ m_iPos = iEnd;\r
+ a_Tok.SetVar(item->second, strTok);\r
+ m_UsedVar[item->first] = item->second; // Add variable to used-var-list\r
+\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR;\r
+\r
+// Zur Info hier die SynFlags von IsVal():\r
+// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; \r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)\r
+ {\r
+ if (!m_pStrVarDef || !m_pStrVarDef->size())\r
+ return false;\r
+\r
+ string_type strTok;\r
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);\r
+ if (iEnd==m_iPos)\r
+ return false;\r
+\r
+ strmap_type::const_iterator item = m_pStrVarDef->find(strTok);\r
+ if (item==m_pStrVarDef->end())\r
+ return false;\r
+\r
+ if (m_iSynFlags & noSTR)\r
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);\r
+\r
+ m_iPos = iEnd;\r
+ if (!m_pParser->m_vStringVarBuf.size())\r
+ Error(ecINTERNAL_ERROR);\r
+\r
+ a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );\r
+\r
+ m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP);\r
+ return true;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is an undefined variable. \r
+\r
+ \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.\r
+ \return true if a variable token has been found.\r
+ \throw nothrow\r
+ */\r
+ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)\r
+ {\r
+ string_type strTok;\r
+ int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );\r
+ if ( iEnd==m_iPos )\r
+ return false;\r
+\r
+ if (m_iSynFlags & noVAR)\r
+ {\r
+ // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the \r
+ // token identifier. \r
+ // related bug report:\r
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979\r
+ Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);\r
+ }\r
+\r
+ // If a factory is available implicitely create new variables\r
+ if (m_pFactory)\r
+ {\r
+ value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);\r
+ a_Tok.SetVar(fVar, strTok );\r
+\r
+ // Do not use m_pParser->DefineVar( strTok, fVar );\r
+ // in order to define the new variable, it will clear the\r
+ // m_UsedVar array which will kill previousely defined variables\r
+ // from the list\r
+ // This is safe because the new variable can never override an existing one\r
+ // because they are checked first!\r
+ (*m_pVarDef)[strTok] = fVar;\r
+ m_UsedVar[strTok] = fVar; // Add variable to used-var-list\r
+ }\r
+ else\r
+ {\r
+ a_Tok.SetVar((value_type*)&m_fZero, strTok);\r
+ m_UsedVar[strTok] = 0; // Add variable to used-var-list\r
+ }\r
+\r
+ m_iPos = iEnd;\r
+\r
+ // Call the variable factory in order to let it define a new parser variable\r
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;\r
+ return true;\r
+ }\r
+\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Check wheter a token at a given position is a string.\r
+ \param a_Tok [out] If a variable token has been found it will be placed here.\r
+ \return true if a string token has been found.\r
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok\r
+ \throw nothrow\r
+ */\r
+ bool ParserTokenReader::IsString(token_type &a_Tok)\r
+ {\r
+ if (m_strFormula[m_iPos]!='"') \r
+ return false;\r
+\r
+ string_type strBuf(&m_strFormula[m_iPos+1]);\r
+ std::size_t iEnd(0), iSkip(0);\r
+\r
+ // parser over escaped '\"' end replace them with '"'\r
+ for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd))\r
+ {\r
+ if (strBuf[iEnd-1]!='\\') break;\r
+ strBuf.replace(iEnd-1, 2, _T("\"") );\r
+ iSkip++;\r
+ }\r
+\r
+ if (iEnd==string_type::npos)\r
+ Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );\r
+\r
+ string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);\r
+\r
+ if (m_iSynFlags & noSTR)\r
+ Error(ecUNEXPECTED_STR, m_iPos, strTok);\r
+\r
+ m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer\r
+ a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());\r
+\r
+ m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen\r
+ m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );\r
+\r
+ return true;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ /** \brief Create an error containing the parse error position.\r
+\r
+ This function will create an Parser Exception object containing the error text and its position.\r
+\r
+ \param a_iErrc [in] The error code of type #EErrorCodes.\r
+ \param a_iPos [in] The position where the error was detected.\r
+ \param a_strTok [in] The token string representation associated with the error.\r
+ \throw ParserException always throws thats the only purpose of this function.\r
+ */\r
+ void ParserTokenReader::Error( EErrorCodes a_iErrc, \r
+ int a_iPos, \r
+ const string_type &a_sTok) const\r
+ {\r
+ m_pParser->Error(a_iErrc, a_iPos, a_sTok);\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ void ParserTokenReader::SetArgSep(char_type cArgSep)\r
+ {\r
+ m_cArgSep = cArgSep;\r
+ }\r
+\r
+ //---------------------------------------------------------------------------\r
+ char_type ParserTokenReader::GetArgSep() const\r
+ {\r
+ return m_cArgSep;\r
+ }\r
+} // namespace mu\r
+\r
-## ---------------------------------------------------------------------
+# ---------------------------------------------------------------------
## $Id$
##
## Copyright (C) 2013 by the deal.II authors
SET(BOOST_FOLDER "${CMAKE_SOURCE_DIR}/bundled/boost-1.49.0")
-#
-# FunctionParser project:
-#
-
-SET(FEATURE_FUNCTIONPARSER_HAVE_BUNDLED TRUE)
-
-OPTION(DEAL_II_FORCE_BUNDLED_FUNCTIONPARSER
- "Always use the bundled functionparser library instead of an external one."
- OFF)
-
-SET(FUNCTIONPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/functionparser/")
#
# Threading Building Blocks library
OFF)
SET(UMFPACK_FOLDER "${CMAKE_SOURCE_DIR}/bundled/umfpack")
+
+
+#
+# muparser
+#
+SET(FEATURE_MUPARSER_HAVE_BUNDLED TRUE)
+
+OPTION(DEAL_II_FORCE_BUNDLED_MUPARSER
+ "Always use the bundled functionparser library instead of an external one."
+ OFF)
+
+SET(MUPARSER_FOLDER "${CMAKE_SOURCE_DIR}/bundled/muparser_v2_2_3/")
# DEAL_II_WORDS_BIGENDIAN
# DEAL_II_HAVE_SSE2 *)
# DEAL_II_HAVE_AVX *)
+# DEAL_II_HAVE_AVX512 *)
# DEAL_II_COMPILER_VECTORIZATION_LEVEL
#
# *)
CHECK_CXX_SOURCE_RUNS(
"
#include <emmintrin.h>
- #include <mm_malloc.h>
int main()
{
__m128d a, b;
CHECK_CXX_SOURCE_RUNS(
"
#include <immintrin.h>
- #include <mm_malloc.h>
int main()
{
__m256d a, b;
}
"
DEAL_II_HAVE_AVX)
-ENDIF()
+ CHECK_CXX_SOURCE_RUNS(
+ "
+ #include <immintrin.h>
+ int main()
+ {
+ __m512d a, b;
+ const unsigned int vector_bytes = sizeof(__m512d);
+ const int n_vectors = vector_bytes/sizeof(double);
+ __m512d * data =
+ reinterpret_cast<__m512d*>(_mm_malloc (2*vector_bytes, vector_bytes));
+ double * ptr = reinterpret_cast<double*>(&a);
+ ptr[0] = (volatile double)(1.0);
+ for (int i=1; i<n_vectors; ++i)
+ ptr[i] = 0.0;
+ const volatile double x = 2.25;
+ b = _mm512_set_pd(x, x, x, x, x, x, x, x);
+ data[0] = _mm512_add_pd (a, b);
+ data[1] = _mm512_mul_pd (b, data[0]);
+ ptr = reinterpret_cast<double*>(&data[1]);
+ unsigned int return_value = 0;
+ if (ptr[0] != 7.3125)
+ return_value = 1;
+ for (int i=1; i<n_vectors; ++i)
+ if (ptr[i] != 5.0625)
+ return_value = 1;
+ _mm_free (data);
+ return return_value;
+ }
+ "
+ DEAL_II_HAVE_AVX512)
+ENDIF()
-IF(DEAL_II_HAVE_SSE2)
- IF(DEAL_II_HAVE_AVX)
- SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 2)
- ELSE()
- SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 1)
- ENDIF()
+IF(DEAL_II_HAVE_AVX512)
+ SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 3)
+ELSEIF(DEAL_II_HAVE_AVX)
+ SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 2)
+ELSEIF(DEAL_II_HAVE_SSE2)
+ SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 1)
ELSE()
SET(DEAL_II_COMPILER_VECTORIZATION_LEVEL 0)
ENDIF()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
ENDIF()
+#
+# Microsoft Visual C++ has a bug where the resulting object
+# from calling std::bind does not have a const operator(),
+# so we cannot pass such objects as const references as we
+# usually do with input arguments of other functions.
+#
+# - Wolfgang Bangerth, 2014
+#
+IF(DEAL_II_WITH_CXX11)
+ PUSH_CMAKE_REQUIRED("${DEAL_II_CXX11_FLAG}")
+ CHECK_CXX_COMPILER_BUG(
+ "
+ #include <functional>
+
+ void f(int, int) {}
+
+ template <typename F>
+ void g(const F &func)
+ {
+ func(1);
+ }
+
+ int main ()
+ {
+ g (std::bind(&f, std::placeholders::_1, 1));
+ }
+ "
+ DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ )
+ RESET_CMAKE_REQUIRED()
+ELSE()
+ CHECK_CXX_COMPILER_BUG(
+ "
+ #include <functional>
+ #include \"${BOOST_FOLDER}/include/boost/bind.hpp\"
+
+ void f(int, int) {}
+
+ template <typename F>
+ void g(const F &func)
+ {
+ func(1);
+ }
+
+ int main ()
+ {
+ using boost::bind;
+ using boost::reference_wrapper;
+
+ // now also import the _1, _2 placeholders from the global namespace
+ // into the current one as suggested above
+ using ::_1;
+
+ g (boost::bind(&f, boost::_1, 1));
+ }
+ "
+ DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ )
+ENDIF()
+
+
#
# in intel (at least 13.1 and 14), vectorization causes
# wrong code. See https://code.google.com/p/dealii/issues/detail?id=156
COND_SET_TO_YES(DEAL_II_WITH_FUNCTIONPARSER MAKEFILE_enableparser)
COND_SET_TO_YES(BUILD_SHARED_LIBS MAKEFILE_enableshared)
- COND_SET_TO_YES(DEAL_II_WITH_PETSC MAKEFILE_PETSC)
- COND_SET_TO_YES(DEAL_II_WITH_SLEPC MAKEFILE_SLEPC)
- COND_SET_TO_YES(DEAL_II_WITH_TRILINOS MAKEFILE_TRILINOS)
- COND_SET_TO_YES(DEAL_II_WITH_HDF5 MAKEFILE_HDF5)
+ COND_SET_TO_YES(DEAL_II_WITH_ARPACK MAKEFILE_ARPACK)
COND_SET_TO_YES(DEAL_II_WITH_BLAS MAKEFILE_BLAS)
- COND_SET_TO_YES(DEAL_II_WITH_MUMPS MAKEFILE_MUMPS)
+ COND_SET_TO_YES(DEAL_II_WITH_HDF5 MAKEFILE_HDF5)
COND_SET_TO_YES(DEAL_II_WITH_LAPACK MAKEFILE_LAPACK)
- COND_SET_TO_YES(DEAL_II_WITH_ARPACK MAKEFILE_ARPACK)
COND_SET_TO_YES(DEAL_II_WITH_METIS MAKEFILE_METIS)
- COND_SET_TO_YES(DEAL_II_WITH_UMFPACK MAKEFILE_UMFPACK)
- COND_SET_TO_YES(DEAL_II_WITH_P4EST MAKEFILE_P4EST)
COND_SET_TO_YES(DEAL_II_WITH_MPI MAKEFILE_MPI)
+ COND_SET_TO_YES(DEAL_II_WITH_MUMPS MAKEFILE_MUMPS)
+ COND_SET_TO_YES(DEAL_II_WITH_P4EST MAKEFILE_P4EST)
+ COND_SET_TO_YES(DEAL_II_WITH_PETSC MAKEFILE_PETSC)
+ COND_SET_TO_YES(DEAL_II_WITH_SLEPC MAKEFILE_SLEPC)
+ COND_SET_TO_YES(DEAL_II_WITH_TRILINOS MAKEFILE_TRILINOS)
+ COND_SET_TO_YES(DEAL_II_WITH_UMFPACK MAKEFILE_UMFPACK)
#
# For binary dir:
## ---------------------------------------------------------------------
#
-# Configuration for the zlib library:
+# Configuration for the bzip2 library:
#
-MACRO(FEATURE_BZIP2_FIND_EXTERNAL var)
- FIND_PACKAGE(BZip2)
-
- IF(BZIP2_FOUND)
- #
- # Rename variables:
- #
- SET(BZIP2_VERSION ${BZIP2_VERSION_STRING})
- SET(BZIP2_INCLUDE_DIRS ${BZIP2_INCLUDE_DIR})
-
- SET(${var} TRUE)
- ENDIF()
-ENDMACRO()
-
CONFIGURE_FEATURE(BZIP2)
#
MACRO(FEATURE_LAPACK_FIND_EXTERNAL var)
- FIND_PACKAGE(DEALII_LAPACK)
+ FIND_PACKAGE(LAPACK)
- IF(LAPACK_FOUND)
- SET(${var} TRUE)
- ENDIF()
-ENDMACRO()
-
-
-#
-# We do a fine grained check for availability of every single LAPACK
-# function we use. We have to ensure that this check is repeated every time
-# the lapack library or DEAL_II_WITH_LAPACK changes.
-#
-
-SET(DEAL_II_LAPACK_FUNCTIONS
- daxpy_ dgeev_ dgeevx_ dgelsd_ dgemm_ dgemv_ dgeqrf_ dgesdd_ dgesvd_
- dgetrf_ dgetri_ dgetrs_ dorgqr_ dormqr_ dstev_ dsyevx_ dsygv_ dsygvx_
- dtrtrs_ saxpy_ sgeev_ sgeevx_ sgelsd_ sgemm_ sgemv_ sgeqrf_ sgesdd_
- sgesvd_ sgetrf_ sgetri_ sgetrs_ sorgqr_ sormqr_ sstev_ ssyevx_ ssygv_
- ssygvx_ strtrs_
- )
-
-MACRO(CHECK_FOR_LAPACK_FUNCTIONS)
- #
- # Clear the test flags because the following test will use a C compiler
- #
- CLEAR_CMAKE_REQUIRED()
- SET(CMAKE_REQUIRED_FLAGS "${LAPACK_LINKER_FLAGS}")
- SET(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LIBRARIES})
#
- # Push -pthread as well:
+ # We do a check for availability of every single LAPACK function we use.
#
- ENABLE_IF_SUPPORTED(CMAKE_REQUIRED_FLAGS "-pthread")
+ IF(LAPACK_FOUND)
+ SET(${var} TRUE)
- IF(CMAKE_C_COMPILER_WORKS)
- FOREACH(_func ${DEAL_II_LAPACK_FUNCTIONS})
- STRING(TOUPPER ${_func} _func_uppercase)
- CHECK_FUNCTION_EXISTS(${_func} HAVE_${_func_uppercase})
- ENDFOREACH()
- ELSE()
- MESSAGE(STATUS
- "No suitable C compiler was found! Skipping LAPACK symbol check."
- )
- FOREACH(_func ${DEAL_II_LAPACK_FUNCTIONS})
- SET_IF_EMPTY(HAVE_${_func_uppercase} TRUE)
- ENDFOREACH()
+ #
+ # Clear the test flags because the following test will use a C compiler
+ #
+ CLEAR_CMAKE_REQUIRED()
+ SET(CMAKE_REQUIRED_FLAGS "${LAPACK_LINKER_FLAGS}")
+ SET(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LIBRARIES})
+ # Push -pthread as well:
+ ENABLE_IF_SUPPORTED(CMAKE_REQUIRED_FLAGS "-pthread")
+
+ IF(CMAKE_C_COMPILER_WORKS)
+
+ INCLUDE(CheckCSourceCompiles)
+ CHECK_C_SOURCE_COMPILES("
+ char daxpy_(); char dgeev_(); char dgeevx_(); char dgelsd_(); char
+ dgemm_(); char dgemv_(); char dgeqrf_(); char dgesdd_(); char
+ dgesvd_(); char dgetrf_(); char dgetri_(); char dgetrs_(); char
+ dorgqr_(); char dormqr_(); char dstev_(); char dsyevx_(); char
+ dsygv_(); char dsygvx_(); char dtrtrs_(); char saxpy_(); char
+ sgeev_(); char sgeevx_(); char sgelsd_(); char sgemm_(); char
+ sgemv_(); char sgeqrf_(); char sgesdd_(); char sgesvd_(); char
+ sgetrf_(); char sgetri_(); char sgetrs_(); char sorgqr_(); char
+ sormqr_(); char sstev_(); char ssyevx_(); char ssygv_(); char
+ ssygvx_(); char strtrs_();
+ int main(){
+ daxpy_ (); dgeev_ (); dgeevx_ (); dgelsd_ (); dgemm_ (); dgemv_ ();
+ dgeqrf_ (); dgesdd_ (); dgesvd_ (); dgetrf_ (); dgetri_ (); dgetrs_
+ (); dorgqr_ (); dormqr_ (); dstev_ (); dsyevx_ (); dsygv_ ();
+ dsygvx_ (); dtrtrs_ (); saxpy_ (); sgeev_ (); sgeevx_ (); sgelsd_
+ (); sgemm_ (); sgemv_ (); sgeqrf_ (); sgesdd_ (); sgesvd_ ();
+ sgetrf_ (); sgetri_ (); sgetrs_ (); sorgqr_ (); sormqr_ (); sstev_
+ (); ssyevx_ (); ssygv_ (); ssygvx_ (); strtrs_ ();
+
+ return 0;
+ }"
+ LAPACK_SYMBOL_CHECK)
+
+ IF(NOT LAPACK_SYMBOL_CHECK)
+ MESSAGE(STATUS
+ "Could not find a sufficient BLAS/LAPACK installation: "
+ "BLAS/LAPACK symbol check failed! Consult CMakeFiles/CMakeError.log "
+ "for further information."
+ )
+ SET(LAPACK_ADDITIONAL_ERROR_STRING
+ ${LAPACK_ADDITIONAL_ERROR_STRING}
+ "Could not find a sufficient BLAS/LAPACK installation: \n"
+ "BLAS/LAPACK symbol check failed! This usually means that your "
+ "BLAS/LAPACK installation is incomplete or the link line is "
+ "broken. Consult\n"
+ " CMakeFiles/CMakeError.log\n"
+ "for further information.\n"
+ )
+ SET(${var} FALSE)
+ ENDIF()
+ ELSE()
+ MESSAGE(STATUS
+ "No suitable C compiler was found! Skipping LAPACK symbol check."
+ )
+ ENDIF()
ENDIF()
-
- RESET_CMAKE_REQUIRED()
-ENDMACRO()
-
-
-MACRO(RESET_LAPACK_FUNCTIONS_CACHE)
- FOREACH(_func ${DEAL_II_LAPACK_FUNCTIONS})
- STRING(TOUPPER ${_func} _func_uppercase)
- UNSET(HAVE_${_func_uppercase} CACHE)
- ENDFOREACH()
-ENDMACRO()
-
-
-MACRO(FEATURE_LAPACK_CONFIGURE_EXTERNAL)
- CHECK_FOR_LAPACK_FUNCTIONS()
ENDMACRO()
CONFIGURE_FEATURE(LAPACK)
-
-#
-# Call RESET_LAPACK_FUNCTIONS_CHECK if DEAL_II_WITH_LAPACK is unset to
-# clean the configuration
-#
-IF(NOT DEAL_II_WITH_LAPACK)
- RESET_LAPACK_FUNCTIONS_CACHE()
-ENDIF()
#
# Configuration for mpi support:
#
-# We look for the C and Fortran libraries as well because they are needed
-# by some external libraries for the link interface:
-#
-
-MACRO(FEATURE_MPI_FIND_EXTERNAL var)
- #
- # Obey a manual user override: If MPI_CXX_FOUND is set to true in the
- # cache, we skip the FIND_PACKAGE calls:
- #
- IF(MPI_CXX_FOUND)
- SET(MPI_FOUND TRUE)
- ENDIF()
-
- #
- # If CMAKE_CXX_COMPILER is already an MPI wrapper, use it to determine
- # the mpi implementation. If MPI_CXX_COMPILER is defined use the value
- # directly.
- #
- SET_IF_EMPTY(MPI_CXX_COMPILER ${CMAKE_CXX_COMPILER})
- IF(CMAKE_C_COMPILER_WORKS)
- SET_IF_EMPTY(MPI_C_COMPILER ${CMAKE_C_COMPILER}) # for good measure
- ELSE()
- MESSAGE(STATUS
- "No suitable C compiler was found! MPI C interface can not be "
- "autodetected"
- )
- ENDIF()
- IF(CMAKE_Fortran_COMPILER_WORKS)
- SET_IF_EMPTY(MPI_Fortran_COMPILER ${CMAKE_Fortran_COMPILER}) # for good measure
- ELSE()
- MESSAGE(STATUS
- "No suitable Fortran compiler was found! MPI Fortran interface can "
- "not be autodetected"
- )
- ENDIF()
-
- FIND_PACKAGE(MPI)
-
- IF(NOT MPI_CXX_FOUND AND DEAL_II_WITH_MPI)
- #
- # CMAKE_CXX_COMPILER is apparently not an mpi wrapper.
- # So, let's be a bit more aggressive in finding MPI (and if
- # DEAL_II_WITH_MPI is set).
- #
- MESSAGE(STATUS
- "MPI not found but DEAL_II_WITH_MPI is set to TRUE."
- " Try again with more aggressive search paths:"
- )
- SET(MPI_FOUND) # clear this value so that FIND_PACKAGE runs again.
- UNSET(MPI_CXX_COMPILER CACHE)
- UNSET(MPI_C_COMPILER CACHE)
- UNSET(MPI_Fortran_COMPILER CACHE)
- FIND_PACKAGE(MPI)
- ENDIF()
-
- #
- # Manually clean up variables:
- #
- FOREACH(_lang C CXX Fortran)
- IF(MPI_${_lang}_LIBRARIES MATCHES "-NOTFOUND")
- SET(MPI_${_lang}_LIBRARIES)
- ENDIF()
- ENDFOREACH()
-
- IF(MPI_CXX_FOUND)
- #
- # Manually assemble some version information:
- #
- FIND_FILE(MPI_MPI_H NAMES mpi.h
- HINTS ${MPI_INCLUDE_PATH}
- )
-
- IF(NOT MPI_MPI_H MATCHES "-NOTFOUND" AND NOT DEFINED MPI_VERSION)
- FILE(STRINGS "${MPI_MPI_H}" MPI_VERSION_MAJOR_STRING
- REGEX "#define.*MPI_VERSION")
- STRING(REGEX REPLACE "^.*MPI_VERSION.*([0-9]+).*" "\\1"
- MPI_VERSION_MAJOR "${MPI_VERSION_MAJOR_STRING}"
- )
- FILE(STRINGS ${MPI_MPI_H} MPI_VERSION_MINOR_STRING
- REGEX "#define.*MPI_SUBVERSION")
- STRING(REGEX REPLACE "^.*MPI_SUBVERSION.*([0-9]+).*" "\\1"
- MPI_VERSION_MINOR "${MPI_VERSION_MINOR_STRING}"
- )
- SET(MPI_VERSION "${MPI_VERSION_MAJOR}.${MPI_VERSION_MINOR}")
- IF("${MPI_VERSION}" STREQUAL ".")
- SET(MPI_VERSION)
- SET(MPI_VERSION_MAJOR)
- SET(MPI_VERSION_MINOR)
- ENDIF()
-
- # OMPI specific version number:
- FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_MAJOR_STRING
- REGEX "#define.*OMPI_MAJOR_VERSION")
- STRING(REGEX REPLACE "^.*OMPI_MAJOR_VERSION.*([0-9]+).*" "\\1"
- OMPI_VERSION_MAJOR "${OMPI_VERSION_MAJOR_STRING}"
- )
- FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_MINOR_STRING
- REGEX "#define.*OMPI_MINOR_VERSION")
- STRING(REGEX REPLACE "^.*OMPI_MINOR_VERSION.*([0-9]+).*" "\\1"
- OMPI_VERSION_MINOR "${OMPI_VERSION_MINOR_STRING}"
- )
- FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_RELEASE_STRING
- REGEX "#define.*OMPI_RELEASE_VERSION")
- STRING(REGEX REPLACE "^.*OMPI_RELEASE_VERSION.*([0-9]+).*" "\\1"
- OMPI_VERSION_SUBMINOR "${OMPI_VERSION_RELEASE_STRING}"
- )
- SET(OMPI_VERSION
- "${OMPI_VERSION_MAJOR}.${OMPI_VERSION_MINOR}.${OMPI_VERSION_SUBMINOR}"
- )
- IF("${OMPI_VERSION}" STREQUAL "..")
- SET(OMPI_VERSION)
- SET(OMPI_VERSION_MAJOR)
- SET(OMPI_VERSION_MINOR)
- SET(OMPI_VERSION_SUBMINOR)
- ENDIF()
- ENDIF()
-
- SET(${var} TRUE)
- ENDIF()
-
- # Hide some variables:
- MARK_AS_ADVANCED(MPI_EXTRA_LIBRARY MPI_LIBRARY MPI_MPI_H)
-
- #
- # Populate correct variables:
- #
- SET(MPI_LIBRARIES ${MPI_CXX_LIBRARIES})
- SET(MPI_INCLUDE_DIRS ${MPI_CXX_INCLUDE_PATH})
- SET(MPI_CXX_FLAGS ${MPI_CXX_COMPILE_FLAGS})
- SET(MPI_LINKER_FLAGS "${MPI_CXX_LINK_FLAGS}")
-
-ENDMACRO()
-
MACRO(FEATURE_MPI_ERROR_MESSAGE)
MESSAGE(FATAL_ERROR "\n"
CONFIGURE_FEATURE(MPI)
-
-#
-# The user has to know the location of the mpi headers as well:
-#
-SET(MPI_USER_INCLUDE_DIRS ${MPI_INCLUDE_DIRS})
##
## ---------------------------------------------------------------------
-
#
# Configuration for thread support in deal.II with the help of the tbb
# library:
#
-
#
# Set up general threading:
# The macro will be included in CONFIGURE_FEATURE_THREADS_EXTERNAL/BUNDLED.
LIST(APPEND THREADS_LIBRARIES ${TBB_LIBRARIES})
LIST(APPEND THREADS_INCLUDE_DIRS ${TBB_INCLUDE_DIRS})
+ LIST(APPEND THREADS_USER_INCLUDE_DIRS ${TBB_USER_INCLUDE_DIRS})
ENDMACRO()
#
# TODO: Also necessary for external lib, use preference toggle
#
- FIND_SYSTEM_LIBRARY(dl_LIBRARY NAMES dl)
- MARK_AS_ADVANCED(dl_LIBRARY)
- IF(NOT dl_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND THREADS_LIBRARIES ${dl_LIBRARY})
- ENDIF()
+ LIST(APPEND THREADS_LIBRARIES ${CMAKE_DL_LIBS})
LIST(APPEND THREADS_BUNDLED_INCLUDE_DIRS ${TBB_FOLDER}/include)
ENDMACRO()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
#
CONFIGURE_FEATURE(ZLIB)
-
-# Export ZLIB_VERSION:
-IF(DEFINED ZLIB_VERSION_STRING)
- SET(ZLIB_VERSION ${ZLIB_VERSION_STRING})
-ENDIF()
##
## ---------------------------------------------------------------------
+SET(FEATURE_METIS_AFTER MPI)
+
#
# Configuration for the metis library:
#
FIND_PACKAGE(METIS)
IF(METIS_FOUND)
- IF(METIS_VERSION_MAJOR GREATER 4)
- SET(${var} TRUE)
- ELSE()
+ SET(${var} TRUE)
+
+ IF(NOT METIS_VERSION_MAJOR GREATER 4)
MESSAGE(STATUS "Insufficient metis installation found: "
"Version 5.x required!"
)
"Could not find a sufficient modern metis installation: "
"Version 5.x required!\n"
)
-
- UNSET(METIS_LIBRARY CACHE)
- UNSET(METIS_INCLUDE_DIR CACHE)
- SET(METIS_DIR "" CACHE PATH
- "An optional hint to a metis directory"
- )
- MARK_AS_ADVANCED(CLEAR METIS_DIR)
+ SET(${var} FALSE)
ENDIF()
+
+ CHECK_MPI_INTERFACE(METIS ${var})
ENDIF()
ENDMACRO()
ENDIF()
#
- # Trilinos has to be configured with 32bit indices if deal.II uses unsigned long
- # long int.
+ # Trilinos has to be configured with 32bit indices if deal.II uses unsigned int.
#
IF(TRILINOS_WITH_NO_32BIT_INDICES AND NOT DEAL_II_WITH_64BIT_INDICES)
MESSAGE(STATUS "deal.II was configured to use 32bit global indices but "
ENDIF()
ENDIF()
- ENDIF(TRILINOS_FOUND)
-
- IF(NOT ${var})
- UNSET(TRILINOS_CONFIG CACHE)
- SET(TRILINOS_DIR "" CACHE STRING
- "An optional hint to a Trilinos installation"
- )
- MARK_AS_ADVANCED(CLEAR TRILINOS_DIR)
+ CHECK_MPI_INTERFACE(TRILINOS ${var})
ENDIF()
-
ENDMACRO()
MACRO(FEATURE_TRILINOS_CONFIGURE_EXTERNAL)
-
- SET(TRILINOS_USER_INCLUDE_DIRS ${TRILINOS_INCLUDE_DIRS})
-
SET(DEAL_II_EXPAND_TRILINOS_VECTOR "TrilinosWrappers::Vector")
SET(DEAL_II_EXPAND_TRILINOS_BLOCKVECTOR "TrilinosWrappers::BlockVector")
SET(DEAL_II_EXPAND_TRILINOS_SPARSITY_PATTERN "TrilinosWrappers::SparsityPattern")
ENABLE_IF_SUPPORTED(TRILINOS_CXX_FLAGS "-Wno-unused")
ENABLE_IF_SUPPORTED(TRILINOS_CXX_FLAGS "-Wno-extra")
ENABLE_IF_SUPPORTED(TRILINOS_CXX_FLAGS "-Wno-overloaded-virtual")
-
ENDMACRO()
# Configuration for the umfpack library:
#
-SET(FEATURE_UMFPACK_DEPENDS DEAL_II_WITH_LAPACK)
+SET(FEATURE_UMFPACK_DEPENDS LAPACK)
MACRO(FEATURE_UMFPACK_CONFIGURE_BUNDLED)
SET(UMFPACK_BUNDLED_INCLUDE_DIRS
# Configuration for the petsc library:
#
+SET(FEATURE_PETSC_AFTER MPI)
-MACRO(FEATURE_PETSC_FIND_EXTERNAL var)
+MACRO(FEATURE_PETSC_FIND_EXTERNAL var)
FIND_PACKAGE(PETSC)
IF(PETSC_FOUND)
SET(${var} FALSE)
ENDIF()
-
#
# Petsc has to be configured with the same number of bits for indices as
# deal.II.
SET(${var} FALSE)
ENDIF()
- IF(NOT ${var})
- UNSET(PETSC_INCLUDE_DIR_ARCH CACHE)
- UNSET(PETSC_INCLUDE_DIR_COMMON CACHE)
- UNSET(PETSC_LIBRARY CACHE)
- UNSET(PETSC_PETSCVARIABLES CACHE)
- SET(PETSC_DIR "" CACHE PATH
- "An optional hint to a PETSc directory"
- )
- SET(PETSC_ARCH "" CACHE STRING
- "An optional hint to a PETSc arch"
- )
- MARK_AS_ADVANCED(CLEAR PETSC_DIR PETSC_ARCH)
- ENDIF()
+ CHECK_MPI_INTERFACE(PETSC ${var})
ENDIF()
ENDMACRO()
MACRO(FEATURE_PETSC_CONFIGURE_EXTERNAL)
-
- SET(PETSC_USER_INCLUDE_DIRS ${PETSC_INCLUDE_DIRS})
+ SET(DEAL_II_EXPAND_PETSC_VECTOR "PETScWrappers::Vector")
+ SET(DEAL_II_EXPAND_PETSC_BLOCKVECTOR "PETScWrappers::BlockVector")
+ SET(DEAL_II_EXPAND_PETSC_MPI_VECTOR "PETScWrappers::MPI::Vector")
+ SET(DEAL_II_EXPAND_PETSC_MPI_BLOCKVECTOR "PETScWrappers::MPI::BlockVector")
#
# Disable a bunch of warnings when compiling with petsc:
#
ENABLE_IF_SUPPORTED(PETSC_CXX_FLAGS "-Wno-long-long")
-
- SET(DEAL_II_EXPAND_PETSC_VECTOR "PETScWrappers::Vector")
- SET(DEAL_II_EXPAND_PETSC_BLOCKVECTOR "PETScWrappers::BlockVector")
- SET(DEAL_II_EXPAND_PETSC_MPI_VECTOR "PETScWrappers::MPI::Vector")
- SET(DEAL_II_EXPAND_PETSC_MPI_BLOCKVECTOR "PETScWrappers::MPI::BlockVector")
ENDMACRO()
# Configuration for the ARPACK library:
#
-SET(FEATURE_ARPACK_DEPENDS DEAL_II_WITH_LAPACK)
+SET(FEATURE_ARPACK_DEPENDS LAPACK)
CONFIGURE_FEATURE(ARPACK)
# Configuration for the boost library:
#
-#
-# This configure script has to be included after configure_threads.
-# We need some of the variables defined in SETUP_THREADING for
-# the setup of the bundled boost library (if used)
-#
-IF(NOT FEATURE_THREADS_PROCESSED)
- MESSAGE(FATAL_ERROR "\n"
- "Internal build system error:\n"
- "configure_boost.cmake included before configure_1_threads.cmake\n\n"
- )
-ENDIF()
-
-
SET(DEAL_II_WITH_BOOST ON # Always true. We need it :-]
CACHE BOOL "Build deal.II with support for boost." FORCE
)
-MACRO(FEATURE_BOOST_FIND_EXTERNAL var)
-
- #
- # This mumbo jumbo is necessary because CMake won't let us test against
- # BOOST_DIR directly. WTF?!
- #
- IF(NOT DEFINED BOOST_DIR)
- SET(BOOST_DIR "$ENV{BOOST_DIR}")
- ELSE()
- SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}")
- ENDIF()
-
- IF(NOT "${BOOST_DIR}" STREQUAL "")
- SET(BOOST_ROOT "${BOOST_DIR}")
- ENDIF()
-
- IF(DEAL_II_WITH_THREADS)
- SET(_boost_components iostreams serialization system thread)
- ELSE()
- SET(_boost_components iostreams serialization system)
- ENDIF()
-
- #
- # Prefer static libs if BUILD_SHARED_LIBS=OFF:
- #
- IF(NOT BUILD_SHARED_LIBS)
- SET(Boost_USE_STATIC_LIBS TRUE)
- ENDIF()
-
- FIND_PACKAGE(Boost 1.44 COMPONENTS ${_boost_components})
-
- #
- # Fall back to dynamic libraries if no static libraries could be found:
- #
- IF(NOT Boost_FOUND AND Boost_USE_STATIC_LIBS)
- SET(Boost_USE_STATIC_LIBS FALSE)
- FIND_PACKAGE(Boost 1.44 COMPONENTS ${_boost_components})
- ENDIF()
-
- MARK_AS_ADVANCED(Boost_DIR)
-
- IF(Boost_FOUND)
- SET(BOOST_VERSION_MAJOR "${Boost_MAJOR_VERSION}")
- SET(BOOST_VERSION_MINOR "${Boost_MINOR_VERSION}")
- SET(BOOST_VERSION_SUBMINOR "${Boost_SUBMINOR_VERSION}")
- SET(BOOST_VERSION
- "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}"
- )
-
- #
- # Remove "pthread" from Boost_LIBRARIES. Threading, if necessary, is
- # already set up via configure_1_threads.cmake.
- #
- LIST(REMOVE_ITEM Boost_LIBRARIES "pthread")
-
- SET(BOOST_INCLUDE_DIRS ${Boost_INCLUDE_DIRS})
- SET(BOOST_LIBRARIES ${Boost_LIBRARIES})
-
- MARK_AS_ADVANCED(BOOST_DIR)
-
- SET(${var} TRUE)
-
- ELSE()
-
- SET(BOOST_DIR "" CACHE PATH "An optional hint to a boost directory")
- ENDIF()
-ENDMACRO()
-
-
MACRO(FEATURE_BOOST_CONFIGURE_BUNDLED)
SET(BOOST_BUNDLED_INCLUDE_DIRS ${BOOST_FOLDER}/include)
ENDMACRO()
CONFIGURE_FEATURE(BOOST)
-#
-# The user has to know the location of the boost headers as well:
-#
-SET(BOOST_USER_INCLUDE_DIRS ${BOOST_INCLUDE_DIRS})
#
# DEAL_II_WITH_BOOST is always required.
+++ /dev/null
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2012 - 2014 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE at
-## the top level of the deal.II distribution.
-##
-## ---------------------------------------------------------------------
-
-#
-# Configuration for functionparser
-#
-
-MACRO(FEATURE_FUNCTIONPARSER_FIND_EXTERNAL var)
- MESSAGE(STATUS
- "No module available for finding functionparser externally."
- )
-ENDMACRO()
-
-
-MACRO(FEATURE_FUNCTIONPARSER_CONFIGURE_BUNDLED)
- SET(FUNCTIONPARSER_BUNDLED_INCLUDE_DIRS ${FUNCTIONPARSER_FOLDER})
-ENDMACRO()
-
-
-MACRO(FEATURE_FUNCTIONPARSER_ERROR_MESSAGE)
- MESSAGE(FATAL_ERROR "\n"
- "No module available for finding functionparser externally.\n"
- "Disable DEAL_II_WITH_FUNCTIONPARSER, or enable DEAL_II_ALLOW_BUNDLED.\n\n"
- )
-ENDMACRO()
-
-
-CONFIGURE_FEATURE(FUNCTIONPARSER)
# Configuration for the hdf5 library:
#
+SET(FEATURE_HDF5_AFTER MPI)
+
+
MACRO(FEATURE_HDF5_FIND_EXTERNAL var)
FIND_PACKAGE(HDF5)
IF(HDF5_FOUND)
+ SET(${var} TRUE)
- IF( (HDF5_WITH_MPI AND DEAL_II_WITH_MPI) OR
- (NOT HDF5_WITH_MPI AND NOT DEAL_II_WITH_MPI) )
- SET(${var} TRUE)
-
- ELSE()
-
+ IF( (HDF5_WITH_MPI AND NOT DEAL_II_WITH_MPI) OR
+ (NOT HDF5_WITH_MPI AND DEAL_II_WITH_MPI) )
MESSAGE(STATUS "Insufficient hdf5 installation found: "
"hdf5 has to be configured with the same MPI configuration as deal.II."
)
" DEAL_II_WITH_MPI = ${DEAL_II_WITH_MPI}\n"
" HDF5_WITH_MPI = ${HDF5_WITH_MPI}\n"
)
- UNSET(HDF5_HL_LIBRARY CACHE)
- UNSET(HDF5_INCLUDE_DIR CACHE)
- UNSET(HDF5_LIBRARY CACHE)
- UNSET(HDF5_PUBCONF CACHE)
+ SET(${var} FALSE)
ENDIF()
+
+ CHECK_MPI_INTERFACE(HDF5 ${var})
ENDIF()
ENDMACRO()
CONFIGURE_FEATURE(HDF5)
-
-
-#
-# The user has to know the location of the hdf5 headers as well:
-#
-SET(HDF5_USER_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS})
# Configuration for the MUMPS library:
#
-SET(FEATURE_MUMPS_DEPENDS DEAL_II_WITH_MPI DEAL_II_WITH_LAPACK)
+SET(FEATURE_MUMPS_DEPENDS MPI LAPACK)
-CONFIGURE_FEATURE(MUMPS)
+MACRO(FEATURE_MUMPS_FIND_EXTERNAL var)
+ FIND_PACKAGE(MUMPS)
-#
-# The user has to know the location of the MUMPS headers as well:
-#
-SET(MUMPS_USER_INCLUDE_DIRS ${MUMPS_INCLUDE_DIRS})
+ IF(MUMPS_FOUND)
+ SET(${var} TRUE)
+ CHECK_MPI_INTERFACE(MUMPS ${var})
+ ENDIF()
+ENDMACRO()
+
+CONFIGURE_FEATURE(MUMPS)
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2013 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Configuration for the MUPARSER library:
+#
+
+MACRO(FEATURE_MUPARSER_CONFIGURE_BUNDLED)
+ SET(MUPARSER_BUNDLED_INCLUDE_DIRS ${MUPARSER_FOLDER}/include)
+ENDMACRO()
+
+
+CONFIGURE_FEATURE(MUPARSER)
# Configuration for the p4est and sc libraries:
#
-SET(FEATURE_P4EST_DEPENDS DEAL_II_WITH_MPI)
+SET(FEATURE_P4EST_DEPENDS MPI)
+
MACRO(FEATURE_P4EST_FIND_EXTERNAL var)
FIND_PACKAGE(P4EST)
SET(${var} FALSE)
ENDIF()
- #
- # Reset configuration:
- #
- IF(NOT ${var})
- UNSET(P4EST_LIBRARY_OPTIMIZED CACHE)
- UNSET(P4EST_LIBRARY_DEBUG CACHE)
- UNSET(P4EST_INCLUDE_DIR CACHE)
- UNSET(SC_LIBRARY_OPTIMIZED CACHE)
- UNSET(SC_LIBRARY_DEBUG CACHE)
- UNSET(SC_INCLUDE_DIR CACHE)
- SET(P4EST_DIR "" CACHE PATH
- "An optional hint to a p4est installation/directory"
- )
- MARK_AS_ADVANCED(CLEAR P4EST_DIR)
- ENDIF()
-
+ CHECK_MPI_INTERFACE(P4EST ${var})
ENDIF()
ENDMACRO()
CONFIGURE_FEATURE(P4EST)
-
-#
-# The user has to know the location of the P4est headers as well:
-#
-SET(P4EST_USER_INCLUDE_DIRS ${P4EST_INCLUDE_DIRS})
# Configuration for the SLEPC library:
#
-SET(FEATURE_SLEPC_DEPENDS DEAL_II_WITH_PETSC)
+SET(FEATURE_SLEPC_DEPENDS PETSC)
+
MACRO(FEATURE_SLEPC_FIND_EXTERNAL var)
FIND_PACKAGE(SLEPC)
CONFIGURE_FEATURE(SLEPC)
-
-#
-# The user has to know the location of the SLEPC headers as well:
-#
-SET(SLEPC_USER_INCLUDE_DIRS ${SLEPC_INCLUDE_DIRS})
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2013 by the deal.II authors
+## Copyright (C) 2013, 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
SET(_test_diff_variable TEST_DIFF)
IF(_file MATCHES "\\.binary\\.")
- IF(NOT DIFF_EXECUTABLE MATCHES "-NOTFOUND")
- SET(_test_diff_variable DIFF_EXECUTABLE)
- ENDIF()
+ SET(_test_diff_variable DIFF_EXECUTABLE)
ENDIF()
#
COMMAND rm -f ${_test_directory}/failing_diff
COMMAND touch ${_test_directory}/diff
COMMAND
- ${${_test_diff_variable}} # see comment in line 72
- ${_test_directory}/output
+ # run diff or numdiff (if available) to determine
+ # whether files are the same. if they are not, output
+ # the first few lines of the output of numdiff, followed
+ # by the results of regular diff since the latter is just
+ # more readable
+ ${${_test_diff_variable}} # see comment above about redirection
${_comparison_file}
+ ${_test_directory}/output
> ${_test_directory}/diff
|| (mv ${_test_directory}/diff
${_test_directory}/failing_diff
&& echo "${_test_full}: DIFF failed. ------ Source: ${_comparison_file}"
&& echo "${_test_full}: DIFF failed. ------ Result: ${_test_directory}/output"
&& echo "${_test_full}: DIFF failed. ------ Diff: ${_test_directory}/failing_diff"
- && echo "${_test_full}: DIFF failed. ------ Diffs as follows:"
- && cat ${_test_directory}/failing_diff
+ && echo "${_test_full}: DIFF failed. ------ First 8 lines of numdiff/diff output:"
+ && cat ${_test_directory}/failing_diff | head -n 8
+ && echo "${_test_full}: DIFF failed. ------ First 50 lines diff output:"
+ && ${DIFF_EXECUTABLE} -c ${_comparison_file} ${_test_directory}/output | head -n 50
&& exit 1)
WORKING_DIRECTORY
${_test_directory}
)
#
- # We have to be careful not to run different mpirun settings for the
- # same executable in parallel because this triggers a race condition
- # when compiling the not yet existent executable that is shared
- # between the different tests.
- #
- # Luckily CMake has a mechanism to force a test to be run after
- # another has finished (and both are scheduled):
+ # Limit concurrency of mpi tests. We can only set concurrency
+ # for the entire test, which includes the compiling and linking
+ # stages that are purely sequential. There is no good way to model
+ # this without unnecessarily restricting concurrency. Consequently,
+ # we just choose to model an "average" concurrency as one half of
+ # the number of MPI jobs.
#
+ IF(_n_cpu GREATER 2)
+ MATH(EXPR _slots "${_n_cpu} / 2")
+ SET_TESTS_PROPERTIES(${_test_full} PROPERTIES PROCESSORS ${_slots})
+ ENDIF()
+
IF(NOT "${_n_cpu}" STREQUAL "0")
+ #
+ # We have to be careful not to run different mpirun settings for the
+ # same executable in parallel because this triggers a race condition
+ # when compiling the not yet existent executable that is shared
+ # between the different tests.
+ #
+ # Luckily CMake has a mechanism to force a test to be run after
+ # another has finished (and both are scheduled):
+ #
IF(DEFINED TEST_DEPENDENCIES_${_target})
SET_TESTS_PROPERTIES(${_test_full} PROPERTIES
DEPENDS ${TEST_DEPENDENCIES_${_target}}
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Check whether a feature is compiled against the same MPI library as the
+# one deal.II picked up
+#
+# Usage:
+# CHECK_MPI_INTERFACE(_feature _var),
+#
+
+MACRO(CHECK_MPI_INTERFACE _feature _var)
+ IF(DEAL_II_WITH_MPI)
+
+ SET(_nope FALSE)
+
+ FOREACH(_library ${${_feature}_LIBRARIES})
+ IF( _library MATCHES "/libmpi(|_cxx)\\.(a|so)[^/]*$")
+
+ GET_FILENAME_COMPONENT(_file1 ${_library} REALPATH)
+
+ SET(_not_found TRUE)
+ FOREACH(_mpi_library ${MPI_LIBRARIES})
+ GET_FILENAME_COMPONENT(_file2 ${_mpi_library} REALPATH)
+ IF("${_file1}" STREQUAL "${_file2}")
+ SET(_not_found FALSE)
+ BREAK()
+ ENDIF()
+ ENDFOREACH()
+
+ IF(_not_found)
+ SET(_nope TRUE)
+ SET(_spurious_library ${_library})
+ BREAK()
+ ENDIF()
+ ENDIF()
+ ENDFOREACH()
+
+ IF(_nope)
+ MESSAGE(STATUS "Could not find a sufficient ${_feature} installation: "
+ "${_feature} is compiled against a different MPI library than the one "
+ "deal.II picked up."
+ )
+ TO_STRING(_str ${MPI_LIBRARIES})
+ SET(PETSC_ADDITIONAL_ERROR_STRING
+ ${PETSC_ADDITIONAL_ERROR_STRING}
+ "Could not find a sufficient ${_feature} installation:\n"
+ "${_feature} has to be compiled against the same MPI library as deal.II "
+ "but the link line of ${_feature} contains:\n"
+ " ${_spurious_library}\n"
+ "which is not listed in MPI_LIBRARIES:\n"
+ " MPI_LIBRARIES = \"${_str}\"\n"
+ )
+ SET(${_var} FALSE)
+ ENDIF()
+ ENDIF()
+ENDMACRO()
+
# FEATURE_${feature}_DEPENDS (a variable)
# a variable which contains an optional list of other features
# this feature depends on (and which have to be enbled for this feature
-# to work.) The features must be given with the full option toggle:
-# DEAL_II_WITH_[...]
+# to work.)
+# Features must be given with short name, i.e. without DEAL_II_WITH_
+#
+# FEATURE_${feature}_after (a variable)
+# a variable which contains an optional list of other features
+# that have to be configured prior to this feature
+# Features must be given with short name, i.e. without DEAL_II_WITH_
#
# FEATURE_${feature}_HAVE_BUNDLED (a variable)
# which should either be set to TRUE if all necessary libraries of the
#
# Check for correct include order of the configure_*.cmake files:
- # If feature B depends on feature A, configure_A.cmake has to be
- # included before configure_B.cmake:
+ # If feature B explicitly states to come after feature A, or if feature B
+ # depends on feature A, configure_A.cmake has to be included before
+ # configure_B.cmake:
#
- FOREACH(_dependency ${FEATURE_${_feature}_DEPENDS})
- STRING(REGEX REPLACE "^DEAL_II_WITH_" "" _dependency ${_dependency})
+ FOREACH(_dependency
+ ${FEATURE_${_feature}_AFTER}
+ ${FEATURE_${_feature}_DEPENDS}
+ )
IF(NOT FEATURE_${_dependency}_PROCESSED)
MESSAGE(FATAL_ERROR "\n"
- "Internal build system error: DEAL_II_WITH_${_feature} depends on "
+ "Internal build system error: The configuration of "
+ "DEAL_II_WITH_${_feature} depends on "
"DEAL_II_WITH_${_dependency}, but CONFIGURE_FEATURE(${_feature}) "
"was called before CONFIGURE_FEATURE(${_dependency}).\n\n"
)
#
IF( (NOT DEAL_II_ALLOW_AUTODETECTION) AND
(NOT DEFINED DEAL_II_WITH_${_feature}) )
+ PURGE_FEATURE(${_feature})
SET_CACHED_OPTION(${_feature} OFF)
ENDIF()
#
SET(_dependencies_ok TRUE)
FOREACH(_dependency ${FEATURE_${_feature}_DEPENDS})
- IF(NOT ${_dependency})
+ IF(NOT DEAL_II_WITH_${_dependency})
IF(DEAL_II_WITH_${_feature})
MESSAGE(FATAL_ERROR "\n"
"DEAL_II_WITH_${_feature} has unmet configuration requirements: "
"DEAL_II_WITH_${_feature} has unmet configuration requirements: "
"${_dependency} has to be set to \"ON\"."
)
+ PURGE_FEATURE(${_feature})
SET_CACHED_OPTION(${_feature} OFF)
ENDIF()
SET(_dependencies_ok FALSE)
#
# First case: DEAL_II_FORCE_BUNDLED_${_feature} is defined:
#
+
+ PURGE_FEATURE(${_feature})
+
IF(FEATURE_${_feature}_HAVE_BUNDLED)
RUN_COMMAND("FEATURE_${_feature}_CONFIGURE_BUNDLED()")
MESSAGE(STATUS "DEAL_II_WITH_${_feature} successfully set up with bundled packages.")
ENDIF()
IF(FEATURE_${_feature}_EXTERNAL_FOUND)
- MESSAGE(STATUS "All external dependencies for DEAL_II_WITH_${_feature} are fullfilled.")
-
IF(COMMAND FEATURE_${_feature}_CONFIGURE_EXTERNAL)
RUN_COMMAND("FEATURE_${_feature}_CONFIGURE_EXTERNAL()")
ENDIF()
ELSE(FEATURE_${_feature}_EXTERNAL_FOUND)
+ PURGE_FEATURE(${_feature})
+
MESSAGE(STATUS "DEAL_II_WITH_${_feature} has unmet external dependencies.")
IF(FEATURE_${_feature}_HAVE_BUNDLED AND DEAL_II_ALLOW_BUNDLED)
# DEAL_II_WITH_${_feature} is defined and set to OFF, promote it to
# cache nevertheless:
#
+ MESSAGE(STATUS "DEAL_II_WITH_${_feature} is set to off.")
+ PURGE_FEATURE(${_feature})
SET_CACHED_OPTION(${_feature} OFF)
ENDIF()
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# A small wrapper around FIND_FILE to be a bit more verbose
+#
+
+MACRO(DEAL_II_FIND_FILE _file_name)
+ FIND_FILE(${_file_name} ${ARGN})
+
+ IF(${_file_name} MATCHES "-NOTFOUND")
+ MESSAGE(STATUS "${_file_name} not found! Call:")
+ TO_STRING(_str ${ARGN})
+ MESSAGE(STATUS " FIND_FILE(${_file_name} ${_str})")
+ ELSE()
+ MESSAGE(STATUS "Found ${_file_name}")
+ ENDIF()
+ENDMACRO()
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# A small wrapper around FIND_LIBRARY to be a bit more verbose
+#
+
+MACRO(DEAL_II_FIND_LIBRARY _library_name)
+ FIND_LIBRARY(${_library_name} ${ARGN})
+
+ IF(${_library_name} MATCHES "-NOTFOUND")
+ MESSAGE(STATUS "${_library_name} not found! Call:")
+ TO_STRING(_str ${ARGN})
+ MESSAGE(STATUS " FIND_LIBRARY(${_library_name} ${_str})")
+ ELSE()
+ MESSAGE(STATUS "Found ${_library_name}")
+ ENDIF()
+ENDMACRO()
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# A small wrapper around FIND_FILE to be a bit more verbose
+#
+
+MACRO(DEAL_II_FIND_PATH _path_name)
+ FIND_PATH(${_path_name} ${ARGN})
+
+ IF(${_path_name} MATCHES "-NOTFOUND")
+ MESSAGE(STATUS "${_path_name} not found! Call:")
+ TO_STRING(_str ${ARGN})
+ MESSAGE(STATUS " FIND_PATH(${_path_name} ${_str})")
+ ELSE()
+ MESSAGE(STATUS "Found ${_path_name}")
+ ENDIF()
+ENDMACRO()
# empty
#
+CMAKE_POLICY(PUSH)
+IF(NOT ${CMAKE_VERSION} VERSION_LESS 3.0.0)
+ CMAKE_POLICY(SET CMP0037 OLD) # allow to override the generic 'help' target
+ENDIF()
+
MACRO(DEAL_II_INVOKE_AUTOPILOT)
# Generator specific values:
IF(CMAKE_GENERATOR MATCHES "Ninja")
- #
- # Ninja doesn't like a redefinition of the "help" target, so use "info"
- # in this case...
- #
SET(_make_command "$ ninja")
ELSE()
SET(_make_command " $ make")
#
")
ENDIF()
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
+ IF(PERL_FOUND)
+ FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
"# ${_make_command} strip_comments - to strip the source files in this
# directory off the documentation comments
-# ${_make_command} clean - to remove the generated executable as well as
+")
+ ENDIF()
+ FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
+"# ${_make_command} clean - to remove the generated executable as well as
# all intermediate compilation files
# ${_make_command} runclean - to remove all output generated by the program
# ${_make_command} distclean - to clean the directory from _all_ generated
# files (includes clean, runclean and the removal
# of the generated build system)
+# ${_make_command} info - to view this message again
#
-"
- )
- IF(CMAKE_GENERATOR MATCHES "Ninja")
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
-"# $ ninja info - to view this message again
-"
- )
- ELSE()
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
-"# $ make help - to view this message again
-" )
- ENDIF()
- FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
-"#
# Have a nice day!
#
###\")"
)
- # A custom target to print the message:
ADD_CUSTOM_TARGET(info
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
)
- IF(NOT CMAKE_GENERATOR MATCHES "Ninja")
+
+ #
+ # In case of the Unix Makefiles generator it is safe to override the
+ # default 'help' target, which is - frankly - quite unhelpful.
+ #
+ IF(CMAKE_GENERATOR MATCHES "Unix Makefiles")
ADD_CUSTOM_TARGET(help
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake
)
INCLUDE(${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_usage.cmake)
SET(USAGE_PRINTED TRUE CACHE INTERNAL "")
ELSE()
- IF(CMAKE_GENERATOR MATCHES "Ninja")
- MESSAGE(STATUS "Run $ ninja info to print a detailed help message")
- ELSE()
- MESSAGE(STATUS "Run $ make help to print a detailed help message")
- ENDIF()
+ MESSAGE(STATUS "Run ${_make_command} info to print a detailed help message")
ENDIF()
ENDMACRO()
+CMAKE_POLICY(POP)
+
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# DEAL_II_PACKAGE_HANDLE(<feature>
+# {<conf. variable> {(REQUIRED|OPTIONAL) <variables>}}
+# [CLEAR <variables>]
+# )
+#
+# This macro is an alternative implementation of the
+# FIND_PACKAGE_HANDLE_STANDARD_ARGS macro shipped with CMake - aka do
+# everything that was expected from CMake in the first place *sigh*
+#
+# Its usage is best explained with an example:
+#
+# DEAL_II_PACKAGE_HANDLE(PETSC
+# LIBRARIES
+# REQUIRED PETSC_LIBRARY
+# OPTIONAL _petsc_libraries
+# INCLUDE_DIRS
+# REQUIRED PETSC_INCLUDE_DIR_COMMON PETSC_INCLUDE_DIR_ARCH
+# OPTIONAL _petsc_includes
+# CLEAR PETSC_LIBRARY PETSC_INCLUDE_DIR_COMMON PETSC_INCLUDE_DIR_ARCH
+# )
+#
+# This will check whether all REQUIRED variables are non-empty and
+# different from "-NOTFOUND". If so, PETSC_LIBRARIES and PETSC_INCLUDE_DIRS
+# is defined and populated with the contents of all specified variables.
+# Optional variables with no content or whose content is "-NOTFOUND" are
+# filtered out.
+# After the 'CLEAR' statement all internally cached variables should be
+# listed - this is used to provide a possibility to undo a feature
+# search.
+#
+
+MACRO(DEAL_II_PACKAGE_HANDLE _feature _var)
+
+ IF(DEFINED ${_feature}_VERSION)
+ MESSAGE(STATUS " ${_feature}_VERSION: ${${_feature}_VERSION}")
+ ENDIF()
+
+ SET(${_feature}_FOUND TRUE)
+
+ SET(_variable ${_var})
+ SET(${_feature}_${_variable} "")
+ SET(_required TRUE)
+ SET(_fine TRUE)
+ SET(_fill_clear FALSE)
+ SET(_clear "")
+
+ FOREACH(_arg ${ARGN})
+ IF(_arg MATCHES "^LIBRARIES(|_DEBUG|_RELEASE)$"
+ OR _arg MATCHES "^(|BUNDLED_|USER_)INCLUDE_DIRS$"
+ OR _arg MATCHES "^(|USER_)DEFINITIONS(|_DEBUG|_RELEASE)$"
+ OR _arg MATCHES "^CXX_FLAGS(|_DEBUG|_RELEASE)"
+ OR _arg MATCHES "^LINKER_FLAGS(|_DEBUG|_RELEASE)")
+
+ IF(_fine)
+ IF(_variable MATCHES "^CXX_FLAGS(|_DEBUG|_RELEASE)"
+ OR _variable MATCHES "^LINKER_FLAGS(|_DEBUG|_RELEASE)")
+ TO_STRING(${_feature}_${_variable} ${${_feature}_${_variable}})
+ ENDIF()
+ MESSAGE(STATUS " ${_feature}_${_variable}: ${${_feature}_${_variable}}")
+ ENDIF()
+
+ #
+ # *Yay* a new keyword.
+ #
+ SET(_variable ${_arg})
+ SET(${_feature}_${_variable} "")
+ SET(_required TRUE)
+ SET(_fine TRUE)
+
+ ELSEIF("${_arg}" STREQUAL "REQUIRED")
+ SET(_required TRUE)
+ ELSEIF("${_arg}" STREQUAL "OPTIONAL")
+ SET(_required FALSE)
+ ELSEIF(_arg MATCHES "^(optimized|debug|general)$"
+ AND "${_variable}" STREQUAL "LIBRARIES")
+ #
+ # Keywords are special...
+ #
+ LIST(APPEND ${_feature}_${_variable} ${_arg})
+ ELSEIF("${_arg}" STREQUAL "CLEAR")
+ SET(_fill_clear TRUE)
+ ELSE()
+ MARK_AS_ADVANCED(${_arg})
+ IF(_fill_clear)
+ IF(NOT _arg MATCHES "^(optimized|debug|general)$")
+ LIST(APPEND _clear ${_arg})
+ ENDIF()
+ ELSE()
+ IF("${${_arg}}" MATCHES "^\\s*$" OR "${${_arg}}" MATCHES "-NOTFOUND")
+ IF(_required AND _fine)
+ IF("${${_arg}}" MATCHES "^\\s*$")
+ MESSAGE(STATUS
+ " ${_feature}_${_variable}: *** Required variable \"${_arg}\" empty ***"
+ )
+ ELSE()
+ MESSAGE(STATUS
+ " ${_feature}_${_variable}: *** Required variable \"${_arg}\" set to NOTFOUND ***"
+ )
+ ENDIF()
+ SET(${_feature}_FOUND FALSE)
+ SET(_fine FALSE)
+ ENDIF()
+ ELSE()
+ LIST(APPEND ${_feature}_${_variable} ${${_arg}})
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ ENDFOREACH()
+
+ SET(${_feature}_CLEAR_VARIABLES ${_clear} CACHE INTERNAL "")
+
+ IF(_fine)
+ IF(_variable MATCHES "^CXX_FLAGS(|_DEBUG|_RELEASE)"
+ OR _variable MATCHES "^LINKER_FLAGS(|_DEBUG|_RELEASE)")
+ TO_STRING(${_feature}_${_variable} ${${_feature}_${_variable}})
+ ENDIF()
+ MESSAGE(STATUS " ${_feature}_${_variable}: ${${_feature}_${_variable}}")
+ ENDIF()
+
+ IF(${_feature}_FOUND)
+ #
+ # Deduplicate entries:
+ #
+ FOREACH(_suffix ${DEAL_II_LIST_SUFFIXES})
+ IF(_suffix MATCHES "INCLUDE_DIRS$")
+ REMOVE_DUPLICATES(${_feature}_${_suffix})
+ ELSE()
+ REMOVE_DUPLICATES(${_feature}_${_suffix} REVERSE)
+ ENDIF()
+ ENDFOREACH()
+
+ MESSAGE(STATUS "Found ${_feature}")
+
+ MARK_AS_ADVANCED(${_feature}_DIR ${_feature}_ARCH)
+
+ ELSE()
+
+ MESSAGE(STATUS "Could NOT find ${_feature}")
+ ENDIF()
+ENDMACRO()
SET(_tmp_${_variable} ${${_variable}})
SET(${_variable} "")
FOREACH(_lib ${_tmp_${_variable}})
- IF(_lib MATCHES "lib(c|quadmath|gfortran|m|rt|nsl|dl|pthread).so$")
+ IF(_lib MATCHES "lib(c|quadmath|gfortran|m|rt|nsl|dl|pthread)\\.(a|so)$")
string(REGEX REPLACE ".*lib([a-z]+).so$" "\\1" _lib ${_lib})
ENDIF()
LIST(APPEND ${_variable} ${_lib})
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Remove all cached and non cached variables associated with a feature.
+#
+# Usage:
+# PURGE_FEATURE(feature)
+#
+
+MACRO(PURGE_FEATURE _feature)
+ #
+ # uncached:
+ #
+ FOREACH(_var ${DEAL_II_LIST_SUFFIXES} ${DEAL_II_STRING_SUFFIXES})
+ IF(NOT _var MATCHES BUNDLED)
+ SET(${_feature}_${_var})
+ ENDIF()
+ ENDFOREACH()
+
+ UNSET(${_feature}_FOUND)
+ UNSET(${_feature}_VERSION)
+
+ #
+ # cached:
+ #
+ FOREACH(_var ${${_feature}_CLEAR_VARIABLES})
+ SET(${_var})
+ UNSET(${_var} CACHE)
+ ENDFOREACH()
+
+ UNSET(${_feature}_CLEAR_VARIABLES CACHE)
+
+ MARK_AS_ADVANCED(CLEAR ${_feature}_DIR ${_feature}_ARCH)
+ENDMACRO()
# This macro will add
#
# <FEATURE>_LIBRARIES (respecting general, optimized, debug keyword)
-# <FEATURE>_LIBRARIES(_DEBUG|_RELEASE)
-# <FEATURE>_(|BUNDLED_|USER_)INCLUDE_DIRS
-# <FEATURE>_DEFINITIONS(|_DEBUG|_RELEASE)
-# <FEATURE>_USER_DEFINITIONS(|_DEBUG|_RELEASE)
-# <FEATURE>_CXX_FLAGS(|_DEBUG|_RELEASE)
-# <FEATURE>_LINKER_FLAGS(|_DEBUG|_RELEASE)
#
-# to the corresponding DEAL_II_* variables
+# and all other suffixes defined in DEAL_II_LIST_SUFFIXES and
+# DEAL_II_STRING_SUFFIXES to the corresponding DEAL_II_* variables
#
MACRO(REGISTER_FEATURE _feature)
ENDFOREACH()
ENDIF()
- FOREACH(_var
- LIBRARIES_DEBUG LIBRARIES_RELEASE
- INCLUDE_DIRS BUNDLED_INCLUDE_DIRS USER_INCLUDE_DIRS
- DEFINITIONS DEFINITIONS_DEBUG DEFINITIONS_RELEASE
- USER_DEFINITIONS USER_DEFINITIONS_DEBUG USER_DEFINITIONS_RELEASE
- )
- IF(DEFINED ${_feature}_${_var})
+ FOREACH(_var ${DEAL_II_LIST_SUFFIXES})
+ IF(NOT "${_var}" STREQUAL "LIBRARIES" AND DEFINED ${_feature}_${_var})
LIST(APPEND DEAL_II_${_var} ${${_feature}_${_var}})
ENDIF()
ENDFOREACH()
- FOREACH(_var
- CXX_FLAGS CXX_FLAGS_DEBUG CXX_FLAGS_RELEASE
- LINKER_FLAGS LINKER_FLAGS_DEBUG LINKER_FLAGS_RELEASE
- )
+ FOREACH(_var ${DEAL_II_STRING_SUFFIXES})
IF(DEFINED ${_feature}_${_var})
ADD_FLAGS(DEAL_II_${_var} "${${_feature}_${_var}}")
ENDIF()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# TODO: ARPACK and mpi...
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(ARPACK_DIR "" CACHE PATH "An optional hint to an ARPACK installation")
SET_IF_EMPTY(ARPACK_DIR "$ENV{ARPACK_DIR}")
-FIND_LIBRARY(ARPACK_LIBRARY
+DEAL_II_FIND_LIBRARY(ARPACK_LIBRARY
NAMES arpack
- HINTS
- ${ARPACK_DIR}
+ HINTS ${ARPACK_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(ARPACK DEFAULT_MSG
- ARPACK_LIBRARY
- LAPACK_FOUND
- )
-
-MARK_AS_ADVANCED(
- lapack_LIBRARY
- atlas_LIBRARY
- blas_LIBRARY
- ARPACK_LIBRARY
+DEAL_II_PACKAGE_HANDLE(ARPACK
+ LIBRARIES REQUIRED ARPACK_LIBRARY LAPACK_LIBRARIES
+ LINKER_FLAGS OPTIONAL LAPACK_LINKER_FLAGS
+ CLEAR ARPACK_LIBRARY
)
-
-IF(ARPACK_FOUND)
- SET(ARPACK_LIBRARIES
- ${ARPACK_LIBRARY}
- ${LAPACK_LIBRARIES}
- )
- SET(ARPACK_LINKER_FLAGS
- ${LAPACK_LINKER_FLAGS}
- )
-
- MARK_AS_ADVANCED(ARPACK_DIR)
-ELSE()
- SET(ARPACK_DIR "" CACHE PATH
- "An optional hint to an ARPACK installation"
- )
-ENDIF()
-
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Try to find the boost libraries
+#
+# This module exports:
+#
+# BOOST_FOUND
+# BOOST_LIBRARIES
+# BOOST_INCLUDE_DIRS
+# BOOST_VERSION
+# BOOST_VERSION_MAJOR
+# BOOST_VERSION_MINOR
+# BOOST_VERSION_SUBMINOR
+#
+
+SET(BOOST_DIR "" CACHE PATH "An optional hint to a BOOST installation")
+SET_IF_EMPTY(BOOST_DIR "$ENV{BOOST_DIR}")
+
+IF(NOT "${BOOST_DIR}" STREQUAL "")
+ SET(BOOST_ROOT "${BOOST_DIR}")
+ENDIF()
+
+#
+# Prefer static libs if BUILD_SHARED_LIBS=OFF:
+#
+IF(NOT BUILD_SHARED_LIBS)
+ SET(Boost_USE_STATIC_LIBS TRUE)
+ENDIF()
+
+LIST(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+FIND_PACKAGE(Boost 1.44 COMPONENTS iostreams serialization system thread)
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+#
+# Fall back to dynamic libraries if no static libraries could be found:
+#
+IF(NOT Boost_FOUND AND Boost_USE_STATIC_LIBS)
+ SET(Boost_USE_STATIC_LIBS FALSE)
+ FIND_PACKAGE(Boost 1.44 COMPONENTS iostreams serialization system thread)
+ENDIF()
+
+IF(Boost_FOUND)
+ #
+ # Remove "pthread" from Boost_LIBRARIES. Threading, if necessary, is
+ # already set up via configure_1_threads.cmake.
+ #
+ LIST(REMOVE_ITEM Boost_LIBRARIES "pthread")
+
+ SET(BOOST_VERSION_MAJOR "${Boost_MAJOR_VERSION}")
+ SET(BOOST_VERSION_MINOR "${Boost_MINOR_VERSION}")
+ SET(BOOST_VERSION_SUBMINOR "${Boost_SUBMINOR_VERSION}")
+ SET(BOOST_VERSION
+ "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}"
+ )
+ENDIF()
+
+DEAL_II_PACKAGE_HANDLE(BOOST
+ LIBRARIES REQUIRED Boost_LIBRARIES
+ INCLUDE_DIRS REQUIRED Boost_INCLUDE_DIRS
+ USER_INCLUDE_DIRS Boost_INCLUDE_DIRS
+ CLEAR
+ Boost_INCLUDE_DIR Boost_IOSTREAMS_LIBRARY_DEBUG
+ Boost_IOSTREAMS_LIBRARY_RELEASE Boost_LIBRARY_DIR
+ Boost_SERIALIZATION_LIBRARY_DEBUG Boost_SERIALIZATION_LIBRARY_RELEASE
+ Boost_SYSTEM_LIBRARY_DEBUG Boost_SYSTEM_LIBRARY_RELEASE
+ Boost_THREAD_LIBRARY_DEBUG Boost_THREAD_LIBRARY_RELEASE
+ _Boost_COMPONENTS_SEARCHED _Boost_INCLUDE_DIR_LAST
+ _Boost_LIBRARY_DIR_LAST _Boost_USE_MULTITHREADED_LAST
+ )
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Try to find the BZIP2 library
+#
+# This module exports
+#
+# BZIP2_LIBRARIES
+# BZIP2_INCLUDE_DIRS
+# BZIP2_VERSION
+#
+
+#
+# Houston, we have a problem: CMake ships its own FindBZip2.cmake module.
+# Unfortunately we want to call DEAL_II_PACKAGE_HANDLE. Therefore, use the
+# original find module and do a dummy call to DEAL_II_PACKAGE_HANDLE:
+#
+
+LIST(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+FIND_PACKAGE(BZip2)
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+SET(BZIP2_VERSION ${BZIP2_VERSION_STRING})
+SET(_bzip2_libraries ${BZIP2_LIBRARIES})
+
+DEAL_II_PACKAGE_HANDLE(BZIP2
+ LIBRARIES REQUIRED _bzip2_libraries
+ INCLUDE_DIRS REQUIRED BZIP2_INCLUDE_DIR
+ CLEAR
+ BZIP2_INCLUDE_DIR BZIP2_LIBRARY_DEBUG BZIP2_LIBRARY_RELEASE
+ BZIP2_NEED_PREFIX
+ )
+++ /dev/null
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2013 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE at
-## the top level of the deal.II distribution.
-##
-## ---------------------------------------------------------------------
-
-#
-# This module is a wrapper around the FindLAPACK.cmake module provided by
-# CMake.
-#
-# This module exports
-#
-# LAPACK_FOUND
-# LAPACK_LIBRARIES
-# LAPACK_LINKER_FLAGS
-# BLAS_FOUND
-# BLAS_LIBRARIES
-# BLAS_LINKER_FLAGS
-#
-
-
-
-#
-# We have to use a trick with CMAKE_PREFIX_PATH to make LAPACK_DIR and
-# BLAS_DIR work...
-#
-SET_IF_EMPTY(BLAS_DIR "$ENV{BLAS_DIR}")
-SET_IF_EMPTY(LAPACK_DIR "$ENV{LAPACK_DIR}")
-
-SET(_cmake_prefix_path_backup "${CMAKE_PREFIX_PATH}")
-
-SET(CMAKE_PREFIX_PATH ${BLAS_DIR} ${LAPACK_DIR} ${_cmake_prefix_path_backup})
-
-FIND_PACKAGE(BLAS)
-
-SET(CMAKE_PREFIX_PATH ${LAPACK_DIR} ${_cmake_prefix_path_backup})
-
-FIND_PACKAGE(LAPACK)
-
-SET(CMAKE_PREFIX_PATH ${_cmake_prefix_path_backup})
-
-MARK_AS_ADVANCED(
- atlas_LIBRARY atlcblas_LIBRARY atllapack_LIBRARY blas_LIBRARY
- eigen_blas_LIBRARY f77blas_LIBRARY gslcblas_LIBRARY lapack_LIBRARY
- m_LIBRARY ptf77blas_LIBRARY ptlapack_LIBRARY refblas_LIBRARY
- reflapack_LIBRARY
- )
-
-
-IF(LAPACK_FOUND)
- SET(DEALII_LAPACK_FOUND TRUE)
-
- #
- # So, well... LAPACK_LINKER_FLAGS and LAPACK_LIBRARIES should contain the
- # complete link interface. But for invalid user overrides we include
- # BLAS_LIBRARIES and BLAS_LINKER_FLAGS as well..
- #
- IF(NOT LAPACK_LINKER_FLAGS MATCHES "${BLAS_LINKER_FLAGS}")
- MESSAGE(STATUS
- "Manually adding BLAS_LINKER_FLAGS to LAPACK_LINKER_FLAGS"
- )
- ADD_FLAGS(LAPACK_LINKER_FLAGS "${BLAS_LINKER_FLAGS}")
- ENDIF()
- IF(NOT "${LAPACK_LIBRARIES}" MATCHES "${BLAS_LIBRARIES}")
- MESSAGE(STATUS
- "Manually adding BLAS_LIBRARIES to LAPACK_LIBRARIES"
- )
- LIST(APPEND LAPACK_LIBRARIES ${BLAS_LIBRARIES})
- ENDIF()
-
- #
- # Well, in case of static archives we have to manually pick up the
- # complete link interface. *sigh*
- #
- # If CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES is not available, do it
- # unconditionally for the most common case (gfortran).
- #
- SET(_fortran_libs ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES})
- SET_IF_EMPTY(_fortran_libs gfortran m quadmath c)
-
- FOREACH(_lib ${_fortran_libs})
- FIND_SYSTEM_LIBRARY(${_lib}_LIBRARY NAMES ${_lib})
- MARK_AS_ADVANCED(${_lib}_LIBRARY)
-
- IF(NOT ${_lib}_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND BLAS_LIBRARIES ${${_lib}_LIBRARY})
- LIST(APPEND LAPACK_LIBRARIES ${${_lib}_LIBRARY})
- ENDIF()
-
- ENDFOREACH()
-
- #
- # Filter out spurious "FALSE" in the library lists:
- #
- IF(DEFINED BLAS_LIBRARIES)
- LIST(REMOVE_ITEM BLAS_LIBRARIES "FALSE")
- ENDIF()
- LIST(REMOVE_ITEM LAPACK_LIBRARIES "FALSE")
-
- MARK_AS_ADVANCED(
- BLAS_DIR
- LAPACK_DIR
- )
-
-ELSE()
- SET(DEALII_LAPACK_FOUND FALSE)
-
- SET(LAPACK_DIR "" CACHE PATH
- "An optional hint to a LAPACK installation"
- )
- SET(BLAS_DIR "" CACHE PATH
- "An optional hint to a BLAS installation"
- )
-
- #
- # Clean up the library variables in case we couldn't find the libraries
- # to avoid spurious inclusions of "-NOTFOUND" or "FALSE":
- #
- SET(BLAS_LIBRARIES)
- SET(LAPACK_LIBRARIES)
-
-ENDIF()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# HDF5_WITH_MPI
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(HDF5_DIR "" CACHE PATH "An optional hint to an hdf5 directory")
SET_IF_EMPTY(HDF5_DIR "$ENV{HDF5_DIR}")
-FIND_PATH(HDF5_INCLUDE_DIR hdf5.h
- HINTS
- ${HDF5_DIR}
- PATH_SUFFIXES
- hdf5 hdf5/include include/hdf5 include
- )
-
-FIND_LIBRARY(HDF5_LIBRARY NAMES hdf5
- HINTS
- ${HDF5_DIR}
- PATH_SUFFIXES
- hdf5/lib lib${LIB_SUFFIX} lib64 lib
+DEAL_II_FIND_PATH(HDF5_INCLUDE_DIR hdf5.h
+ HINTS ${HDF5_DIR}
+ PATH_SUFFIXES hdf5 hdf5/include include/hdf5 include
)
-FIND_LIBRARY(HDF5_HL_LIBRARY NAMES hdf5_hl
- HINTS
- ${HDF5_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib
+DEAL_II_FIND_LIBRARY(HDF5_LIBRARY NAMES hdf5
+ HINTS ${HDF5_DIR}
+ PATH_SUFFIXES hdf5/lib lib${LIB_SUFFIX} lib64 lib
)
-FIND_FILE(HDF5_PUBCONF NAMES H5pubconf.h H5pubconf-64.h
- HINTS
- ${HDF5_INCLUDE_DIR}
- ${HDF5_DIR}
- PATH_SUFFIXES
- hdf5 hdf5/include include/hdf5 include
+DEAL_II_FIND_LIBRARY(HDF5_HL_LIBRARY NAMES hdf5_hl
+ HINTS ${HDF5_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-SET(_output ${HDF5_HL_LIBRARY} ${HDF5_LIBRARY})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(HDF5 DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- HDF5_HL_LIBRARY
- HDF5_LIBRARY
- HDF5_INCLUDE_DIR
- HDF5_PUBCONF
+DEAL_II_FIND_FILE(HDF5_PUBCONF NAMES H5pubconf.h H5pubconf-64.h
+ HINTS ${HDF5_INCLUDE_DIR} ${HDF5_DIR}
+ PATH_SUFFIXES hdf5 hdf5/include include/hdf5 include
)
-MARK_AS_ADVANCED(
- HDF5_LIBRARY
- HDF5_HL_LIBRARY
- HDF5_INCLUDE_DIR
- HDF5_PUBCONF
- )
-
-IF(HDF5_FOUND)
- SET(HDF5_INCLUDE_DIRS
- ${HDF5_INCLUDE_DIR}
- )
- SET(HDF5_LIBRARIES
- ${HDF5_HL_LIBRARY}
- ${HDF5_LIBRARY}
- ${MPI_C_LIBRARIES} # for good measure
- )
-
+IF(EXISTS ${HDF5_PUBCONF})
#
# Is hdf5 compiled with support for mpi?
#
FILE(STRINGS ${HDF5_PUBCONF} HDF5_MPI_STRING
- REGEX "#define.*H5_HAVE_PARALLEL 1")
+ REGEX "#define.*H5_HAVE_PARALLEL 1"
+ )
IF("${HDF5_MPI_STRING}" STREQUAL "")
SET(HDF5_WITH_MPI FALSE)
ELSE()
SET(HDF5_WITH_MPI TRUE)
ENDIF()
-
- MARK_AS_ADVANCED(HDF5_DIR)
-ELSE()
- SET(HDF5_DIR "" CACHE PATH
- "An optional hint to an hdf5 directory"
- )
ENDIF()
+DEAL_II_PACKAGE_HANDLE(HDF5
+ LIBRARIES
+ REQUIRED HDF5_HL_LIBRARY HDF5_LIBRARY
+ OPTIONAL MPI_C_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED HDF5_INCLUDE_DIR
+ USER_INCLUDE_DIRS
+ REQUIRED HDF5_INCLUDE_DIR
+ CLEAR HDF5_HL_LIBRARY HDF5_LIBRARY HDF5_INCLUDE_DIR HDF5_PUBCONF
+ )
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2013 - 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# This module is a wrapper around the FindLAPACK.cmake module provided by
+# CMake.
+#
+# This module exports
+#
+# LAPACK_FOUND
+# LAPACK_LIBRARIES
+# LAPACK_LINKER_FLAGS
+# BLAS_FOUND
+# BLAS_LIBRARIES
+# BLAS_LINKER_FLAGS
+#
+
+#
+# We have to use a trick with CMAKE_PREFIX_PATH to make LAPACK_DIR and
+# BLAS_DIR work...
+#
+SET(LAPACK_DIR "" CACHE PATH "An optional hint to a LAPACK installation")
+SET(BLAS_DIR "" CACHE PATH "An optional hint to a BLAS installation")
+SET_IF_EMPTY(BLAS_DIR "$ENV{BLAS_DIR}")
+SET_IF_EMPTY(LAPACK_DIR "$ENV{LAPACK_DIR}")
+
+SET(_cmake_prefix_path_backup "${CMAKE_PREFIX_PATH}")
+LIST(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+SET(CMAKE_PREFIX_PATH ${BLAS_DIR} ${LAPACK_DIR} ${_cmake_prefix_path_backup})
+FIND_PACKAGE(BLAS)
+
+SET(CMAKE_PREFIX_PATH ${LAPACK_DIR} ${_cmake_prefix_path_backup})
+FIND_PACKAGE(LAPACK)
+
+SET(CMAKE_PREFIX_PATH ${_cmake_prefix_path_backup})
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+#
+# Filter out spurious "FALSE" in the library lists:
+#
+IF(DEFINED BLAS_LIBRARIES)
+ LIST(REMOVE_ITEM BLAS_LIBRARIES "FALSE")
+ENDIF()
+IF(DEFINED LAPACK_LIBRARIES)
+ LIST(REMOVE_ITEM LAPACK_LIBRARIES "FALSE")
+ENDIF()
+
+#
+# Well, in case of static archives we have to manually pick up the
+# complete link interface. *sigh*
+#
+# If CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES is not available, do it
+# unconditionally for the most common case (gfortran).
+#
+SET(_fortran_libs ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES})
+SET_IF_EMPTY(_fortran_libs gfortran m quadmath c)
+FOREACH(_lib ${_fortran_libs})
+ FIND_SYSTEM_LIBRARY(${_lib}_LIBRARY NAMES ${_lib})
+ LIST(APPEND _additional_libraries ${_lib}_LIBRARY)
+ENDFOREACH()
+
+
+SET(_lapack_libraries ${LAPACK_LIBRARIES})
+SET(_lapack_linker_flags ${LAPACK_LINKER_FLAGS})
+DEAL_II_PACKAGE_HANDLE(LAPACK
+ LIBRARIES
+ REQUIRED _lapack_libraries
+ OPTIONAL BLAS_LIBRARIES ${_additional_libraries}
+ LINKER_FLAGS OPTIONAL _lapack_linker_flags BLAS_LINKER_FLAGS
+ CLEAR
+ atlas_LIBRARY atlcblas_LIBRARY atllapack_LIBRARY blas_LIBRARY
+ eigen_blas_LIBRARY f77blas_LIBRARY gslcblas_LIBRARY lapack_LIBRARY
+ m_LIBRARY ptf77blas_LIBRARY ptlapack_LIBRARY refblas_LIBRARY
+ reflapack_LIBRARY BLAS_LIBRARIES ${_additional_libraries}
+ LAPACK_SYMBOL_CHECK # Cleanup check in configure_1_lapack.cmake
+ )
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# METIS_VERSION_SUBMINOR
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(METIS_DIR "" CACHE PATH "An optional hint to a metis directory")
SET_IF_EMPTY(METIS_DIR "$ENV{METIS_DIR}")
#
# Link in MPI unconditionally (if found).
#
-FIND_PATH(METIS_INCLUDE_DIR metis.h
- HINTS
- ${METIS_DIR}
- PATH_SUFFIXES
- metis include/metis include
- )
-
-FIND_LIBRARY(METIS_LIBRARY
+DEAL_II_FIND_LIBRARY(METIS_LIBRARY
NAMES metis
- HINTS
- ${METIS_DIR}
+ HINTS ${METIS_DIR}
PATH_SUFFIXES
lib${LIB_SUFFIX} lib64 lib
# This is a hint, isn't it?
build/${CMAKE_CXX_PLATFORM_ID}-${CMAKE_SYSTEM_PROCESSOR}/libmetis
)
-FIND_LIBRARY(PARMETIS_LIBRARY
+#
+# Sanity check: Only search the parmetis library in the same directory as
+# the metis library...
+#
+GET_FILENAME_COMPONENT(_path "${METIS_LIBRARY}" PATH)
+DEAL_II_FIND_LIBRARY(PARMETIS_LIBRARY
NAMES parmetis
- HINTS
- ${METIS_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib
- # This is a hint, isn't it?
- build/${CMAKE_CXX_PLATFORM_ID}-${CMAKE_SYSTEM_PROCESSOR}/libmetis
- )
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(METIS DEFAULT_MSG
- METIS_LIBRARY
- METIS_INCLUDE_DIR
+ HINTS ${_path}
+ NO_DEFAULT_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_CMAKE_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH
+ NO_CMAKE_FIND_ROOT_PATH
)
-MARK_AS_ADVANCED(
- METIS_LIBRARY
- PARMETIS_LIBRARY
- METIS_INCLUDE_DIR
+DEAL_II_FIND_PATH(METIS_INCLUDE_DIR metis.h
+ HINTS ${METIS_DIR}
+ PATH_SUFFIXES metis include/metis include
)
-IF(METIS_FOUND)
-
- #
- # Sanity check: Only include parmetis library if it is in the same
- # directory as the metis library...
- #
- GET_FILENAME_COMPONENT(_path1 "${PARMETIS_LIBRARY}" PATH)
- GET_FILENAME_COMPONENT(_path2 "${ETIS_LIBRARY}" PATH)
- IF( NOT PARMETIS_LIBRARY MATCHES "-NOTFOUND"
- AND "${_path1}" STREQUAL "${_path2}" )
- SET(METIS_LIBRARIES ${PARMETIS_LIBRARY})
- ENDIF()
-
- LIST(APPEND METIS_LIBRARIES
- ${METIS_LIBRARY}
- ${MPI_C_LIBRARIES} # for good measure
- )
- SET(METIS_INCLUDE_DIRS ${METIS_INCLUDE_DIR})
-
+IF(EXISTS ${METIS_INCLUDE_DIR}/metis.h)
#
# Extract the version number out of metis.h
#
SET(METIS_VERSION
"${METIS_VERSION_MAJOR}.${METIS_VERSION_MINOR}.${METIS_VERSION_SUBMINOR}"
)
-
- MARK_AS_ADVANCED(METIS_DIR)
-ELSE()
- SET(METIS_DIR "" CACHE PATH
- "An optional hint to a metis directory"
- )
+ IF("${METIS_VERSION}" STREQUAL "..")
+ SET(METIS_VERSION)
+ ENDIF()
ENDIF()
+DEAL_II_PACKAGE_HANDLE(METIS
+ LIBRARIES
+ OPTIONAL PARMETIS_LIBRARY
+ REQUIRED METIS_LIBRARY
+ OPTIONAL MPI_C_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED METIS_INCLUDE_DIR
+ CLEAR METIS_LIBRARY PARMETIS_LIBRARY METIS_INCLUDE_DIR
+ )
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2012 - 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Find MPI
+#
+# This module exports:
+# MPI_LIBRARIES
+# MPI_INCLUDE_DIRS
+# MPI_CXX_FLAGS
+# MPI_LINKER_FLAGS
+# MPI_VERSION
+# OMPI_VERSION
+#
+
+#
+# Configuration for mpi support:
+#
+# We look for the C and Fortran libraries as well because they are needed
+# by some external libraries for the link interface.
+#
+
+IF(MPI_CXX_FOUND)
+ SET(MPI_FOUND TRUE)
+ENDIF()
+
+#
+# If CMAKE_CXX_COMPILER is already an MPI wrapper, use it to determine
+# the mpi implementation. If MPI_CXX_COMPILER is defined use the value
+# directly.
+#
+SET_IF_EMPTY(MPI_CXX_COMPILER ${CMAKE_CXX_COMPILER})
+IF(CMAKE_C_COMPILER_WORKS)
+ SET_IF_EMPTY(MPI_C_COMPILER ${CMAKE_C_COMPILER}) # for good measure
+ELSE()
+ MESSAGE(STATUS
+ "No suitable C compiler was found! MPI C interface can not be "
+ "autodetected"
+ )
+ENDIF()
+IF(CMAKE_Fortran_COMPILER_WORKS)
+ SET_IF_EMPTY(MPI_Fortran_COMPILER ${CMAKE_Fortran_COMPILER}) # for good measure
+ELSE()
+ MESSAGE(STATUS
+ "No suitable Fortran compiler was found! MPI Fortran interface can "
+ "not be autodetected"
+ )
+ENDIF()
+
+#
+# Call the system FindMPI.cmake module:
+#
+LIST(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+FIND_PACKAGE(MPI)
+
+IF(NOT MPI_CXX_FOUND AND DEAL_II_WITH_MPI)
+ #
+ # CMAKE_CXX_COMPILER is apparently not an mpi wrapper.
+ # So, let's be a bit more aggressive in finding MPI (and if
+ # DEAL_II_WITH_MPI is set).
+ #
+ MESSAGE(STATUS
+ "MPI not found but DEAL_II_WITH_MPI is set to TRUE."
+ " Try again with more aggressive search paths:"
+ )
+ # Clear variables so that FIND_PACKAGE runs again:
+ SET(MPI_FOUND)
+ UNSET(MPI_CXX_COMPILER CACHE)
+ UNSET(MPI_C_COMPILER CACHE)
+ UNSET(MPI_Fortran_COMPILER CACHE)
+ FIND_PACKAGE(MPI)
+ENDIF()
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+
+#
+# Manually assemble some version information:
+#
+
+DEAL_II_FIND_FILE(MPI_MPI_H
+ NAMES mpi.h
+ HINTS ${MPI_CXX_INCLUDE_PATH} ${MPI_C_INCLUDE_PATH}
+ )
+IF(NOT MPI_MPI_H MATCHES "-NOTFOUND" AND NOT DEFINED MPI_VERSION)
+ FILE(STRINGS "${MPI_MPI_H}" MPI_VERSION_MAJOR_STRING
+ REGEX "#define.*MPI_VERSION")
+ STRING(REGEX REPLACE "^.*MPI_VERSION.*([0-9]+).*" "\\1"
+ MPI_VERSION_MAJOR "${MPI_VERSION_MAJOR_STRING}"
+ )
+ FILE(STRINGS ${MPI_MPI_H} MPI_VERSION_MINOR_STRING
+ REGEX "#define.*MPI_SUBVERSION")
+ STRING(REGEX REPLACE "^.*MPI_SUBVERSION.*([0-9]+).*" "\\1"
+ MPI_VERSION_MINOR "${MPI_VERSION_MINOR_STRING}"
+ )
+ SET(MPI_VERSION "${MPI_VERSION_MAJOR}.${MPI_VERSION_MINOR}")
+ IF("${MPI_VERSION}" STREQUAL ".")
+ SET(MPI_VERSION)
+ SET(MPI_VERSION_MAJOR)
+ SET(MPI_VERSION_MINOR)
+ ENDIF()
+
+ # OMPI specific version number:
+ FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_MAJOR_STRING
+ REGEX "#define.*OMPI_MAJOR_VERSION")
+ STRING(REGEX REPLACE "^.*OMPI_MAJOR_VERSION.*([0-9]+).*" "\\1"
+ OMPI_VERSION_MAJOR "${OMPI_VERSION_MAJOR_STRING}"
+ )
+ FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_MINOR_STRING
+ REGEX "#define.*OMPI_MINOR_VERSION")
+ STRING(REGEX REPLACE "^.*OMPI_MINOR_VERSION.*([0-9]+).*" "\\1"
+ OMPI_VERSION_MINOR "${OMPI_VERSION_MINOR_STRING}"
+ )
+ FILE(STRINGS ${MPI_MPI_H} OMPI_VERSION_RELEASE_STRING
+ REGEX "#define.*OMPI_RELEASE_VERSION")
+ STRING(REGEX REPLACE "^.*OMPI_RELEASE_VERSION.*([0-9]+).*" "\\1"
+ OMPI_VERSION_SUBMINOR "${OMPI_VERSION_RELEASE_STRING}"
+ )
+ SET(OMPI_VERSION
+ "${OMPI_VERSION_MAJOR}.${OMPI_VERSION_MINOR}.${OMPI_VERSION_SUBMINOR}"
+ )
+ IF("${OMPI_VERSION}" STREQUAL "..")
+ SET(OMPI_VERSION)
+ SET(OMPI_VERSION_MAJOR)
+ SET(OMPI_VERSION_MINOR)
+ SET(OMPI_VERSION_SUBMINOR)
+ ENDIF()
+ENDIF()
+
+DEAL_II_PACKAGE_HANDLE(MPI
+ LIBRARIES
+ REQUIRED MPI_CXX_LIBRARIES
+ OPTIONAL MPI_Fortran_LIBRARIES MPI_C_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED MPI_CXX_INCLUDE_PATH
+ OPTIONAL MPI_C_INCLUDE_PATH
+ USER_INCLUDE_DIRS
+ REQUIRED MPI_CXX_INCLUDE_PATH
+ OPTIONAL MPI_C_INCLUDE_PATH
+ CXX_FLAGS OPTIONAL MPI_CXX_COMPILE_FLAGS
+ LINKER_FLAGS OPTIONAL MPI_CXX_LINK_FLAGS
+ CLEAR
+ MPI_C_COMPILER
+ MPI_CXX_COMPILER
+ MPIEXEC
+ MPI_EXTRA_LIBRARY
+ MPI_Fortran_COMPILER
+ MPI_HEADER_PATH
+ MPI_LIB
+ MPI_LIBRARY
+ MPI_MPI_H
+ )
+
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# MUMPS_VERSION_SUBMINOR
#
+SET(MUMPS_DIR "" CACHE PATH "An optional hint to a mumps directory")
+SET(SCALAPACK_DIR "" CACHE PATH "An optional hint to a SCALAPACK directory")
+SET(BLACS_DIR "" CACHE PATH "An optional hint to a BLACS directory")
SET_IF_EMPTY(MUMPS_DIR "$ENV{MUMPS_DIR}")
+SET_IF_EMPTY(SCALAPACK_DIR "$ENV{SCALAPACK_DIR}")
+SET_IF_EMPTY(BLACS_DIR "$ENV{BLACS_DIR}")
-INCLUDE(FindPackageHandleStandardArgs)
+#
+# Search for scalapack:
+#
+
+DEAL_II_FIND_LIBRARY(SCALAPACK_LIBRARY NAMES scalapack
+ HINTS ${SCALAPACK_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
+ )
#
-# Search for all known dependencies of MUMPS:
-# (We'll rely on the user of FindMUMPS, setting up mpi *cough*)
+# Well, depending on the version of scalapack and the distribution it might
+# be necessary to search for blacs, too. So we do this in a very
+# probabilistic way...
#
-FIND_PACKAGE(SCALAPACK) # which will also include lapack and blas
+FOREACH(_lib blacs blacsCinit blacsF77init)
+ STRING(TOUPPER "${_lib}" _lib_upper)
+ DEAL_II_FIND_LIBRARY(${_lib_upper}_LIBRARY
+ NAMES ${_lib} ${_lib}_MPI-LINUX-0 ${_lib}_MPI-DARWIN-0
+ HINTS ${BLACS_DIR} ${SCALAPACK_DIR} ${SCALAPACK_DIR}/../blacs/
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib LIB
+ )
+ENDFOREACH()
+#
+# Search for mumps:
+#
-FIND_PATH(MUMPS_INCLUDE_DIR dmumps_c.h
- HINTS
- ${MUMPS_DIR}
- PATH_SUFFIXES
- mumps include/mumps include
+DEAL_II_FIND_PATH(MUMPS_INCLUDE_DIR dmumps_c.h
+ HINTS ${MUMPS_DIR}
+ PATH_SUFFIXES mumps include/mumps include
)
-FIND_LIBRARY(DMUMPS_LIBRARY
+DEAL_II_FIND_LIBRARY(DMUMPS_LIBRARY
NAMES dmumps
- HINTS
- ${MUMPS_DIR}
+ HINTS ${MUMPS_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-FIND_LIBRARY(MUMPS_COMMON_LIBRARY
+DEAL_II_FIND_LIBRARY(MUMPS_COMMON_LIBRARY
NAMES mumps_common
- HINTS
- ${MUMPS_DIR}
+ HINTS ${MUMPS_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
#
# If we can find libport.so (or similiar), link it in as well:
#
-FIND_LIBRARY(PORD_LIBRARY
+DEAL_II_FIND_LIBRARY(PORD_LIBRARY
NAMES pord
- HINTS
- ${MUMPS_DIR}
+ HINTS ${MUMPS_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-MARK_AS_ADVANCED(PORD_LIBRARY)
-IF(PORD_LIBRARY MATCHES "-NOTFOUND")
- SET(PORD_LIBRARY "")
- UNSET(PORD_LIBRARY CACHE)
-ENDIF()
IF(EXISTS ${MUMPS_INCLUDE_DIR}/dmumps_c.h)
FILE(STRINGS "${MUMPS_INCLUDE_DIR}/dmumps_c.h" MUMPS_VERSION_STRING
)
ENDIF()
-SET(_output ${DMUMPS_LIBRARY} ${MUMPS_COMMON_LIBRARY} ${PORD_LIBRARY})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(MUMPS DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- DMUMPS_LIBRARY
- MUMPS_COMMON_LIBRARY
- MUMPS_INCLUDE_DIR
- SCALAPACK_FOUND
+DEAL_II_PACKAGE_HANDLE(MUMPS
+ LIBRARIES
+ REQUIRED DMUMPS_LIBRARY MUMPS_COMMON_LIBRARY
+ OPTIONAL PORD_LIBRARY
+ REQUIRED SCALAPACK_LIBRARY LAPACK_LIBRARIES
+ OPTIONAL BLACS_LIBRARY BLACSCINIT_LIBRARY BLACSF77INIT_LIBRARY MPI_Fortran_LIBRARIES
+ OPTIONAL METIS_LIBRARIES MPI_Fortran_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED MUMPS_INCLUDE_DIR
+ USER_INCLUDE_DIRS
+ REQUIRED MUMPS_INCLUDE_DIR
+ LINKER_FLAGS
+ OPTIONAL LAPACK_LINKER_FLAGS
+ CLEAR
+ DMUMPS_LIBRARY MUMPS_COMMON_LIBRARY PORD_LIBRARY SCALAPACK_LIBRARY
+ BLACS_LIBRARY BLACSCINIT_LIBRARY BLACSF77INIT_LIBRARY MUMPS_INCLUDE_DIR
)
-
-MARK_AS_ADVANCED(
- DMUMPS_LIBRARY
- MUMPS_COMMON_LIBRARY
- MUMPS_INCLUDE_DIR
- PORT_LIBRARY
- )
-
-IF(MUMPS_FOUND)
- SET(MUMPS_INCLUDE_DIRS
- ${MUMPS_INCLUDE_DIR}
- )
- SET(MUMPS_LIBRARIES
- ${DMUMPS_LIBRARY}
- ${MUMPS_COMMON_LIBRARY}
- ${PORD_LIBRARY}
- ${SCALAPACK_LIBRARIES}
- ${METIS_LIBRARIES} # for good measure
- ${MPI_Fortran_LIBRARIES} # for good measure
- )
- SET(MUMPS_LINKER_FLAGS
- ${SCALAPACK_LINKER_FLAGS}
- )
-
- MARK_AS_ADVANCED(MUMPS_DIR)
-ELSE()
- SET(MUMPS_DIR "" CACHE PATH
- "An optional hint to a mumps directory"
- )
-ENDIF()
-
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2013 - 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Try to find the MUPARSER library
+#
+# This module exports
+#
+# MUPARSER_LIBRARIES
+# MUPARSER_INCLUDE_DIRS
+# MUPARSER_VERSION
+# MUPARSER_VERSION_MAJOR
+# MUPARSER_VERSION_MINOR
+# MUPARSER_VERSION_SUBMINOR
+#
+
+SET(MUPARSER_DIR "" CACHE PATH "An optional hint to a MUPARSER installation")
+SET_IF_EMPTY(MUPARSER_DIR "$ENV{MUPARSER_DIR}")
+
+DEAL_II_FIND_LIBRARY(MUPARSER_LIBRARY
+ NAMES muparser muparserd
+ HINTS ${MUPARSER_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
+ )
+
+DEAL_II_FIND_PATH(MUPARSER_INCLUDE_DIR muParserDef.h
+ HINTS ${MUPARSER_DIR}
+ PATH_SUFFIXES include
+ )
+
+IF(EXISTS ${MUPARSER_INCLUDE_DIR}/muParserDef.h)
+ FILE(STRINGS "${MUPARSER_INCLUDE_DIR}/muParserDef.h" MUPARSER_VERSION_STRING
+ REGEX "#define MUP_VERSION _T"
+ )
+ STRING(REGEX REPLACE ".*\"([0-9]+)\\.[0-9]+\\..*" "\\1"
+ MUPARSER_VERSION_MAJOR "${MUPARSER_VERSION_STRING}"
+ )
+ STRING(REGEX REPLACE ".*\\.([0-9]+)\\..*" "\\1"
+ MUPARSER_VERSION_MINOR "${MUPARSER_VERSION_STRING}"
+ )
+ STRING(REGEX REPLACE ".*\\.[0-9]+\\.([0-9]+)\".*" "\\1"
+ MUPARSER_VERSION_SUBMINOR "${MUPARSER_VERSION_STRING}"
+ )
+ SET(MUPARSER_VERSION
+ "${MUPARSER_VERSION_MAJOR}.${MUPARSER_VERSION_MINOR}.${MUPARSER_VERSION_SUBMINOR}"
+ )
+ENDIF()
+
+DEAL_II_PACKAGE_HANDLE(MUPARSER
+ LIBRARIES REQUIRED MUPARSER_LIBRARY
+ INCLUDE_DIRS REQUIRED MUPARSER_INCLUDE_DIR
+ CLEAR MUPARSER_LIBRARY MUPARSER_INCLUDE_DIR
+ )
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# NETCDF_INCLUDE_DIRS
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(NETCDF_DIR "" CACHE PATH "An optional hint to a NETCDF installation")
SET_IF_EMPTY(NETCDF_DIR "$ENV{NETCDF_DIR}")
-FIND_PATH(NETCDF_INCLUDE_DIR netcdfcpp.h
- HINTS
- ${NETCDF_DIR}
- PATH_SUFFIXES
- netcdf include
+DEAL_II_FIND_PATH(NETCDF_INCLUDE_DIR netcdfcpp.h
+ HINTS ${NETCDF_DIR}
+ PATH_SUFFIXES netcdf include
)
#
# - separate C++ and C library search
#
-FIND_LIBRARY(NETCDF_CPLUSPLUS_LIBRARY NAMES netcdf_c++ netcdf_cpp
- HINTS
- ${NETCDF_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib
- )
-
-FIND_LIBRARY(NETCDF_C_LIBRARY NAMES netcdf
- HINTS
- ${NETCDF_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib
+DEAL_II_FIND_LIBRARY(NETCDF_CPLUSPLUS_LIBRARY NAMES netcdf_c++ netcdf_cpp
+ HINTS ${NETCDF_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-SET(_output ${NETCDF_CPLUSPLUS_LIBRARY} ${NETCDF_C_LIBRARY})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETCDF DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- NETCDF_CPLUSPLUS_LIBRARY
- NETCDF_C_LIBRARY
- NETCDF_INCLUDE_DIR
+DEAL_II_FIND_LIBRARY(NETCDF_C_LIBRARY NAMES netcdf
+ HINTS ${NETCDF_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-MARK_AS_ADVANCED(
- NETCDF_CPLUSPLUS_LIBRARY
- NETCDF_C_LIBRARY
- NETCDF_INCLUDE_DIR
+DEAL_II_PACKAGE_HANDLE(NETCDF
+ LIBRARIES REQUIRED NETCDF_CPLUSPLUS_LIBRARY NETCDF_C_LIBRARY
+ INCLUDE_DIRS REQUIRED NETCDF_INCLUDE_DIR
+ CLEAR NETCDF_CPLUSPLUS_LIBRARY NETCDF_C_LIBRARY NETCDF_INCLUDE_DIR
)
-
-IF(NETCDF_FOUND)
- SET(NETCDF_INCLUDE_DIRS
- ${NETCDF_INCLUDE_DIR}
- )
- SET(NETCDF_LIBRARIES
- ${NETCDF_CPLUSPLUS_LIBRARY}
- ${NETCDF_C_LIBRARY}
- )
-
- MARK_AS_ADVANCED(NETCDF_DIR)
-ELSE()
- SET(NETCDF_DIR "" CACHE PATH
- "An optional hint to a NETCDF installation"
- )
-ENDIF()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# P4EST_VERSION_PATCH
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(P4EST_DIR "" CACHE PATH
+ "An optional hint to a p4est installation/directory"
+ )
SET_IF_EMPTY(P4EST_DIR "$ENV{P4EST_DIR}")
SET_IF_EMPTY(SC_DIR "$ENV{SC_DIR}")
# given, take what we chose for p4est.
#
-FIND_PATH(P4EST_INCLUDE_DIR p4est_config.h
- HINTS
- ${P4EST_DIR}/FAST
- ${P4EST_DIR}/DEBUG
- ${P4EST_DIR}
- PATH_SUFFIXES
- p4est include/p4est include src
- )
-
-FIND_PATH(SC_INCLUDE_DIR sc.h
+DEAL_II_FIND_PATH(SC_INCLUDE_DIR sc.h
HINTS
${SC_DIR}/FAST
${SC_DIR}/DEBUG
sc include/p4est include src sc/src
)
-FIND_LIBRARY(P4EST_LIBRARY_OPTIMIZED
+DEAL_II_FIND_LIBRARY(P4EST_LIBRARY_OPTIMIZED
NAMES p4est
- HINTS
- ${P4EST_DIR}/FAST
- ${P4EST_DIR}/DEBUG
- ${P4EST_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib src
+ HINTS ${P4EST_DIR}/FAST ${P4EST_DIR}/DEBUG ${P4EST_DIR}
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib src
)
-FIND_LIBRARY(P4EST_LIBRARY_DEBUG
- NAMES p4est
- HINTS
- ${P4EST_DIR}/DEBUG
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib src
- )
-
-FIND_LIBRARY(SC_LIBRARY_OPTIMIZED
+DEAL_II_FIND_LIBRARY(SC_LIBRARY_OPTIMIZED
NAMES sc
HINTS
${SC_DIR}/FAST
lib${LIB_SUFFIX} lib64 lib src sc/src
)
-FIND_LIBRARY(SC_LIBRARY_DEBUG
- NAMES sc
- HINTS
- ${SC_DIR}/DEBUG
- ${P4EST_DIR}/DEBUG
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib src sc/src
- )
+#
+# Support debug variants as well:
+#
-SET(_output ${P4EST_LIBRARY_OPTMIZED} ${SC_LIBRARY_OPTIMIZED})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(P4EST DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- P4EST_LIBRARY_OPTIMIZED
- SC_LIBRARY_OPTIMIZED
- P4EST_INCLUDE_DIR
- SC_INCLUDE_DIR
+DEAL_II_FIND_LIBRARY(P4EST_LIBRARY_DEBUG
+ NAMES p4est
+ HINTS ${P4EST_DIR}/DEBUG
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib src
)
-MARK_AS_ADVANCED(
- P4EST_LIBRARY_OPTIMIZED
- P4EST_LIBRARY_DEBUG
- P4EST_INCLUDE_DIR
- SC_LIBRARY_OPTIMIZED
- SC_LIBRARY_DEBUG
- SC_INCLUDE_DIR
+DEAL_II_FIND_LIBRARY(SC_LIBRARY_DEBUG
+ NAMES sc
+ HINTS ${SC_DIR}/DEBUG ${P4EST_DIR}/DEBUG
+ PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib src sc/src
)
+IF( ( "${P4EST_LIBRARY_OPTIMIZED}" STREQUAL "${P4EST_LIBRARY_DEBUG}"
+ AND "${SC_LIBRARY_OPTIMIZED}" STREQUAL "${SC_LIBRARY_DEBUG}" )
+ OR P4EST_LIBRARY_DEBUG MATCHES "-NOTFOUND"
+ OR SC_LIBRARY_DEBUG MATCHES "-NOTFOUND" )
+ SET(_libraries P4EST_LIBRARY_OPTIMIZED SC_LIBRARY_OPTIMIZED)
+ELSE()
+ SET(_libraries
+ optimized P4EST_LIBRARY_OPTIMIZED SC_LIBRARY_OPTIMIZED
+ debug P4EST_LIBRARY_DEBUG SC_LIBRARY_DEBUG
+ general
+ )
+ENDIF()
-IF(P4EST_FOUND)
- IF( ( "${P4EST_LIBRARY_OPTIMIZED}" STREQUAL "${P4EST_LIBRARY_DEBUG}"
- AND
- "${SC_LIBRARY_OPTIMIZED}" STREQUAL "${SC_LIBRARY_DEBUG}" )
- OR P4EST_LIBRARY_DEBUG MATCHES "-NOTFOUND"
- OR SC_LIBRARY_DEBUG MATCHES "-NOTFOUND" )
- SET(P4EST_LIBRARIES
- ${P4EST_LIBRARY_OPTIMIZED}
- ${SC_LIBRARY_OPTIMIZED}
- )
- ELSE()
- SET(P4EST_LIBRARIES
- optimized
- ${P4EST_LIBRARY_OPTIMIZED}
- ${SC_LIBRARY_OPTIMIZED}
- debug
- ${P4EST_LIBRARY_DEBUG}
- ${SC_LIBRARY_DEBUG}
- general
- )
- ENDIF()
-
- LIST(APPEND P4EST_LIBRARIES
- ${LAPACK_LIBRARIES} # for good measure
- ${MPI_C_LIBRARIES} # for good measure
- )
- SET(P4EST_INCLUDE_DIRS
- ${P4EST_INCLUDE_DIR}
- ${SC_INCLUDE_DIR}
- )
+DEAL_II_FIND_PATH(P4EST_INCLUDE_DIR p4est_config.h
+ HINTS ${P4EST_DIR}/FAST ${P4EST_DIR}/DEBUG ${P4EST_DIR}
+ PATH_SUFFIXES p4est include/p4est include src
+ )
+IF(EXISTS ${P4EST_INCLUDE_DIR}/p4est_config.h)
#
# Determine mpi support of p4est:
#
IF("${P4EST_MPI_STRING}" STREQUAL "")
SET(P4EST_WITH_MPI FALSE)
ELSE()
-
SET(P4EST_WITH_MPI TRUE)
ENDIF()
P4EST_VERSION_SUBMINOR "${P4EST_VERSION}")
# Now for the patch number such as in 0.3.4.1. If there
- # is no patch number, then the REGEX REPLACE will fail,
- # setting P4EST_VERSION_PATCH to P4EST_VERSION. If that
+ # is no patch number, then REGEX REPLACE will set
+ # P4EST_VERSION_PATCH to an empty string. If that
# is the case, then set the patch number to zero
STRING(REGEX REPLACE
- "^[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)?.*$" "\\1"
+ "^[0-9]+\\.[0-9]+\\.[0-9]+\\.?(([0-9]+)?).*$" "\\1"
P4EST_VERSION_PATCH "${P4EST_VERSION}")
- IF(${P4EST_VERSION_PATCH} STREQUAL "${P4EST_VERSION}")
+ IF("${P4EST_VERSION_PATCH}" STREQUAL "")
SET(P4EST_VERSION_PATCH "0")
ENDIF()
-
-
- MARK_AS_ADVANCED(P4EST_DIR)
-ELSE()
- SET(P4EST_DIR "" CACHE PATH
- "An optional hint to a p4est installation/directory"
- )
ENDIF()
+DEAL_II_PACKAGE_HANDLE(P4EST
+ LIBRARIES
+ REQUIRED ${_libraries}
+ OPTIONAL LAPACK_LIBRARIES MPI_C_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED P4EST_INCLUDE_DIR SC_INCLUDE_DIR
+ USER_INCLUDE_DIRS
+ REQUIRED P4EST_INCLUDE_DIR SC_INCLUDE_DIR
+ CLEAR
+ SC_INCLUDE_DIR P4EST_LIBRARY_OPTIMIZED SC_LIBRARY_OPTIMIZED
+ P4EST_LIBRARY_DEBUG SC_LIBRARY_DEBUG P4EST_INCLUDE_DIR
+ )
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# PETSC_WITH_COMPLEX
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(PETSC_DIR "" CACHE PATH "An optional hint to a PETSc directory")
+SET(PETSC_ARCH "" CACHE STRING "An optional hint to a PETSc arch")
SET_IF_EMPTY(PETSC_DIR "$ENV{PETSC_DIR}")
SET_IF_EMPTY(PETSC_ARCH "$ENV{PETSC_ARCH}")
-
-FIND_LIBRARY(PETSC_LIBRARY
+DEAL_II_FIND_LIBRARY(PETSC_LIBRARY
NAMES petsc
- HINTS
- # petsc is special. Account for that
- ${PETSC_DIR}
- ${PETSC_DIR}/${PETSC_ARCH}
+ HINTS ${PETSC_DIR} ${PETSC_DIR}/${PETSC_ARCH}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
# Search for the first part of the includes:
#
-FIND_PATH(PETSC_INCLUDE_DIR_ARCH petscconf.h
- HINTS
- # petsc is special. Account for that
- ${PETSC_DIR}
- ${PETSC_DIR}/${PETSC_ARCH}
- ${PETSC_INCLUDE_DIRS}
+DEAL_II_FIND_PATH(PETSC_INCLUDE_DIR_ARCH petscconf.h
+ HINTS ${PETSC_DIR} ${PETSC_DIR}/${PETSC_ARCH} ${PETSC_INCLUDE_DIRS}
PATH_SUFFIXES petsc include include/petsc
)
+SET(PETSC_PETSCCONF_H "${PETSC_INCLUDE_DIR_ARCH}/petscconf.h")
+IF(EXISTS ${PETSC_PETSCCONF_H})
+ #
+ # Is petsc compiled with support for MPIUNI?
+ #
+ FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_MPIUNI_STRING
+ REGEX "#define.*PETSC_HAVE_MPIUNI 1")
+ IF("${PETSC_MPIUNI_STRING}" STREQUAL "")
+ SET(PETSC_WITH_MPIUNI FALSE)
+ ELSE()
+ SET(PETSC_WITH_MPIUNI TRUE)
+ ENDIF()
+
+ #
+ # Is petsc compiled with support for 64BIT_INDICES?
+ #
+ FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_64BIT_INDICES_STRING
+ REGEX "#define.*PETSC_USE_64BIT_INDICES 1")
+ IF("${PETSC_64BIT_INDICES_STRING}" STREQUAL "")
+ SET(PETSC_WITH_64BIT_INDICES FALSE)
+ ELSE()
+ SET(PETSC_WITH_64BIT_INDICES TRUE)
+ ENDIF()
+
+ #
+ # Is petsc compiled with support for COMPLEX numbers?
+ #
+ FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_COMPLEX_STRING
+ REGEX "#define.*PETSC_USE_COMPLEX 1")
+ IF("${PETSC_COMPLEX_STRING}" STREQUAL "")
+ SET(PETSC_WITH_COMPLEX FALSE)
+ ELSE()
+ SET(PETSC_WITH_COMPLEX TRUE)
+ ENDIF()
+ENDIF()
+
#
# Sometimes, this is not enough...
# If petsc is not installed but in source tree layout, there will be
# Either way, we must be able to find petscversion.h:
#
-FIND_PATH(PETSC_INCLUDE_DIR_COMMON petscversion.h
- HINTS
- ${PETSC_DIR}
- ${PETSC_DIR}/${PETSC_ARCH}
- ${PETSC_INCLUDE_DIRS}
+DEAL_II_FIND_PATH(PETSC_INCLUDE_DIR_COMMON petscversion.h
+ HINTS ${PETSC_DIR} ${PETSC_DIR}/${PETSC_ARCH} ${PETSC_INCLUDE_DIRS}
PATH_SUFFIXES petsc include include/petsc
)
+SET(PETSC_PETSCVERSION_H "${PETSC_INCLUDE_DIR_COMMON}/petscversion.h")
+IF(EXISTS ${PETSC_PETSCVERSION_H})
+ FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_MAJOR_STRING
+ REGEX "#define.*PETSC_VERSION_MAJOR")
+ STRING(REGEX REPLACE "^.*PETSC_VERSION_MAJOR.*([0-9]+).*" "\\1"
+ PETSC_VERSION_MAJOR "${PETSC_VERSION_MAJOR_STRING}"
+ )
+ FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_MINOR_STRING
+ REGEX "#define.*PETSC_VERSION_MINOR")
+ STRING(REGEX REPLACE "^.*PETSC_VERSION_MINOR.*([0-9]+).*" "\\1"
+ PETSC_VERSION_MINOR "${PETSC_VERSION_MINOR_STRING}"
+ )
+ FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_SUBMINOR_STRING
+ REGEX "#define.*PETSC_VERSION_SUBMINOR")
+ STRING(REGEX REPLACE "^.*PETSC_VERSION_SUBMINOR.*([0-9]+).*" "\\1"
+ PETSC_VERSION_SUBMINOR "${PETSC_VERSION_SUBMINOR_STRING}"
+ )
+ FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_PATCH_STRING
+ REGEX "#define.*PETSC_VERSION_PATCH")
+ STRING(REGEX REPLACE "^.*PETSC_VERSION_PATCH.*([0-9]+).*" "\\1"
+ PETSC_VERSION_PATCH "${PETSC_VERSION_PATCH_STRING}"
+ )
+ SET(PETSC_VERSION
+ "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.${PETSC_VERSION_PATCH}"
+ )
+ENDIF()
+
#
# So, up to this point it was easy. Now, the tricky part. Search for
# petscvariables and determine the includes and the link interface from
# that file:
#
-FIND_FILE(PETSC_PETSCVARIABLES
+DEAL_II_FIND_FILE(PETSC_PETSCVARIABLES
NAMES petscvariables
- HINTS
- ${PETSC_DIR}/${PETSC_ARCH}
- ${PETSC_DIR}
+ HINTS ${PETSC_DIR}/${PETSC_ARCH} ${PETSC_DIR}
PATH_SUFFIXES conf
)
IF(NOT PETSC_PETSCVARIABLES MATCHES "-NOTFOUND")
-
#
# Includes:
#
FILE(STRINGS "${PETSC_PETSCVARIABLES}" PETSC_EXTERNAL_LINK_LINE
REGEX "^PETSC_WITH_EXTERNAL_LIB =.*")
- SEPARATE_ARGUMENTS(PETSC_EXTERNAL_LINK_LINE)
- IF(NOT "${PETSC_EXTERNAL_LINK_LINE}" STREQUAL "${PETSC_EXTERNAL_LINK_LINE_SAVED}")
- SET(_new_petsc_external_link_line TRUE)
- ENDIF()
- SET(PETSC_EXTERNAL_LINK_LINE_SAVED "${PETSC_EXTERNAL_LINK_LINE}" CACHE INTERNAL "" FORCE)
+ SEPARATE_ARGUMENTS(PETSC_EXTERNAL_LINK_LINE)
SET(_hints)
SET(_petsc_libraries)
- FOREACH(_token ${PETSC_EXTERNAL_LINK_LINE}})
+ SET(_cleanup_variables)
+ FOREACH(_token ${PETSC_EXTERNAL_LINK_LINE})
IF(_token MATCHES "^-L")
# Build up hints with the help of all tokens passed with -L:
STRING(REGEX REPLACE "^-L" "" _token "${_token}")
# Search for every library that was specified with -l:
STRING(REGEX REPLACE "^-l" "" _token "${_token}")
- IF(_new_petsc_external_link_line)
- UNSET(PETSC_LIBRARY_${_token} CACHE)
- ENDIF()
+ IF(NOT _token MATCHES "(petsc|stdc\\+\\+|gcc_s|clang_rt)")
+ LIST(APPEND _cleanup_variables PETSC_LIBRARY_${_token})
- IF(_token MATCHES "^(c|quadmath|gfortran|m|rt|nsl|dl|pthread)$")
- FIND_SYSTEM_LIBRARY(PETSC_LIBRARY_${_token} NAMES ${_token})
- IF(NOT PETSC_LIBRARY_${_token} MATCHES "-NOTFOUND")
- LIST(APPEND _petsc_libraries ${PETSC_LIBRARY_${_token}})
+ IF(_token MATCHES "^(c|quadmath|gfortran|m|rt|nsl|dl|pthread)$")
+ FIND_SYSTEM_LIBRARY(PETSC_LIBRARY_${_token} NAMES ${_token})
+ ELSE()
+ DEAL_II_FIND_LIBRARY(PETSC_LIBRARY_${_token}
+ NAMES ${_token}
+ HINTS ${_hints}
+ )
ENDIF()
- ELSEIF(NOT _token MATCHES "(petsc|stdc\\+\\+|gcc_s)")
- FIND_LIBRARY(PETSC_LIBRARY_${_token}
- NAMES ${_token}
- HINTS ${_hints}
- )
IF(NOT PETSC_LIBRARY_${_token} MATCHES "-NOTFOUND")
LIST(APPEND _petsc_libraries ${PETSC_LIBRARY_${_token}})
ENDIF()
+
ENDIF()
ENDIF()
ENDFOREACH()
-
ENDIF()
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PETSC DEFAULT_MSG
- PETSC_LIBRARY
- PETSC_INCLUDE_DIR_ARCH
- PETSC_INCLUDE_DIR_COMMON
- )
-
-MARK_AS_ADVANCED(
- PETSC_INCLUDE_DIR_ARCH
- PETSC_INCLUDE_DIR_COMMON
- PETSC_INCLUDE_DIRS
- PETSC_LIBRARY
- PETSC_PETSCVARIABLES
+DEAL_II_PACKAGE_HANDLE(PETSC
+ LIBRARIES
+ REQUIRED PETSC_LIBRARY
+ OPTIONAL _petsc_libraries
+ INCLUDE_DIRS
+ REQUIRED PETSC_INCLUDE_DIR_COMMON PETSC_INCLUDE_DIR_ARCH
+ OPTIONAL _petsc_includes
+ USER_INCLUDE_DIRS
+ REQUIRED PETSC_INCLUDE_DIR_COMMON PETSC_INCLUDE_DIR_ARCH
+ OPTIONAL _petsc_includes
+ CLEAR
+ PETSC_LIBRARY PETSC_INCLUDE_DIR_COMMON PETSC_INCLUDE_DIR_ARCH
+ PETSC_PETSCVARIABLES ${_cleanup_variables}
)
IF(PETSC_FOUND)
- SET(PETSC_LIBRARIES
- ${PETSC_LIBRARY}
- ${_petsc_libraries}
- )
- SET(PETSC_INCLUDE_DIRS
- ${PETSC_INCLUDE_DIR_COMMON}
- ${PETSC_INCLUDE_DIR_ARCH}
- ${_petsc_includes}
- )
-
- SET(PETSC_PETSCCONF_H "${PETSC_INCLUDE_DIR_ARCH}/petscconf.h")
- SET(PETSC_PETSCVERSION_H "${PETSC_INCLUDE_DIR_COMMON}/petscversion.h")
-
- #
- # Is petsc compiled with support for MPIUNI?
- #
- FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_MPIUNI_STRING
- REGEX "#define.*PETSC_HAVE_MPIUNI 1")
- IF("${PETSC_MPIUNI_STRING}" STREQUAL "")
- SET(PETSC_WITH_MPIUNI FALSE)
- ELSE()
- SET(PETSC_WITH_MPIUNI TRUE)
- ENDIF()
-
- #
- # Is petsc compiled with support for 64BIT_INDICES?
- #
- FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_64BIT_INDICES_STRING
- REGEX "#define.*PETSC_USE_64BIT_INDICES 1")
- IF("${PETSC_64BIT_INDICES_STRING}" STREQUAL "")
- SET(PETSC_WITH_64BIT_INDICES FALSE)
- ELSE()
- SET(PETSC_WITH_64BIT_INDICES TRUE)
- ENDIF()
-
- #
- # Is petsc compiled with support for COMPLEX numbers?
- #
- FILE(STRINGS "${PETSC_PETSCCONF_H}" PETSC_COMPLEX_STRING
- REGEX "#define.*PETSC_USE_COMPLEX 1")
- IF("${PETSC_COMPLEX_STRING}" STREQUAL "")
- SET(PETSC_WITH_COMPLEX FALSE)
- ELSE()
- SET(PETSC_WITH_COMPLEX TRUE)
- ENDIF()
-
- FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_MAJOR_STRING
- REGEX "#define.*PETSC_VERSION_MAJOR")
- STRING(REGEX REPLACE "^.*PETSC_VERSION_MAJOR.*([0-9]+).*" "\\1"
- PETSC_VERSION_MAJOR "${PETSC_VERSION_MAJOR_STRING}"
- )
-
- FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_MINOR_STRING
- REGEX "#define.*PETSC_VERSION_MINOR")
- STRING(REGEX REPLACE "^.*PETSC_VERSION_MINOR.*([0-9]+).*" "\\1"
- PETSC_VERSION_MINOR "${PETSC_VERSION_MINOR_STRING}"
- )
-
- FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_SUBMINOR_STRING
- REGEX "#define.*PETSC_VERSION_SUBMINOR")
- STRING(REGEX REPLACE "^.*PETSC_VERSION_SUBMINOR.*([0-9]+).*" "\\1"
- PETSC_VERSION_SUBMINOR "${PETSC_VERSION_SUBMINOR_STRING}"
- )
-
- FILE(STRINGS "${PETSC_PETSCVERSION_H}" PETSC_VERSION_PATCH_STRING
- REGEX "#define.*PETSC_VERSION_PATCH")
- STRING(REGEX REPLACE "^.*PETSC_VERSION_PATCH.*([0-9]+).*" "\\1"
- PETSC_VERSION_PATCH "${PETSC_VERSION_PATCH_STRING}"
- )
-
- SET(PETSC_VERSION
- "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.${PETSC_VERSION_PATCH}"
- )
-
- MARK_AS_ADVANCED(PETSC_ARCH PETSC_DIR)
+ MARK_AS_ADVANCED(PETSC_ARCH)
ELSE()
- SET(PETSC_DIR "" CACHE PATH
- "An optional hint to a PETSc directory"
- )
- SET(PETSC_ARCH "" CACHE STRING
- "An optional hint to a PETSc arch"
- )
+ MARK_AS_ADVANCED(CLEAR PETSC_ARCH)
ENDIF()
-
+++ /dev/null
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2012 - 2013 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE at
-## the top level of the deal.II distribution.
-##
-## ---------------------------------------------------------------------
-
-#
-# Try to find the SCALAPACK library
-#
-# Used as a helper module for FindMUMPS.cmake
-#
-# This module exports
-#
-# SCALAPACK_LIBRARIES
-# SCALAPACK_LINKER_FLAGS
-#
-
-SET_IF_EMPTY(SCALAPACK_DIR "$ENV{SCALAPACK_DIR}")
-SET_IF_EMPTY(BLACS_DIR "$ENV{BLACS_DIR}")
-
-INCLUDE(FindPackageHandleStandardArgs)
-
-FIND_LIBRARY(SCALAPACK_LIBRARY NAMES scalapack
- HINTS
- ${SCALAPACK_DIR}
- PATH_SUFFIXES
- lib${LIB_SUFFIX} lib64 lib
- )
-
-#
-# Well, depending on the version of scalapack and the distribution it might
-# be necessary to search for blacs, too. So we do this in a very
-# probabilistic way...
-#
-FOREACH(_lib blacs blacsCinit blacsF77init)
- STRING(TOUPPER "${_lib}" _lib_upper)
- FIND_LIBRARY(${_lib_upper}_LIBRARY
- NAMES ${_lib} ${_lib}_MPI-LINUX-0 ${_lib}_MPI-DARWIN-0
- HINTS
- ${BLACS_DIR}
- ${SCALAPACK_DIR}
- ${SCALAPACK_DIR}/../blacs/
- PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib LIB
- )
- IF(NOT ${_lib_upper}_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND BLACS_LIBRARIES
- ${${_lib_upper}_LIBRARY}
- )
- ENDIF()
-ENDFOREACH()
-
-
-SET(_output ${SCALAPACK_LIBRARY} ${BLACS_LIBRARIES})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SCALAPACK DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- SCALAPACK_LIBRARY
- LAPACK_FOUND
- )
-
-MARK_AS_ADVANCED(
- lapack_LIBRARY
- atlas_LIBRARY
- blas_LIBRARY
- SCALAPACK_LIBRARY
- BLACS_LIBRARY
- BLACSCINIT_LIBRARY
- BLACSF77INIT_LIBRARY
- )
-
-IF(SCALAPACK_FOUND)
- SET(SCALAPACK_LIBRARIES
- ${SCALAPACK_LIBRARY}
- ${LAPACK_LIBRARIES}
- ${BLACS_LIBRARIES}
- ${MPI_Fortran_LIBRARIES} # for good measure
- )
- SET(SCALAPACK_LINKER_FLAGS
- ${LAPACK_LINKER_FLAGS}
- )
-
- MARK_AS_ADVANCED(SCALAPACK_DIR BLACS_DIR)
-ELSE()
- SET(SCALAPACK_DIR "" CACHE PATH
- "An optional hint to a SCALAPACK directory"
- )
- SET(BLACS_DIR "" CACHE PATH
- "An optional hint to a BLACS directory"
- )
-ENDIF()
-
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# SLEPC_VERSION_PATCH
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(SLEPC_DIR "" CACHE PATH "An optional hint to a SLEPC directory")
SET_IF_EMPTY(SLEPC_DIR "$ENV{SLEPC_DIR}")
SET_IF_EMPTY(PETSC_DIR "$ENV{PETSC_DIR}")
SET_IF_EMPTY(PETSC_ARCH "$ENV{PETSC_ARCH}")
# mechanism.
#
-FIND_LIBRARY(SLEPC_LIBRARY
+DEAL_II_FIND_LIBRARY(SLEPC_LIBRARY
NAMES slepc
- HINTS
- # SLEPC is special. Account for that
- ${SLEPC_DIR}
- ${SLEPC_DIR}/${PETSC_ARCH}
- ${PETSC_DIR}
+ HINTS ${SLEPC_DIR} ${SLEPC_DIR}/${PETSC_ARCH} ${PETSC_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
-FIND_PATH(SLEPC_INCLUDE_DIR_ARCH slepcconf.h
+DEAL_II_FIND_PATH(SLEPC_INCLUDE_DIR_ARCH slepcconf.h
HINTS
- # SLEPC is special. Account for that
${SLEPC_DIR}
${SLEPC_DIR}/${PETSC_ARCH}
${SLEPC_INCLUDE_DIRS}
PATH_SUFFIXES slepc include include/slepc
)
-FIND_PATH(SLEPC_INCLUDE_DIR_COMMON slepcversion.h
+DEAL_II_FIND_PATH(SLEPC_INCLUDE_DIR_COMMON slepcversion.h
HINTS
${SLEPC_DIR}
${SLEPC_DIR}/${PETSC_ARCH}
PATH_SUFFIXES slepc include include/slepc
)
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SLEPC DEFAULT_MSG
- SLEPC_LIBRARY
- SLEPC_INCLUDE_DIR_ARCH
- SLEPC_INCLUDE_DIR_COMMON
- PETSC_FOUND
- )
-
-MARK_AS_ADVANCED(
- SLEPC_DIR
- SLEPC_INCLUDE_DIR_ARCH
- SLEPC_INCLUDE_DIR_COMMON
- SLEPC_INCLUDE_DIRS
- SLEPC_LIBRARY
- )
-
-IF(SLEPC_FOUND)
- SET(SLEPC_INCLUDE_DIRS
- ${SLEPC_INCLUDE_DIR_ARCH}
- ${SLEPC_INCLUDE_DIR_COMMON}
- )
- SET(SLEPC_LIBRARIES
- ${SLEPC_LIBRARY}
- ${PETSC_LIBRARIES}
- )
-
- SET(SLEPC_SLEPCVERSION_H "${SLEPC_INCLUDE_DIR_COMMON}/slepcversion.h")
-
+SET(SLEPC_SLEPCVERSION_H "${SLEPC_INCLUDE_DIR_COMMON}/slepcversion.h")
+IF(EXISTS ${SLEPC_SLEPCVERSION_H})
FILE(STRINGS "${SLEPC_SLEPCVERSION_H}" SLEPC_VERSION_MAJOR_STRING
REGEX "#define.*SLEPC_VERSION_MAJOR")
STRING(REGEX REPLACE "^.*SLEPC_VERSION_MAJOR.*([0-9]+).*" "\\1"
SLEPC_VERSION_MAJOR "${SLEPC_VERSION_MAJOR_STRING}"
)
-
FILE(STRINGS "${SLEPC_SLEPCVERSION_H}" SLEPC_VERSION_MINOR_STRING
REGEX "#define.*SLEPC_VERSION_MINOR")
STRING(REGEX REPLACE "^.*SLEPC_VERSION_MINOR.*([0-9]+).*" "\\1"
SLEPC_VERSION_MINOR "${SLEPC_VERSION_MINOR_STRING}"
)
-
FILE(STRINGS "${SLEPC_SLEPCVERSION_H}" SLEPC_VERSION_SUBMINOR_STRING
REGEX "#define.*SLEPC_VERSION_SUBMINOR")
STRING(REGEX REPLACE "^.*SLEPC_VERSION_SUBMINOR.*([0-9]+).*" "\\1"
SLEPC_VERSION_SUBMINOR "${SLEPC_VERSION_SUBMINOR_STRING}"
)
-
FILE(STRINGS "${SLEPC_SLEPCVERSION_H}" SLEPC_VERSION_PATCH_STRING
REGEX "#define.*SLEPC_VERSION_PATCH")
STRING(REGEX REPLACE "^.*SLEPC_VERSION_PATCH.*([0-9]+).*" "\\1"
SLEPC_VERSION_PATCH "${SLEPC_VERSION_PATCH_STRING}"
)
-
SET(SLEPC_VERSION
"${SLEPC_VERSION_MAJOR}.${SLEPC_VERSION_MINOR}.${SLEPC_VERSION_SUBMINOR}.${SLEPC_VERSION_PATCH}"
)
-
- MARK_AS_ADVANCED(SLEPC_DIR)
-ELSE()
- SET(SLEPC_DIR "" CACHE PATH
- "An optional hint to a SLEPC directory"
- )
ENDIF()
+DEAL_II_PACKAGE_HANDLE(SLEPC
+ LIBRARIES
+ REQUIRED SLEPC_LIBRARY PETSC_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED SLEPC_INCLUDE_DIR_ARCH SLEPC_INCLUDE_DIR_COMMON
+ USER_INCLUDE_DIRS
+ REQUIRED SLEPC_INCLUDE_DIR_ARCH SLEPC_INCLUDE_DIR_COMMON
+ CLEAR SLEPC_LIBRARY SLEPC_INCLUDE_DIR_ARCH SLEPC_INCLUDE_DIR_COMMON
+ )
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# TBB_VERSION_MINOR
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(TBB_DIR "" CACHE PATH "An optional hint to a TBB installation")
SET_IF_EMPTY(TBB_DIR "$ENV{TBB_DIR}")
-FIND_PATH(TBB_INCLUDE_DIR tbb/tbb_stddef.h
- HINTS
- ${TBB_DIR}
- PATH_SUFFIXES include include/tbb tbb
- )
-
FILE(GLOB _path ${TBB_DIR}/build/*_release)
-
-FIND_LIBRARY(TBB_LIBRARY
+DEAL_II_FIND_LIBRARY(TBB_LIBRARY
NAMES tbb
HINTS
${_path}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
+#
+# Also search for the debug library:
+#
FILE(GLOB _path ${TBB_DIR}/build/*_debug)
-
-FIND_LIBRARY(TBB_DEBUG_LIBRARY
+DEAL_II_FIND_LIBRARY(TBB_DEBUG_LIBRARY
NAMES tbb_debug
HINTS
${_path}
${TBB_DIR}
PATH_SUFFIXES lib${LIB_SUFFIX} lib64 lib
)
+IF(NOT TBB_DEBUG_LIBRARY MATCHES "-NOTFOUND")
+ SET(TBB_WITH_DEBUGLIB TRUE)
+ SET(_libraries debug TBB_DEBUG_LIBRARY optimized TBB_LIBRARY)
+ELSE()
+ SET(_libraries TBB_LIBRARY)
+ENDIF()
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(TBB DEFAULT_MSG
- TBB_LIBRARY
- TBB_INCLUDE_DIR
+DEAL_II_FIND_PATH(TBB_INCLUDE_DIR tbb/tbb_stddef.h
+ HINTS
+ ${TBB_DIR}
+ PATH_SUFFIXES include include/tbb tbb
)
-IF(NOT TBB_INCLUDE_DIR MATCHES "-NOTFOUND")
+IF(EXISTS ${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h)
FILE(STRINGS "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" TBB_VERSION_MAJOR_STRING
REGEX "#define.*TBB_VERSION_MAJOR")
STRING(REGEX REPLACE "^.*TBB_VERSION_MAJOR.*([0-9]+).*" "\\1"
TBB_VERSION_MAJOR "${TBB_VERSION_MAJOR_STRING}"
)
-
FILE(STRINGS "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" TBB_VERSION_MINOR_STRING
REGEX "#define.*TBB_VERSION_MINOR")
STRING(REGEX REPLACE "^.*TBB_VERSION_MINOR.*([0-9]+).*" "\\1"
TBB_VERSION_MINOR "${TBB_VERSION_MINOR_STRING}"
)
-
SET(TBB_VERSION
"${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}"
)
ENDIF()
-MARK_AS_ADVANCED(
- TBB_LIBRARY
- TBB_DEBUG_LIBRARY
- TBB_INCLUDE_DIR
+DEAL_II_PACKAGE_HANDLE(TBB
+ LIBRARIES REQUIRED ${_libraries}
+ INCLUDE_DIRS REQUIRED TBB_INCLUDE_DIR
+ USER_INCLUDE_DIRS REQUIRED TBB_INCLUDE_DIR
+ CLEAR TBB_DEBUG_LIBRARY TBB_LIBRARY TBB_INCLUDE_DIR
)
-
-IF(TBB_FOUND)
-
- IF(NOT TBB_DEBUG_LIBRARY MATCHES "-NOTFOUND")
- SET(TBB_WITH_DEBUGLIB TRUE)
- SET(TBB_LIBRARIES debug ${TBB_DEBUG_LIBRARY} optimized ${TBB_LIBRARY})
- ELSE()
- SET(TBB_LIBRARIES ${TBB_LIBRARY})
- ENDIF()
-
- SET(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
-
- MARK_AS_ADVANCED(TBB_DIR)
-ELSE()
- SET(TBB_DIR "" CACHE PATH
- "An optional hint to a TBB installation"
- )
-ENDIF()
-
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# TRILINOS_HAS_C99_TR1_WORKAROUND
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(TRILINOS_DIR "" CACHE PATH "An optional hint to a Trilinos installation")
SET_IF_EMPTY(TRILINOS_DIR "$ENV{TRILINOS_DIR}")
#
NO_SYSTEM_ENVIRONMENT_PATH
)
-IF(NOT "${TRILINOS_CONFIG_DIR}" STREQUAL "${TRILINOS_CONFIG_DIR_SAVED}")
- SET(_new_trilinos_config TRUE)
-ENDIF()
-SET(TRILINOS_CONFIG_DIR_SAVED "${TRILINOS_CONFIG_DIR}" CACHE INTERNAL "" FORCE)
-
-
-#
-# Look for the one include file that we'll query for further information:
-#
-IF(_new_trilinos_config)
- UNSET(EPETRA_CONFIG_H CACHE)
-ENDIF()
-FIND_FILE(EPETRA_CONFIG_H Epetra_config.h
- HINTS ${Trilinos_INCLUDE_DIRS}
- NO_DEFAULT_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_CMAKE_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH
- NO_CMAKE_FIND_ROOT_PATH
- )
-
-
-#
-# *Boy* Sanitize the include paths given by TrilinosConfig.cmake...
-#
-SET(TRILINOS_INCLUDE_DIRS ${Trilinos_INCLUDE_DIRS})
-STRING(REGEX REPLACE
- "(lib64|lib)\\/cmake\\/Trilinos\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/" ""
- TRILINOS_INCLUDE_DIRS "${TRILINOS_INCLUDE_DIRS}"
- )
-
-
-#
-# We'd like to have the full library names but the Trilinos package only
-# exports a list with short names...
-# So we check again for every lib and store the full path:
-#
-FOREACH(_library ${Trilinos_LIBRARIES})
- IF(_new_trilinos_config)
- UNSET(TRILINOS_LIBRARY_${_library} CACHE)
- ENDIF()
-
- FIND_LIBRARY(TRILINOS_LIBRARY_${_library}
- NAMES ${_library}
- HINTS ${Trilinos_LIBRARY_DIRS}
- NO_DEFAULT_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_CMAKE_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH
- NO_CMAKE_FIND_ROOT_PATH
- )
-
- MARK_AS_ADVANCED(TRILINOS_LIBRARY_${_library})
-
- LIST(APPEND TRILINOS_LIBRARIES ${TRILINOS_LIBRARY_${_library}})
- LIST(APPEND TRILINOS_LIBRARY_VARIABLES TRILINOS_LIBRARY_${_library})
-
-ENDFOREACH()
-
-#
-# Add the link interface:
-#
-LIST(APPEND TRILINOS_LIBRARIES
- ${Trilinos_TPL_LIBRARIES}
- ${MPI_CXX_LIBRARIES} # for good measure
- )
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(TRILINOS DEFAULT_MSG
- TRILINOS_LIBRARIES # cosmetic: Gives nice output
- TRILINOS_CONFIG_FOUND
- EPETRA_CONFIG_H
- ${TRILINOS_LIBRARY_VARIABLES}
- )
-
-MARK_AS_ADVANCED(TRILINOS_CONFIG_DIR EPETRA_CONFIG_H)
-IF(TRILINOS_FOUND)
+IF(DEFINED Trilinos_VERSION)
#
# Extract version numbers:
#
"^[0-9]+\\.([0-9]+).*$" "\\1"
TRILINOS_VERSION_MINOR "${Trilinos_VERSION}")
+ # If there is no subminor number,
+ # TRILINOS_VERSION_SUBMINOR is set to an empty string.
+ # If that is the case, set the subminor number to zero
STRING(REGEX REPLACE
- "^[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1"
+ "^[0-9]+\\.[0-9]+\\.?(([0-9]+)?).*$" "\\1"
TRILINOS_VERSION_SUBMINOR "${Trilinos_VERSION}")
+ IF("${TRILINOS_VERSION_SUBMINOR}" STREQUAL "")
+ SET(TRILINOS_VERSION_SUBMINOR "0")
+ ENDIF()
+ENDIF()
+
+#
+# Look for the one include file that we'll query for further information:
+#
+DEAL_II_FIND_FILE(EPETRA_CONFIG_H Epetra_config.h
+ HINTS ${Trilinos_INCLUDE_DIRS}
+ NO_DEFAULT_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH
+ )
+IF(EXISTS ${EPETRA_CONFIG_H})
#
# Determine whether Trilinos was configured with MPI and 64bit indices:
#
ELSE()
SET(TRILINOS_WITH_NO_64BITS_INDICES FALSE)
ENDIF()
+ENDIF()
- #
- # Some versions of Sacado_cmath.hpp do things that aren't compatible
- # with the -std=c++0x flag of GCC, see deal.II FAQ.
- # Test whether that is indeed the case:
- #
- IF(_new_trilinos_config)
- UNSET(TRILINOS_SUPPORTS_CPP11 CACHE)
- UNSET(TRILINOS_HAS_C99_TR1_WORKAROUND CACHE)
- ENDIF()
+#
+# Some versions of Sacado_cmath.hpp do things that aren't compatible
+# with the -std=c++0x flag of GCC, see deal.II FAQ.
+# Test whether that is indeed the case:
+#
- LIST(APPEND CMAKE_REQUIRED_INCLUDES ${TRILINOS_INCLUDE_DIRS})
+DEAL_II_FIND_FILE(SACADO_CMATH_HPP Sacado_cmath.hpp
+ HINTS ${Trilinos_INCLUDE_DIRS}
+ NO_DEFAULT_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH
+ )
+
+IF(EXISTS ${SACADO_CMATH_HPP})
+ LIST(APPEND CMAKE_REQUIRED_INCLUDES ${Trilinos_INCLUDE_DIRS})
PUSH_CMAKE_REQUIRED("${DEAL_II_CXX11_FLAG}")
CHECK_CXX_SOURCE_COMPILES(
TRILINOS_HAS_C99_TR1_WORKAROUND
)
RESET_CMAKE_REQUIRED()
+ENDIF()
- MARK_AS_ADVANCED(TRILINOS_DIR)
-
-ELSE()
-
- SET(TRILINOS_LIBRARIES)
- SET(TRILINOS_INCLUDE_DIRS)
- UNSET(TRILINOS_CONFIG_DIR_SAVED CACHE)
+#
+# *Boy* Sanitize the include paths given by TrilinosConfig.cmake...
+#
+STRING(REGEX REPLACE
+ "(lib64|lib)\\/cmake\\/Trilinos\\/\\.\\.\\/\\.\\.\\/\\.\\.\\/" ""
+ Trilinos_INCLUDE_DIRS "${Trilinos_INCLUDE_DIRS}"
+ )
- SET(TRILINOS_DIR "" CACHE PATH
- "An optional hint to a Trilinos installation"
+#
+# We'd like to have the full library names but the Trilinos package only
+# exports a list with short names...
+# So we check again for every lib and store the full path:
+#
+SET(_libraries "")
+FOREACH(_library ${Trilinos_LIBRARIES})
+ LIST(APPEND _libraries TRILINOS_LIBRARY_${_library})
+ DEAL_II_FIND_LIBRARY(TRILINOS_LIBRARY_${_library}
+ NAMES ${_library}
+ HINTS ${Trilinos_LIBRARY_DIRS}
+ NO_DEFAULT_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_CMAKE_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_SYSTEM_PATH
+ NO_CMAKE_FIND_ROOT_PATH
)
-ENDIF()
+ENDFOREACH()
+
+DEAL_II_PACKAGE_HANDLE(TRILINOS
+ LIBRARIES
+ REQUIRED ${_libraries} Trilinos_TPL_LIBRARIES
+ OPTIONAL MPI_CXX_LIBRARIES
+ INCLUDE_DIRS
+ REQUIRED Trilinos_INCLUDE_DIRS
+ USER_INCLUDE_DIRS
+ REQUIRED Trilinos_INCLUDE_DIRS
+ CLEAR
+ TRILINOS_CONFIG_DIR EPETRA_CONFIG_H SACADO_CMATH_HPP ${_libraries}
+ TRILINOS_SUPPORTS_CPP11 TRILINOS_HAS_C99_TR1_WORKAROUND
+ )
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# UMFPACK_VERSION_SUBMINOR
#
-INCLUDE(FindPackageHandleStandardArgs)
-
+SET(UMFPACK_DIR "" CACHE PATH "An optional hint to an UMFPACK directory")
+SET(SUITESPARSE_DIR "" CACHE PATH
+ "An optional hint to a SUITESPARSE directory"
+ )
FOREACH(_comp SUITESPARSE SUITESPARSE_CONFIG UMFPACK AMD CHOLMOD COLAMD)
SET_IF_EMPTY(${_comp}_DIR "$ENV{${_comp}_DIR}")
ENDFOREACH()
MACRO(FIND_UMFPACK_PATH _comp _file)
STRING(TOLOWER ${_comp} _comp_lowercase)
STRING(TOUPPER ${_comp} _comp_uppercase)
- FIND_PATH(${_comp}_INCLUDE_DIR ${_file}
+ DEAL_II_FIND_PATH(${_comp}_INCLUDE_DIR ${_file}
HINTS
${${_comp_uppercase}_DIR}
${SUITESPARSE_DIR}/${_comp}
MACRO(FIND_UMFPACK_LIBRARY _comp _name)
STRING(TOUPPER ${_comp} _comp_uppercase)
- FIND_LIBRARY(${_comp}_LIBRARY
+ DEAL_II_FIND_LIBRARY(${_comp}_LIBRARY
NAMES ${_name}
HINTS
${${_comp_uppercase}_DIR}
PATH_SUFFIXES
lib${LIB_SUFFIX} lib64 lib Lib ${_comp}/Lib
)
- IF(NOT "${ARGN}" STREQUAL "REQUIRED")
- IF(${_comp}_LIBRARY MATCHES "-NOTFOUND")
- SET(${_comp}_LIBRARY "")
- UNSET(${_comp}_LIBRARY CACHE)
- ENDIF()
- ENDIF()
ENDMACRO()
FIND_UMFPACK_PATH(UMFPACK umfpack.h)
FIND_UMFPACK_PATH(AMD amd.h)
-#
-# Well, recent versions of UMFPACK include SuiteSparse_config.h, if so,
-# ensure that we'll find these headers as well.
-#
-IF(NOT UMFPACK_INCLUDE_DIR MATCHES "-NOTFOUND")
+IF(EXISTS ${UMFPACK_INCLUDE_DIR}/umfpack.h)
+ #
+ # Well, recent versions of UMFPACK include SuiteSparse_config.h, if so,
+ # ensure that we'll find these headers as well.
+ #
FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_SUITESPARSE_STRING
REGEX "#include \"SuiteSparse_config.h\"")
IF(NOT "${UMFPACK_SUITESPARSE_STRING}" STREQUAL "")
FIND_UMFPACK_PATH(SuiteSparse_config SuiteSparse_config.h)
- LIST(APPEND _required SuiteSparse_config_INCLUDE_DIR)
ENDIF()
+
+ FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_MAJOR_STRING
+ REGEX "#define.*UMFPACK_MAIN_VERSION")
+ STRING(REGEX REPLACE "^.*UMFPACK_MAIN_VERSION.*([0-9]+).*" "\\1"
+ UMFPACK_VERSION_MAJOR "${UMFPACK_VERSION_MAJOR_STRING}"
+ )
+ FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_MINOR_STRING
+ REGEX "#define.*UMFPACK_SUB_VERSION")
+ STRING(REGEX REPLACE "^.*UMFPACK_SUB_VERSION.*([0-9]+).*" "\\1"
+ UMFPACK_VERSION_MINOR "${UMFPACK_VERSION_MINOR_STRING}"
+ )
+ FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_SUBMINOR_STRING
+ REGEX "#define.*UMFPACK_SUBSUB_VERSION")
+ STRING(REGEX REPLACE "^.*UMFPACK_SUBSUB_VERSION.*([0-9]+).*" "\\1"
+ UMFPACK_VERSION_SUBMINOR "${UMFPACK_VERSION_SUBMINOR_STRING}"
+ )
+ SET(UMFPACK_VERSION
+ "${UMFPACK_VERSION_MAJOR}.${UMFPACK_VERSION_MINOR}.${UMFPACK_VERSION_SUBMINOR}"
+ )
ENDIF()
#
# Link against everything we can find to avoid underlinkage:
#
-FIND_UMFPACK_LIBRARY(UMFPACK umfpack REQUIRED)
-FIND_UMFPACK_LIBRARY(AMD amd REQUIRED)
+FIND_UMFPACK_LIBRARY(UMFPACK umfpack)
+FIND_UMFPACK_LIBRARY(AMD amd)
FIND_UMFPACK_LIBRARY(CHOLMOD cholmod)
FIND_UMFPACK_LIBRARY(COLAMD colamd)
FIND_UMFPACK_LIBRARY(CCOLAMD ccolamd)
)
RESET_CMAKE_REQUIRED()
-IF(EXISTS ${UMFPACK_INCLUDE_DIR}/umfpack.h)
- FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_MAJOR_STRING
- REGEX "#define.*UMFPACK_MAIN_VERSION")
- STRING(REGEX REPLACE "^.*UMFPACK_MAIN_VERSION.*([0-9]+).*" "\\1"
- UMFPACK_VERSION_MAJOR "${UMFPACK_VERSION_MAJOR_STRING}"
- )
- FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_MINOR_STRING
- REGEX "#define.*UMFPACK_SUB_VERSION")
- STRING(REGEX REPLACE "^.*UMFPACK_SUB_VERSION.*([0-9]+).*" "\\1"
- UMFPACK_VERSION_MINOR "${UMFPACK_VERSION_MINOR_STRING}"
- )
- FILE(STRINGS "${UMFPACK_INCLUDE_DIR}/umfpack.h" UMFPACK_VERSION_SUBMINOR_STRING
- REGEX "#define.*UMFPACK_SUBSUB_VERSION")
- STRING(REGEX REPLACE "^.*UMFPACK_SUBSUB_VERSION.*([0-9]+).*" "\\1"
- UMFPACK_VERSION_SUBMINOR "${UMFPACK_VERSION_SUBMINOR_STRING}"
- )
- SET(UMFPACK_VERSION
- "${UMFPACK_VERSION_MAJOR}.${UMFPACK_VERSION_MINOR}.${UMFPACK_VERSION_SUBMINOR}"
- )
+IF(LAPACK_SUITESPARSECONFIG_WITH_PIC OR NOT BUILD_SHARED_LIBS)
+ SET(_suitesparse_config SuiteSparse_config_LIBRARY)
ENDIF()
-SET(_output ${UMFPACK_LIBRARY} ${CHOLMOD_LIBRARY} ${CCOLAMD_LIBRARY} ${COLAMD_LIBRARY} ${CAMD_LIBRARY} ${AMD_LIBRARY} ${SuiteSparse_config_LIBRARY})
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(UMFPACK DEFAULT_MSG
- _output # Cosmetic: Gives nice output
- UMFPACK_LIBRARY
- AMD_LIBRARY
- UMFPACK_INCLUDE_DIR
- AMD_INCLUDE_DIR
- ${_required}
- LAPACK_FOUND
- )
-
-MARK_AS_ADVANCED(
- AMD_INCLUDE_DIR
- AMD_LIBRARY
- atlas_LIBRARY
- blas_LIBRARY
- CAMD_LIBRARY
- CHOLMOD_LIBRARY
- CCOLAMD_LIBRARY
- COLAMD_LIBRARY
- SuiteSparse_config_INCLUDE_DIR
- SuiteSparse_config_LIBRARY
- UMFPACK_INCLUDE_DIR
- UMFPACK_LIBRARY
+#
+# Add rt to the link interface as well (for whatever reason,
+# libsuitesparse.so depends on clock_gettime but the shared
+# lib does not record its dependence on librt.so as evidenced
+# by ldd :-( ):
+#
+FIND_SYSTEM_LIBRARY(rt_LIBRARY NAMES rt)
+MARK_AS_ADVANCED(rt_LIBRARY)
+
+DEAL_II_PACKAGE_HANDLE(UMFPACK
+ LIBRARIES
+ REQUIRED UMFPACK_LIBRARY
+ OPTIONAL CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY CAMD_LIBRARY ${_suitesparse_config}
+ REQUIRED AMD_LIBRARY
+ OPTIONAL METIS_LIBRARIES LAPACK_LIBRARIES rt_LIBRARY
+ INCLUDE_DIRS
+ REQUIRED UMFPACK_INCLUDE_DIR AMD_INCLUDE_DIR
+ OPTIONAL SuiteSparse_config_INCLUDE_DIR
+ LINKER_FLAGS
+ OPTIONAL LAPACK_LINKER_FLAGS
+ CLEAR
+ UMFPACK_LIBRARY CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY
+ CAMD_LIBRARY SuiteSparse_config_LIBRARY AMD_LIBRARY UMFPACK_INCLUDE_DIR
+ AMD_INCLUDE_DIR SuiteSparse_config_INCLUDE_DIR
)
-
IF(UMFPACK_FOUND)
- SET(UMFPACK_LIBRARIES
- ${UMFPACK_LIBRARY}
- ${CHOLMOD_LIBRARY}
- ${CCOLAMD_LIBRARY}
- ${COLAMD_LIBRARY}
- ${CAMD_LIBRARY}
- ${AMD_LIBRARY}
- )
- IF(LAPACK_SUITESPARSECONFIG_WITH_PIC OR NOT BUILD_SHARED_LIBS)
- LIST(APPEND UMFPACK_LIBRARIES ${SuiteSparse_config_LIBRARY})
- ENDIF()
-
- #
- # For good measure:
- #
- IF(METIS_FOUND)
- LIST(APPEND UMFPACK_LIBRARIES ${METIS_LIBRARIES})
- ENDIF()
-
- LIST(APPEND UMFPACK_LIBRARIES ${LAPACK_LIBRARIES})
-
- #
- # Add rt to the link interface as well (for whatever reason,
- # libsuitesparse.so depends on clock_gettime but the shared
- # lib does not record its dependence on librt.so as evidenced
- # by ldd :-( ):
- #
- FIND_SYSTEM_LIBRARY(rt_LIBRARY NAMES rt)
- MARK_AS_ADVANCED(rt_LIBRARY)
- IF(NOT rt_LIBRARY MATCHES "-NOTFOUND")
- LIST(APPEND UMFPACK_LIBRARIES ${rt_LIBRARY})
- ENDIF()
-
- SET(UMFPACK_INCLUDE_DIRS
- ${UMFPACK_INCLUDE_DIR}
- ${AMD_INCLUDE_DIR}
- ${SuiteSparse_config_INCLUDE_DIR}
- )
- SET(UMFPACK_LINKER_FLAGS
- ${LAPACK_LINKER_FLAGS}
- )
-
- MARK_AS_ADVANCED(UMFPACK_DIR SUITESPARSE_DIR)
+ MARK_AS_ADVANCED(SUITESPARSE_DIR)
ELSE()
- SET(UMFPACK_DIR "" CACHE PATH
- "An optional hint to an UMFPACK directory"
- )
- SET(SUITESPARSE_DIR "" CACHE PATH
- "An optional hint to a SUITESPARSE directory"
- )
+ MARK_AS_ADVANCED(CLEAR SUITESPARSE_DIR)
ENDIF()
--- /dev/null
+## ---------------------------------------------------------------------
+## $Id$
+##
+## Copyright (C) 2014 by the deal.II authors
+##
+## This file is part of the deal.II library.
+##
+## The deal.II library is free software; you can use it, redistribute
+## it, and/or modify it under the terms of the GNU Lesser General
+## Public License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+## The full text of the license can be found in the file LICENSE at
+## the top level of the deal.II distribution.
+##
+## ---------------------------------------------------------------------
+
+#
+# Try to find the ZLIB library
+#
+# This module exports
+#
+# ZLIB_LIBRARIES
+# ZLIB_INCLUDE_DIRS
+# ZLIB_VERSION
+#
+
+SET(ZLIB_DIR "" CACHE PATH "An optional hint to a ZLIB installation")
+SET_IF_EMPTY(ZLIB_DIR "$ENV{ZLIB_DIR}")
+
+#
+# Houston, we have a problem: CMake ships its own FindZLIB.cmake module.
+# Unfortunately we want to call DEAL_II_PACKAGE_HANDLE. Therefore, use the
+# original find module and do a dummy call to DEAL_II_PACKAGE_HANDLE:
+#
+
+IF(NOT "${ZLIB_DIR}" STREQUAL "")
+ SET(ZLIB_ROOT ${ZLIB_DIR})
+ENDIF()
+LIST(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+FIND_PACKAGE(ZLIB)
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules/)
+
+SET(ZLIB_VERSION ${ZLIB_VERSION_STRING})
+
+DEAL_II_PACKAGE_HANDLE(ZLIB
+ LIBRARIES REQUIRED ZLIB_LIBRARY
+ INCLUDE_DIRS REQUIRED ZLIB_INCLUDE_DIR
+ CLEAR ZLIB_INCLUDE_DIR ZLIB_LIBRARY
+ )
// return the result
std::string
replace_all (const std::string &in,
- const std::string &pattern,
- const std::string &substitute)
+ const std::string &pattern,
+ const std::string &substitute)
{
std::string x = in;
while (x.find(pattern) != std::string::npos)
x.replace (x.find(pattern),
- pattern.size(),
- substitute);
+ pattern.size(),
+ substitute);
return x;
}
-// extract from the start of #in the part of the string that ends with one of
-// the characters in #delim_list. The extracted part is deleted from #in
-// and returned. We skip characters in delim_list if they are preceded
-// by a backslash
+// extract from the start of #in the part of the string that ends with one
+// of the characters in #delim_list. The extracted part is deleted from #in
+// and returned. We skip characters in delim_list if they are preceded by a
+// backslash
std::string
get_substring_with_delim (std::string &in,
- const std::string &delim_list)
+ const std::string &delim_list)
{
std::string x;
while (in.size() != 0)
{
- // stop copying to the result
- // if the current character is
- // a delimiter, but only if the
- // previous character was not a
- // backslash
+ // stop copying to the result if the current character is a
+ // delimiter, but only if the previous character was not a backslash
if ((delim_list.find (in[0]) != std::string::npos)
- &&
- !((x.size() > 0)
- &&
- (x[x.size()-1] == '\\')))
- break;
+ &&
+ !((x.size() > 0)
+ &&
+ (x[x.size()-1] == '\\')))
+ break;
x += in[0];
in.erase (0, 1);
skip_space (std::string &in)
{
while ((in.size() != 0)
- &&
- ((in[0] == ' ') || (in[0] == '\t') || (in[0] == '\n')))
+ &&
+ ((in[0] == ' ') || (in[0] == '\t') || (in[0] == '\n')))
in.erase (0, 1);
}
{
const std::string::size_type slash_star_comment_end = line.find ("*/");
if (slash_star_comment_end == std::string::npos)
- {
- std::cerr << "The program can currently only handle /* block */"
- << "comments that start and end within the same line."
- << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "The program can currently only handle /* block */"
+ << "comments that start and end within the same line."
+ << std::endl;
+ std::exit (1);
+ }
line.erase (slash_star_comment_begin,
- slash_star_comment_end - slash_star_comment_begin + 2);
+ slash_star_comment_end - slash_star_comment_begin + 2);
}
return line;
whole_file += remove_comments (line);
whole_file += '\n';
}
- // substitute tabs by spaces, multiple
- // spaces by single ones
+ // substitute tabs by spaces, multiple spaces by single ones
for (unsigned int i=0; i<whole_file.size(); ++i)
if (whole_file[i] == '\t')
whole_file[i] = ' ';
-// split a given string assumed to consist of a list of substrings delimited
-// by a particular character into its components
+// split a given string assumed to consist of a list of substrings
+// delimited by a particular character into its components
std::list<std::string>
split_string_list (const std::string &s,
- const char delimiter)
+ const char delimiter)
{
std::string tmp = s;
std::list<std::string> split_list;
- // split the input list
+ // split the input list
while (tmp.length() != 0)
{
std::string name;
name = tmp;
if (name.find(delimiter) != std::string::npos)
- {
- name.erase (name.find(delimiter), std::string::npos);
- tmp.erase (0, tmp.find(delimiter)+1);
- }
+ {
+ name.erase (name.find(delimiter), std::string::npos);
+ tmp.erase (0, tmp.find(delimiter)+1);
+ }
else
- tmp = "";
+ tmp = "";
skip_space (name);
while ((name.size() != 0) && (name[name.length()-1] == ' '))
- name.erase (name.length()-1, 1);
+ name.erase (name.length()-1, 1);
split_list.push_back (name);
}
-// determine whether a given substring at position #pos and length #length in
-// the string #text is a real token, i.e. not just part of another word
+// determine whether a given substring at position #pos and length #length
+// in the string #text is a real token, i.e. not just part of another word
bool is_real_token (const std::string &text,
- const std::string::size_type pos,
- const std::string::size_type length)
+ const std::string::size_type pos,
+ const std::string::size_type length)
{
static const std::string token_chars ("abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- "_");
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "_");
if ((pos != 0) && (token_chars.find (text[pos-1]) != std::string::npos))
return false;
// substitute all occurrences of #token in #text by #substitute. because a
-// replacement token could be a templated class like std::complex<double> and
-// because the token to the substituted may be a template argument itself, we
-// surround the substitution by a space which shouldn't matter in C++
+// replacement token could be a templated class like std::complex<double>
+// and because the token to the substituted may be a template argument
+// itself, we surround the substitution by a space which shouldn't matter
+// in C++
std::string substitute_tokens (const std::string &text,
- const std::string &token,
- const std::string &substitute)
+ const std::string &token,
+ const std::string &substitute)
{
std::string x_text = text;
std::string::size_type pos = 0;
while ((pos = x_text.find(token, pos)) != std::string::npos)
{
if (is_real_token (x_text, pos, token.size()))
- {
- x_text.replace (pos, token.size(),
- std::string(" ")+substitute+std::string(" "));
- pos += substitute.size()+2;
- }
+ {
+ x_text.replace (pos, token.size(),
+ std::string(" ")+substitute+std::string(" "));
+ pos += substitute.size()+2;
+ }
else
- ++pos;
+ ++pos;
}
return x_text;
// read and parse the expansion lists like
-// REAL_SCALARS := { double; float; long double }
-// as specified at the top of the file and store them in
-// the global expansion_lists variable
+// REAL_SCALARS := { double; float; long double }
+// as specified at the top of the file and store them in the global
+// expansion_lists variable
void read_expansion_lists (const std::string &filename)
{
std::ifstream in (filename.c_str());
if (! in)
{
std::cerr << "Instantiation list file can not be read!"
- << std::endl;
+ << std::endl;
std::exit (1);
}
- // read the entire file into a string for
- // simpler processing. replace end-of-line
- // characters by spaces
+ // read the entire file into a string for simpler processing. replace
+ // end-of-line characters by spaces
std::string whole_file = read_whole_file (in);
- // now process entries of the form
- // NAME := { class1; class2; ...}.
+ // now process entries of the form
+ // NAME := { class1; class2; ...}.
while (whole_file.size() != 0)
{
const std::string
- name = get_substring_with_delim (whole_file, " :");
+ name = get_substring_with_delim (whole_file, " :");
skip_space (whole_file);
if (whole_file.find (":=") != 0)
- {
- std::cerr << "Invalid entry <" << name << '>' << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid entry <" << name << '>' << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 2);
skip_space (whole_file);
if (whole_file.find ("{") != 0)
- {
- std::cerr << "Invalid entry <" << name << '>' << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid entry <" << name << '>' << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 1);
skip_space (whole_file);
std::string
- expansion = get_substring_with_delim (whole_file, "}");
+ expansion = get_substring_with_delim (whole_file, "}");
if (whole_file.find ("}") != 0)
- {
- std::cerr << "Invalid entry <" << name << '>' << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid entry <" << name << '>' << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 1);
skip_space (whole_file);
- // assign but remove empty entries;
- // this may happen if an expansion list
- // ends in a semicolon (then we get an
- // empty entry at the end), or if there
- // are multiple semicolons after each
- // other (this may happen if, for
- // example, we have "Vector<double>;
- // TRILINOS_VECTOR;" and if
- // TRILINOS_VECTOR is an empty
- // expansion after running ./configure)
+ // assign but remove empty entries; this may happen if an expansion
+ // list ends in a semicolon (then we get an empty entry at the end),
+ // or if there are multiple semicolons after each other (this may
+ // happen if, for example, we have "Vector<double>; TRILINOS_VECTOR;"
+ // and if TRILINOS_VECTOR is an empty expansion after running
+ // ./configure)
expansion_lists[name]
- = delete_empty_entries (split_string_list (expansion, ';'));
+ = delete_empty_entries (split_string_list (expansion, ';'));
}
}
// produce all combinations of substitutions of the tokens given in the
// #substitutions list in #text and output it to std::cout
void substitute (const std::string &text,
- const std::list<std::pair<std::string, std::string> > &substitutions)
+ const std::list<std::pair<std::string, std::string> > &substitutions)
{
- // do things recursively: if the list of
- // substitutions has a single entry, then
- // process all of them. otherwise, process
- // the first in the list and call the
- // function recursively with the rest of
- // the substitutions
+ // do things recursively: if the list of substitutions has a single
+ // entry, then process all of them. otherwise, process the first in the
+ // list and call the function recursively with the rest of the
+ // substitutions
if (substitutions.size() > 1)
{
- // do the first substitution, then call
- // function recursively
+ // do the first substitution, then call function recursively
const std::string name = substitutions.front().first,
- pattern = substitutions.front().second;
+ pattern = substitutions.front().second;
const std::list<std::pair<std::string, std::string> >
- rest_of_substitutions (++substitutions.begin(),
- substitutions.end());
+ rest_of_substitutions (++substitutions.begin(),
+ substitutions.end());
for (std::list<std::string>::const_iterator
- expansion = expansion_lists[pattern].begin();
- expansion != expansion_lists[pattern].end();
- ++expansion)
- {
- std::string new_text
- = substitute_tokens (text, name, *expansion);
-
- substitute (new_text, rest_of_substitutions);
- }
+ expansion = expansion_lists[pattern].begin();
+ expansion != expansion_lists[pattern].end();
+ ++expansion)
+ {
+ std::string new_text
+ = substitute_tokens (text, name, *expansion);
+
+ substitute (new_text, rest_of_substitutions);
+ }
}
else if (substitutions.size() == 1)
{
- // do the substitutions
+ // do the substitutions
const std::string name = substitutions.front().first,
- pattern = substitutions.front().second;
+ pattern = substitutions.front().second;
for (std::list<std::string>::const_iterator
- expansion = expansion_lists[pattern].begin();
- expansion != expansion_lists[pattern].end();
- ++expansion)
- std::cout << substitute_tokens (text, name, *expansion)
- << std::endl;
+ expansion = expansion_lists[pattern].begin();
+ expansion != expansion_lists[pattern].end();
+ ++expansion)
+ std::cout << substitute_tokens (text, name, *expansion)
+ << std::endl;
}
else
{
std::cout << text
- << std::endl;
+ << std::endl;
}
}
// process the list of instantiations given in the form
-// --------------------
-// for (u,v:VECTORS; z:SCALARS) { f(u, z, const v &); }
-// --------------------
+// for (u,v:VECTORS; z:SCALARS) { f(u, z, const v &); }
void process_instantiations ()
{
std::string whole_file = read_whole_file (std::cin);
- // process entries of the form
- // for (X:Y; A:B) { INST }
+ // process entries of the form
+ // for (X:Y; A:B) { INST }
while (whole_file.size() != 0)
{
skip_space (whole_file);
if (whole_file.find ("for") != 0)
- {
- std::cerr << "Invalid instantiation list: missing 'for'" << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid instantiation list: missing 'for'" << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 3);
skip_space (whole_file);
if (whole_file.find ("(") != 0)
- {
- std::cerr << "Invalid instantiation list: missing '('" << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid instantiation list: missing '('" << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 1);
skip_space (whole_file);
const std::list<std::string>
- substitutions_list
- = split_string_list (get_substring_with_delim (whole_file,
- ")"),
- ';');
+ substitutions_list
+ = split_string_list (get_substring_with_delim (whole_file,
+ ")"),
+ ';');
if (whole_file.find (")") != 0)
- {
- std::cerr << "Invalid instantiation list: missing ')'" << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid instantiation list: missing ')'" << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 1);
skip_space (whole_file);
- // process the header
+ // process the header
std::list<std::pair<std::string, std::string> >
- substitutions;
+ substitutions;
for (std::list<std::string>::const_iterator
- s = substitutions_list.begin();
- s != substitutions_list.end(); ++s)
- {
- const std::list<std::string>
- names_and_type = split_string_list (*s, ':');
- if (names_and_type.size() != 2)
- {
- std::cerr << "Invalid instantiation header" << std::endl;
- std::exit (1);
- }
-
- const std::list<std::string>
- names = split_string_list (names_and_type.front(), ',');
-
- for (std::list<std::string>::const_iterator
- x = names.begin(); x != names.end(); ++x)
- substitutions.push_back (std::make_pair (*x,
- names_and_type.back()));
- }
-
- // now read the part in {...}
+ s = substitutions_list.begin();
+ s != substitutions_list.end(); ++s)
+ {
+ const std::list<std::string>
+ names_and_type = split_string_list (*s, ':');
+ if (names_and_type.size() != 2)
+ {
+ std::cerr << "Invalid instantiation header" << std::endl;
+ std::exit (1);
+ }
+
+ const std::list<std::string>
+ names = split_string_list (names_and_type.front(), ',');
+
+ for (std::list<std::string>::const_iterator
+ x = names.begin(); x != names.end(); ++x)
+ substitutions.push_back (std::make_pair (*x,
+ names_and_type.back()));
+ }
+
+ // now read the part in {...}
skip_space (whole_file);
if (whole_file.find ("{") != 0)
- {
- std::cerr << "Invalid substitution text" << std::endl;
- std::exit (1);
- }
+ {
+ std::cerr << "Invalid substitution text" << std::endl;
+ std::exit (1);
+ }
whole_file.erase (0, 1);
skip_space (whole_file);
const std::string text_to_substitute
- = get_substring_with_delim (whole_file, "}");
+ = get_substring_with_delim (whole_file, "}");
whole_file.erase (0,1);
skip_space (whole_file);
- // now produce the
- // substitutions. first replace
- // all occurrences of "\{" by
- // "{"
+ // now produce the substitutions. first replace all occurrences of
+ // "\{" by "{"
substitute (replace_all(replace_all(text_to_substitute, "\\{", "{"),
- "\\}", "}"),
- substitutions);
+ "\\}", "}"),
+ substitutions);
}
}
if (argc < 2)
{
std::cerr << "Usage: " << std::endl
- << " expand_instantiations class_list_files < in_file > out_file"
- << std::endl;
+ << " expand_instantiations class_list_files < in_file > out_file"
+ << std::endl;
std::exit (1);
}
#include <cstdlib>
#include <sys/stat.h>
- // base path for object files,
- // including trailing slash if
- // non-empty
+// base path for object files, including trailing slash if non-empty
std::string basepath;
- // list of include directories
+// list of include directories
std::vector<std::string> include_directories;
- // for each file that we ever visit,
- // store the set of other files it
- // includes directly
+// for each file that we ever visit, store the set of other files it
+// includes directly
std::map<std::string,std::set<std::string> > direct_includes;
- // A variable that stores whether
- // we want old-style or new-style format
+// A variable that stores whether we want old-style or new-style format
enum Format
- {
- old_style, new_style
- } format;
+{
+ old_style, new_style
+} format;
-bool file_exists(const std::string & file)
+bool file_exists(const std::string &file)
{
struct stat buf;
int error = stat (file.c_str(), &buf);
- return ((error == 0) &&
- ((buf.st_mode & S_IFMT) == S_IFREG));
+ return ((error == 0) &&
+ ((buf.st_mode & S_IFMT) == S_IFREG));
}
- // for the given file, fill a
- // respective entry in the "direct_includes"
- // map listing the names of those
- // files that are directly included
+// for the given file, fill a respective entry in the "direct_includes" map
+// listing the names of those files that are directly included
void determine_direct_includes (const std::string &file)
{
- // if this file has already been
- // treated, then leave it at this
+ // if this file has already been treated, then leave it at this
if (direct_includes.find (file) != direct_includes.end())
return;
- // otherwise, open the file and go
- // through it line by line to
- // search for other includes. we
- // will have to have the path to
- // the present file later, so get
- // it already here
+ // otherwise, open the file and go through it line by line to search for
+ // other includes. we will have to have the path to the present file
+ // later, so get it already here
std::string present_path;
if (file.find ('/') != std::string::npos)
present_path = std::string (file.begin(),
- file.begin()+file.rfind ('/')+1);
+ file.begin()+file.rfind ('/')+1);
std::ifstream in(file.c_str());
- // If the file does not exist, for
- // instance an ".inst" file which
- // will be generated by make later,
- // just return from this function.
- //
- // As a result, non-existing files
- // are expected to have no
- // dependencies.
+ // If the file does not exist, for instance an ".inst" file which will be
+ // generated by make later, just return from this function.
+ //
+ // As a result, non-existing files are expected to have no dependencies.
if (! ((bool)in))
return;
-
+
std::string line;
while (in)
{
- // get one line, eat whitespace
- // at the beginning and see
- // whether the first
- // non-whitespace is a #
- // character
+ // get one line, eat whitespace at the beginning and see whether the
+ // first non-whitespace is a # character
getline (in, line);
unsigned int pos=0;
for (; pos<line.length(); ++pos)
if ((line[pos] != ' ') && (line[pos] != '\t'))
break;
- // if no non-whitespace, or
- // something other than #: next
- // line
+ // if no non-whitespace, or something other than #: next line
if ((pos == line.length()) || (line[pos] != '#'))
continue;
- // ok, this is a preprocessor
- // line. eat pound sign and
- // again the next couple of
- // whitespaces
+ // ok, this is a preprocessor line. eat pound sign and again the next
+ // couple of whitespaces
++pos;
for (; pos<line.length(); ++pos)
if ((line[pos] != ' ') && (line[pos] != '\t'))
break;
- // and let's see whether the
- // following is the word
- // include
+ // and let's see whether the following is the word include
if ((line.length() < pos+7)
||
(! ((line[pos+0] == 'i') &&
(line[pos+6] == 'e'))))
continue;
- // ok, word found. advance pos
- // and eat more whitespace
+ // ok, word found. advance pos and eat more whitespace
pos += 7;
for (; pos<line.length(); ++pos)
if ((line[pos] != ' ') && (line[pos] != '\t'))
break;
- // check that the next char is
- // either '<' or '"'
+ // check that the next char is either '<' or '"'
if ((line[pos] != '"') && (line[pos] != '<'))
continue;
- // copy out name
+ // copy out name
std::string included_file;
for (unsigned int endpos=pos+1; endpos<line.length(); ++endpos)
if ((line[endpos]=='"') || (line[endpos] == '>'))
break;
}
if (included_file.length() == 0)
- {
- std::cerr << "Include file name empty in file <" << file << "> line: " << std::endl
- << line << std::endl;
- std::abort();
- }
-
-
- bool is_inst_file =
- included_file.size()>5
- && (included_file.rfind(".inst") == (included_file.size()-5));
-
- // .inst files are always relative to
- // the current path. We need a special
- // case, because they might not exist
- // at this point and the next block
- // checks the files for existence.
+ {
+ std::cerr << "Include file name empty in file <" << file << "> line: " << std::endl
+ << line << std::endl;
+ std::abort();
+ }
+
+
+ bool is_inst_file =
+ included_file.size()>5
+ && (included_file.rfind(".inst") == (included_file.size()-5));
+
+ // .inst files are always relative to the current path. We need a
+ // special case, because they might not exist at this point and the
+ // next block checks the files for existence.
if (is_inst_file)
- included_file = present_path+included_file;
-
+ included_file = present_path+included_file;
+
- // next try to locate the file in
- // absolute paths. For includes of the
- // form #include "...", we check the
- // current path first.
+ // next try to locate the file in absolute paths. For includes of the
+ // form #include "...", we check the current path first.
if (included_file[0] != '/' && !is_inst_file)
{
- bool is_relative_path = false;
+ bool is_relative_path = false;
if (line[pos] == '"' && file_exists(present_path+included_file))
- {
- included_file = present_path+included_file;
- is_relative_path = true;
- }
-
+ {
+ included_file = present_path+included_file;
+ is_relative_path = true;
+ }
+
if (is_relative_path == false)
- for (std::vector<std::string>::const_iterator
- include_dir=include_directories.begin();
+ for (std::vector<std::string>::const_iterator
+ include_dir=include_directories.begin();
include_dir!=include_directories.end(); ++include_dir)
- {
- if (file_exists((*include_dir+included_file)))
- {
- included_file = *include_dir+included_file;
- break;
- }
- }
+ {
+ if (file_exists((*include_dir+included_file)))
+ {
+ included_file = *include_dir+included_file;
+ break;
+ }
+ }
}
- // make sure the file exists
- // and that we can read from
- // it, otherwise just ignore
- // the line
+ // make sure the file exists and that we can read from it, otherwise
+ // just ignore the line
+
+ // If this is an ".inst" file, it will be generated by make later, so
+ // we better keep it on the list.
- // If this is an ".inst" file,
- // it will be generated by make
- // later, so we better keep it
- // on the list.
-
if (line[pos] != '"' || !is_inst_file)
- {
- if (!file_exists(included_file))
- continue;
- }
+ {
+ if (!file_exists(included_file))
+ continue;
+ }
- // ok, so we did find an
- // appropriate file. add it to
- // the correct list
+ // ok, so we did find an appropriate file. add it to the correct list
direct_includes[file].insert (included_file);
- // work on the include file
- // recursively. note that the
- // first line of this function
- // saves us from infinite
- // recursions in case of
- // include loops
+ // work on the include file recursively. note that the first line of
+ // this function saves us from infinite recursions in case of include
+ // loops
determine_direct_includes (included_file);
}
}
- // return the set of all included
- // files, directly or indirectly, for
- // the given file. for this purpose,
- // we consider the direct_includes
- // variable to be a representation of
- // a directed graph: given a file (a
- // node in the graph), the elements
- // of the include-set for this file
- // are outgoing edges from this
- // node. to get at all includes,
- // direct and indirect, we keep a
- // list starting with the direct
- // includes, the collect all direct
- // includes of the files in the list,
- // then their include files, etc. We
- // thus march in fronts through the
- // graph.
- //
- // one of the complications we have
- // to keep track of is that the graph
- // may be cyclic (i.e. header files
- // include each other mutually -- in
- // the real program, one of the
- // includes will be guarded by
- // preprocessor #ifdefs, but we don't
- // see them here), so we have to make
- // sure we strip elements from the
- // present front that we have already
- // visited before
- //
- // this function could presumably be
- // made more efficient in the
- // following way: when we have more
- // than one file for which we want to
- // compute dependencies, we presently
- // walk through the graph for each of
- // them. however, they will likely
- // have one or more includes in
- // common, so they will also have
- // parts of the dependency graph in
- // common. if we could precompute the
- // dependency graph for include files
- // in advance, we wouldn't have to
- // walk through _all_ the graph for
- // each file we consider, but could
- // just draw in blocks. the problem
- // with that is that to make this
- // efficient we cannot just compute
- // the whole set of dependencies for
- // _each_ file, but we have to do
- // this on the fly and to avoid again
- // problems with the cyclic nature we
- // have to keep track where we are
- // presently coming from. that's way
- // too complicated for now and I
- // leave it to times when dependency
- // generation becomes again a
- // noticable time hit
- //
- // one of the ideas to solve this
- // problem would be to start at
- // terminal nodes of the graph
- // (i.e. nodes that have no outgoing
- // edges) and fold these nodes into
- // nodes that have only outgoing
- // edges to terminal nodes. store the
- // dependencies of these
- // next-to-terminal nodes and remove
- // the terminal ones. then start over
- // again with the so generated
- // graph. if we consider the files
- // for which we want to compute
- // dependency information as top
- // level nodes (they will _only_ have
- // outgoing nodes), we could
- // presumable roll up the entire
- // graph from the bottom (terminal
- // nodes) and fold it one layer at a
- // time
- //
- // in any case, there is presently no
- // need for this since the actions of
- // this function are presently not
- // really time critical: parsing the
- // files in the function above is a
- // much bigger time-hit.
+// return the set of all included files, directly or indirectly, for the
+// given file. for this purpose, we consider the direct_includes variable
+// to be a representation of a directed graph: given a file (a node in the
+// graph), the elements of the include-set for this file are outgoing edges
+// from this node. to get at all includes, direct and indirect, we keep a
+// list starting with the direct includes, the collect all direct includes
+// of the files in the list, then their include files, etc. We thus march
+// in fronts through the graph.
+//
+// one of the complications we have to keep track of is that the graph may
+// be cyclic (i.e. header files include each other mutually -- in the real
+// program, one of the includes will be guarded by preprocessor #ifdefs,
+// but we don't see them here), so we have to make sure we strip elements
+// from the present front that we have already visited before
+//
+// this function could presumably be made more efficient in the following
+// way: when we have more than one file for which we want to compute
+// dependencies, we presently walk through the graph for each of them.
+// however, they will likely have one or more includes in common, so they
+// will also have parts of the dependency graph in common. if we could
+// precompute the dependency graph for include files in advance, we
+// wouldn't have to walk through _all_ the graph for each file we consider,
+// but could just draw in blocks. the problem with that is that to make
+// this efficient we cannot just compute the whole set of dependencies for
+// _each_ file, but we have to do this on the fly and to avoid again
+// problems with the cyclic nature we have to keep track where we are
+// presently coming from. that's way too complicated for now and I leave it
+// to times when dependency generation becomes again a noticable time hit
+//
+// one of the ideas to solve this problem would be to start at terminal
+// nodes of the graph (i.e. nodes that have no outgoing edges) and fold
+// these nodes into nodes that have only outgoing edges to terminal nodes.
+// store the dependencies of these next-to-terminal nodes and remove the
+// terminal ones. then start over again with the so generated graph. if we
+// consider the files for which we want to compute dependency information
+// as top level nodes (they will _only_ have outgoing nodes), we could
+// presumable roll up the entire graph from the bottom (terminal nodes) and
+// fold it one layer at a time
+//
+// in any case, there is presently no need for this since the actions of
+// this function are presently not really time critical: parsing the files
+// in the function above is a much bigger time-hit.
std::set<std::string>
get_all_includes (const std::string &name)
{
- // start with direct includes
+ // start with direct includes
std::set<std::string> all_includes = direct_includes[name];
std::set<std::string> next_level_includes = all_includes;
while (true)
{
- // traverse all next level
- // includes and get their
- // direct include files. the
- // set makes sure that
- // duplicates are removed
+ // traverse all next level includes and get their direct include
+ // files. the set makes sure that duplicates are removed
std::set<std::string> second_next;
for (std::set<std::string>::const_iterator
- next=next_level_includes.begin();
+ next=next_level_includes.begin();
next!=next_level_includes.end(); ++next)
second_next.insert (direct_includes[*next].begin(),
direct_includes[*next].end());
- // for each of them, if it
- // hasn't been treated then add
- // it to the files of the next
- // level and later add it to
- // the all_includes
+ // for each of them, if it hasn't been treated then add it to the
+ // files of the next level and later add it to the all_includes
next_level_includes.clear ();
for (std::set<std::string>::const_iterator f=second_next.begin();
f!=second_next.end(); ++f)
if (all_includes.find(*f) == all_includes.end())
next_level_includes.insert (*f);
- // if no new includes found no
- // more, then quit
+ // if no new includes found no more, then quit
if (next_level_includes.size() == 0)
return all_includes;
- // otherwise, copy over and
- // start over on the next level
- // of the tree
+ // otherwise, copy over and start over on the next level of the tree
all_includes.insert (next_level_includes.begin(),
next_level_includes.end());
}
{
std::vector<std::string> filenames;
- // parse all arguments (except the
- // name of the executable itself)
+ // parse all arguments (except the name of the executable itself)
for (unsigned int c=1; c<static_cast<unsigned int>(argc); ++c)
{
const std::string arg = argv[c];
- // if string starts with -I,
- // take this as an include path
+ // if string starts with -I, take this as an include path
if ((arg.length()>2) && (arg[0]=='-') && (arg[1]=='I'))
{
std::string dir (arg.begin()+2, arg.end());
- // append a slash if not
- // already there
+ // append a slash if not already there
if (dir[dir.length()-1] != '/')
dir += '/';
- // drop initial ./ if this
- // is there
+ // drop initial ./ if this is there
if ((dir[0]=='.') && (dir[1]=='/'))
dir = std::string(dir.begin()+2, dir.end());
include_directories.push_back (dir);
}
- // if string starts with -B,
- // then this is the base name
- // for object files
+ // if string starts with -B, then this is the base name for object
+ // files
else if ((arg.length()>2) && (arg[0]=='-') && (arg[1]=='B'))
{
basepath = std::string(arg.begin()+2, arg.end());
if (basepath[basepath.size()-1] != '/')
basepath += '/';
}
- // if string is -n,
- // then use new-style format
+ // if string is -n, then use new-style format
else if ((arg.length()==2) && (arg[0]=='-') && (arg[1]=='n'))
- format = new_style;
+ format = new_style;
- // otherwise assume that this
- // is one of the files for
- // input
+ // otherwise assume that this is one of the files for input
else
{
assert (arg.size()>=1);
}
}
- // next iterate through all files
- // and figure out which other files
- // they include
+ // next iterate through all files and figure out which other files they
+ // include
for (std::vector<std::string>::const_iterator file=filenames.begin();
file != filenames.end(); ++file)
determine_direct_includes (*file);
- // now we have all files that are
- // directly or indirectly included
- // into the files given on the
- // command lines. for each of them,
- // we have recorded which files
- // they include themselves. for
- // each file on the command line,
- // we can thus form a complete
- // include tree.
+ // now we have all files that are directly or indirectly included into
+ // the files given on the command lines. for each of them, we have
+ // recorded which files they include themselves. for each file on the
+ // command line, we can thus form a complete include tree.
for (std::vector<std::string>::const_iterator file=filenames.begin();
file != filenames.end(); ++file)
{
- // get base of filename by
- // chipping away .cc extension
- // as well as path
+ // get base of filename by chipping away .cc extension as well as
+ // path
std::string basename;
if (file->find (".cc") != std::string::npos)
basename = std::string (file->begin(),
basename = std::string (basename.begin()+basename.rfind("/")+1,
basename.end());
- // get all direct and indirect
- // includes for this file...
+ // get all direct and indirect includes for this file...
const std::set<std::string> includes = get_all_includes (*file);
- // ...write the rule for the .o
- // file...
+ // ...write the rule for the .o file...
if (format == old_style)
- std::cout << basepath << basename << ".o: \\"
- << std::endl
- << "\t\t" << *file;
+ std::cout << basepath << basename << ".o: \\"
+ << std::endl
+ << "\t\t" << *file;
else
- std::cout << basepath << "optimized/" << basename << ".o: \\"
- << std::endl
- << "\t\t" << *file;
+ std::cout << basepath << "optimized/" << basename << ".o: \\"
+ << std::endl
+ << "\t\t" << *file;
for (std::set<std::string>::const_iterator i=includes.begin();
i!=includes.end(); ++i)
std::cout << "\\\n\t\t" << *i;
std::cout << std::endl;
- // ...and a similar rule for
- // the .o file in debug mode
+ // ...and a similar rule for the .o file in debug mode
if (format == old_style)
- std::cout << basepath << basename << ".g.o: \\"
- << std::endl
- << "\t\t" << *file;
+ std::cout << basepath << basename << ".g.o: \\"
+ << std::endl
+ << "\t\t" << *file;
else
- std::cout << basepath << "debug/" << basename << ".o: \\"
- << std::endl
- << "\t\t" << *file;
+ std::cout << basepath << "debug/" << basename << ".o: \\"
+ << std::endl
+ << "\t\t" << *file;
for (std::set<std::string>::const_iterator i=includes.begin();
i!=includes.end(); ++i)
std::cout << "\\\n\t\t" << *i;
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2013 by the deal.II authors
+## Copyright (C) 2013, 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# "Nightly" - Reserved for nightly regression tests for
# build bots on various architectures
#
-# "Regression Tests" - Reserved for the regression tester
+# "Regression Tests" - Reserved for the "official" regression tester
#
# CONFIG_FILE
# - A configuration file (see ../deal.II/docs/development/Config.sample)
MESSAGE("-- CTEST_SITE: ${CTEST_SITE}")
IF( "${TRACK}" STREQUAL "Regression Tests"
- AND NOT CTEST_SITE MATCHES "c0541" )
+ AND NOT CTEST_SITE MATCHES "^(simserv04|tester)$" )
MESSAGE(FATAL_ERROR "
I'm sorry ${CTEST_SITE}, I'm afraid I can't do that.
The TRACK \"Regression Tests\" is not for you.
_var MATCHES "^(COMPAT_FILES|DOCUMENTATION|EXAMPLES|MESH_CONVERTER|PARAMETER_GUI)" OR
_var MATCHES "^(ARPACK|BOOST|FUNCTIONPARSER|HDF5|METIS|MPI|MUMPS)_" OR
_var MATCHES "^(NETCDF|P4EST|PETSC|SLEPC|THREADS|TBB|TRILINOS)_" OR
- _var MATCHES "^(UMFPACK|ZLIB|LAPACK)_" OR
+ _var MATCHES "^(UMFPACK|ZLIB|LAPACK|MUPARSER)_" OR
_var MATCHES "^(CMAKE|DEAL_II)_(C|CXX|Fortran|BUILD)_(COMPILER|FLAGS)" OR
_var MATCHES "^CMAKE_BUILD_TYPE$" OR
_var MATCHES "MAKEOPTS" OR
# Umm, no valid subversion info was found, try again with git-svn:
FIND_PACKAGE(Git QUIET)
IF(GIT_FOUND)
- EXECUTE_PROCESS(
- COMMAND ${GIT_EXECUTABLE} svn info
- WORKING_DIRECTORY ${CTEST_SOURCE_DIRECTORY}
- OUTPUT_VARIABLE _svn_WC_INFO
- RESULT_VARIABLE _result
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
+ GET_FILENAME_COMPONENT(_path "${CTEST_SOURCE_DIRECTORY}" PATH)
+ IF(EXISTS ${_path}/.git/svn)
+ EXECUTE_PROCESS(
+ COMMAND ${GIT_EXECUTABLE} svn info
+ WORKING_DIRECTORY ${CTEST_SOURCE_DIRECTORY}
+ OUTPUT_VARIABLE _svn_WC_INFO
+ RESULT_VARIABLE _result
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
- IF(${_result} EQUAL 0)
- STRING(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
- "\\2" _svn_WC_URL "${_svn_WC_INFO}")
- STRING(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
- "\\2" _svn_WC_ROOT "${_svn_WC_INFO}")
- STRING(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
- "\\2" _svn_WC_REVISION "${_svn_WC_INFO}")
- STRING(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
- "\\2" _svn_WC_LAST_CHANGED_DATE "${_svn_WC_INFO}")
- ELSE()
- SET(_svn_WC_INFO)
+ IF(${_result} EQUAL 0)
+ STRING(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*"
+ "\\2" _svn_WC_URL "${_svn_WC_INFO}")
+ STRING(REGEX REPLACE "^(.*\n)?Repository Root: ([^\n]+).*"
+ "\\2" _svn_WC_ROOT "${_svn_WC_INFO}")
+ STRING(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
+ "\\2" _svn_WC_REVISION "${_svn_WC_INFO}")
+ STRING(REGEX REPLACE "^(.*\n)?Last Changed Date: ([^\n]+).*"
+ "\\2" _svn_WC_LAST_CHANGED_DATE "${_svn_WC_INFO}")
+ ELSE()
+ SET(_svn_WC_INFO)
+ ENDIF()
ENDIF()
ENDIF()
ENDIF()
IF("${_res}" STREQUAL "0")
# Only run tests if the build was successful:
- MESSAGE("-- Running make setup_tests")
+ MESSAGE("-- Running setup_tests")
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND}
--build ${CTEST_BINARY_DIRECTORY} --target setup_tests
-- ${MAKEOPTS}
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unused-function")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unused-private-field")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unused-variable")
+ ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unsupported-friend")
ENDIF()
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2012 - 2013 by the deal.II authors
+## Copyright (C) 2012 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# friend struct Implementation;
# };)
# -w177 declared but not referenced
+# -w191 type qualifier is meaningless on cast type
+# Warnings from this warn about code like this:
+# static_cast<T const * const>(p)
+# There are many places in boost that do this kind of stuff
+# -w193 zero used for undefined preprocessing identifier "..."
+# This happens when using undefined preprocessor names in
+# conditions such as
+# #if (abc && def)
+# instead of
+# #if (defined(abc) && defined(def))
+# The standard says that in such cases, the undefined symbol
+# is assumed to be zero. The warning is in principle
+# useful, but the pattern appears exceedingly often in the TBB
# -w279 controlling expression is constant
# -w327 NULL reference is not allowed
# (the compiler is correct here in that statements like
# (happens in boost)
# -w1478 deprecation warning
# -w1572 floating-point equality and inequality comparisons are unreliable
+# -w2259 non-pointer conversion from "double" to "float" may
+# lose significant bits
+# -w21 type qualifiers are meaningless in this declaration
# -w2536 type qualifiers are meaningless here
#
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd68")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd135")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd175")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd177")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd191")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd193")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd279")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd327")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd383")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1418")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1478")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd1572")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2259")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd21")
ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2536")
+# Also disable the following warnings that we frequently
+# trigger writing dimension independent code:
+# -w111 statement is unreachable
+# Happens in code that is guarded by a check on 'dim'
+# -w128 loop is not reachable from preceding
+# Same as above
+# -w185 dynamic initialization in unreachable code
+# When initializing a local variable in code
+# that is executed only for one specific dimension
+# -w280 selector expression is constant
+# When writing 'switch(dim)'
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd111")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd128")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd185")
+ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd280")
+
+
+
IF(DEAL_II_STATIC_EXECUTABLE)
#
# To produce a static executable, we have to statically link intel's
#
# Provide an "info" target to print a help message:
#
-
IF(CMAKE_GENERATOR MATCHES "Ninja")
SET(_make_command "ninja")
ELSE()
SET(_make_command "make")
ENDIF()
+
FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_info.cmake
"MESSAGE(
\"###
")
ELSE()
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_info.cmake
-"# help - print this help message in the toplevel directory,
+"# info - print this help message in the toplevel directory,
# otherwise print a list of targets (in subdirectories)
#
")
#
# test - run a minimal set of tests
#
-# setup_tests - set up the testsuite subprojects
-# regen_tests - rerun configure stage in every testsuite subprojects
+# setup_tests - set up testsuite subprojects
+# regen_tests - rerun configure stage in every testsuite subproject
# clean_tests - run the 'clean' target in every testsuite subproject
# prune_tests - remove all testsuite subprojects
#
ADD_CUSTOM_TARGET(info
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_info.cmake
)
-IF(NOT CMAKE_GENERATOR MATCHES "Ninja")
+
+#
+# In case of the Unix Makefiles generator it is safe to override the
+# default 'help' target, which is - frankly - quite unhelpful.
+#
+IF(CMAKE_GENERATOR MATCHES "Unix Makefiles")
ADD_CUSTOM_TARGET(help
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/print_info.cmake
)
# DEAL_II_PROJECT_CONFIG_RELDIR *)
#
# DEAL_II_BUILD_TYPES
+# DEAL_II_LIST_SUFFIXES
+# DEAL_II_STRING_SUFFIXES
#
# *) Can be overwritten by the command line via -D<...>
#
LIST(APPEND DEAL_II_BUILD_TYPES "RELEASE")
ENDIF()
+SET(DEAL_II_LIST_SUFFIXES
+ DEFINITIONS DEFINITIONS_RELEASE DEFINITIONS_DEBUG
+ USER_DEFINITIONS USER_DEFINITIONS_RELEASE USER_DEFINITIONS_DEBUG
+ INCLUDE_DIRS USER_INCLUDE_DIRS BUNDLED_INCLUDE_DIRS
+ LIBRARIES LIBRARIES_RELEASE LIBRARIES_DEBUG
+ )
+
+SET(DEAL_II_STRING_SUFFIXES
+ CXX_FLAGS CXX_FLAGS_RELEASE CXX_FLAGS_DEBUG
+ LINKER_FLAGS LINKER_FLAGS_RELEASE LINKER_FLAGS_DEBUG
+ )
+
########################################################################
# #
ENDIF()
ENDFOREACH()
-#
-# Deduplicate entries in *_INCLUDE_DIRS and *_LIBRARIES
-#
-FOREACH(_feature DEAL_II ${DEAL_II_FEATURES})
- FOREACH(_suffix INCLUDE_DIRS USER_INCLUDE_DIRS BUNDLED_INCLUDE_DIRS)
- REMOVE_DUPLICATES(${_feature}_${_suffix})
- ENDFOREACH()
- FOREACH(_suffix LIBRARIES LIBRARIES_RELEASE LIBRARIES_DEBUG)
- REMOVE_DUPLICATES(${_feature}_${_suffix} REVERSE)
- ENDFOREACH()
-ENDFOREACH()
-
#
# Save base configuration into variables BASE_* for later use in
# setup_write_config.cmake:
#
-FOREACH(_suffix
- CXX_FLAGS CXX_FLAGS_RELEASE CXX_FLAGS_DEBUG
- DEFINITIONS DEFINITIONS_RELEASE DEFINITIONS_DEBUG
- USER_DEFINITIONS USER_DEFINITIONS_RELEASE USER_DEFINITIONS_DEBUG
- LINKER_FLAGS LINKER_FLAGS_RELEASE LINKER_FLAGS_DEBUG
- INCLUDE_DIRS USER_INCLUDE_DIRS BUNDLED_INCLUDE_DIRS
- LIBRARIES LIBRARIES_RELEASE LIBRARIES_DEBUG
- )
+FOREACH(_suffix ${DEAL_II_STRING_SUFFIXES} ${DEAL_II_LIST_SUFFIXES})
SET(BASE_${_suffix} ${DEAL_II_${_suffix}})
ENDFOREACH()
# Register features:
#
FOREACH(_feature ${DEAL_II_FEATURES})
- FILTER_SYSTEM_LIBRARIES(${_feature})
+ FILTER_SYSTEM_LIBRARIES(${_feature}) # TODO, remove here
REGISTER_FEATURE(${_feature})
ENDFOREACH()
#
# Deduplicate entries one more time :-]
#
-FOREACH(_suffix INCLUDE_DIRS USER_INCLUDE_DIRS BUNDLED_INCLUDE_DIRS)
- REMOVE_DUPLICATES(DEAL_II_${_suffix})
-ENDFOREACH()
-FOREACH(_suffix LIBRARIES LIBRARIES_RELEASE LIBRARIES_DEBUG)
- REMOVE_DUPLICATES(DEAL_II_${_suffix} REVERSE)
+FOREACH(_suffix ${DEAL_II_LIST_SUFFIXES})
+ IF(_suffix MATCHES "INCLUDE_DIRS$")
+ REMOVE_DUPLICATES(DEAL_II_${_suffix})
+ ELSE()
+ REMOVE_DUPLICATES(DEAL_II_${_suffix} REVERSE)
+ ENDIF()
ENDFOREACH()
#
IF(NOT NUMDIFF_EXECUTABLE MATCHES "-NOTFOUND")
SET(TEST_DIFF ${NUMDIFF_EXECUTABLE} -a 1e-6 -r 1e-8 -s ' \\t\\n:')
+ IF(DIFF_EXECUTABLE MATCHES "-NOTFOUND")
+ SET(DIFF_EXECUTABLE ${NUMDIFF_EXECUTABLE})
+ ENDIF()
ELSEIF(NOT DIFF_EXECUTABLE MATCHES "-NOTFOUND")
SET(TEST_DIFF ${DIFF_EXECUTABLE})
ELSE()
_both("DEAL_II_ALLOW_AUTODETECTION = ${DEAL_II_ALLOW_AUTODETECTION}):\n")
-#
-# Cache for quicker access to avoid the O(n^2) complexity of a loop over
-# _all_ defined variables.
-#
-
GET_CMAKE_PROPERTY(_variables VARIABLES)
FOREACH(_var ${_variables})
IF(_var MATCHES "DEAL_II_WITH")
# Print the feature configuration:
#
FOREACH(_var2
- C_COMPILER CXX_COMPILER Fortran_COMPILER
- CXX_FLAGS CXX_FLAGS_RELEASE CXX_FLAGS_DEBUG
- DEFINITIONS DEFINITIONS_RELEASE DEFINITIONS_DEBUG
- USER_DEFINITIONS USER_DEFINITIONS_RELEASE USER_DEFINITIONS_DEBUG
- LINKER_FLAGS LINKER_FLAGS_RELEASE LINKER_FLAGS_DEBUG
- INCLUDE_DIRS USER_INCLUDE_DIRS BUNDLED_INCLUDE_DIRS
- LIBRARIES LIBRARIES_RELEASE LIBRARIES_DEBUG
+ C_COMPILER CXX_COMPILER Fortran_COMPILER
+ ${DEAL_II_STRING_SUFFIXES} ${DEAL_II_LIST_SUFFIXES}
)
IF(DEFINED ${_feature}_${_var2})
_detailed("# ${_feature}_${_var2} = ${${_feature}_${_var2}}\n")
#\n# Run $ "
)
IF(CMAKE_GENERATOR MATCHES "Ninja")
- _summary("ninja info")
+ _summary("ninja ")
ELSE()
-_summary("make help")
+_summary("make ")
ENDIF()
-_summary(" to print a help message with a list of top level targets\n")
+_summary("info to print a help message with a list of top level targets\n")
_both("#\n###")
-
-
-########################################################################
-# #
-# Dump the cache into config.cmake: #
-# #
-########################################################################
-
-SET(_config_cmake "${CMAKE_BINARY_DIR}/config.cmake")
-FILE(WRITE ${_config_cmake}
-"#
-# This is a raw CMake cache dump of this build directory suitable as an
-# initial cache file: Use this file to preseed a CMake cache in an empty
-# build directory by (note that it is still necessary to declare a source
-# directory):
-# $ cmake -C [...]/config.cmake ../deal.II
-#
-# If you want to have a clean configuration file have a look at
-# doc/users/config.sample
-#\n"
- )
-
-FUNCTION(_config _var)
- # It is absolutely beyond my comprehension why on earth there is
- # hardcoded logic built into CMake to throw an error if one uses
- # uppercase variants of FindPACKAGE call variables...
- IF(NOT _var MATCHES "BOOST_DIR")
- UNSET(${_var})
- ENDIF()
- #
- # We have to get down to the raw entry in the cache, therefore clear the
- # current value (and do it in a function to get private scope):
- #
- FILE(APPEND ${_config_cmake}
- "SET(${_var} \"${${_var}}\" CACHE STRING \"\")\n"
- )
-ENDFUNCTION()
-
-GET_CMAKE_PROPERTY(_variables CACHE_VARIABLES)
-FOREACH(_var
- CMAKE_C_COMPILER
- CMAKE_CXX_COMPILER
- CMAKE_Fortran_COMPILER
- ${_variables}
- )
- _config(${_var})
-ENDFOREACH()
--- /dev/null
+// vector update of the form y += alpha*x with a scalar, x,y vectors
+void daxpy_ (const int* n, const double* alpha, const double* x,
+ const int* incx, double* y, const int* incy);
+
+// General Matrix
+// Matrix vector product
+void dgemv_ (const char* trans, const int* m, const int* n,
+ const double* alpha, const double* A, const int* lda,
+ const double* x, const int* incx,
+ const double* b, double* y, const int* incy);
+
+// Matrix matrix product
+void dgemm_ (const char* transa, const char* transb,
+ const int* m, const int* n, const int* k,
+ const double* alpha, const double* A, const int* lda,
+ const double* B, const int* ldb,
+ const double* beta, double* C, const int* ldc);
+
+// Compute LU factorization
+void dgetrf_ (const int* m, const int* n, double* A,
+ const int* lda, int* ipiv, int* info);
+// Apply forward/backward substitution to LU factorization
+void dgetrs_ (const char* trans, const int* n, const int* nrhs,
+ const double* A, const int* lda, const int* ipiv,
+ double* b, const int* ldb, int* info);
+// Invert matrix from LU factorization
+void dgetri_ (const int* n, double* A, const int* lda,
+ int* ipiv, double* inv_work, const int* lwork, int* info);
+
+// Compute QR factorization (Householder)
+void dgeqrf_ (const int* m, const int* n, double* A,
+ const int* lda, double* tau, double* work,
+ const int* lwork, int* info);
+// Compute vector Q^T B, where Q is the result from dgeqrf_
+void dormqr_ (const char* side, const char* trans, const int* m,
+ const int* n, const int* k, const double* A, const int* lda,
+ const double* tau, double* B, const int* ldb,
+ double* work, const int* lwork, int* info);
+// Compute matrix Q from the result of dgeqrf_
+void dorgqr_ (const int* m, const int* n, const int* k, const double* A,
+ const int* lda, const double* tau, double* work, const int* lwork,
+ int* info);
+// Compute Rx = b
+void dtrtrs_ (const char* uplo, const char* trans,
+ const char* diag, const int* n, const int* n_rhs,
+ const double* A, const int* lda, double* B, const int* ldb,
+ int* info);
+
+// Compute eigenvalues and vectors
+void dgeev_ (const char* jobvl, const char* jobvr,
+ const int* n, double* A, const int* lda,
+ double* lambda_re, double* lambda_im,
+ double* vl, const int* ldvl,
+ double* vr, const int* ldva,
+ double* work, const int* lwork,
+ int* info);
+// Compute eigenvalues and vectors (expert)
+void dgeevx_ (const char* balanc, const char* jobvl, const char* jobvr,
+ const char* sense,
+ const int* n, double* A, const int* lda,
+ double* lambda_re, double* lambda_im,
+ double* vl, const int* ldvl,
+ double* vr, const int* ldvr,
+ int* ilo, int* ihi,
+ double* scale, double* abnrm,
+ double* rconde, double* rcondv,
+ double* work, const int* lwork,
+ int* iwork, int* info);
+// Eigenvalues for a symmetric matrix
+void dsyev_ (const char *jobz, const char *uplo, const int *n,
+ double *A, const int *lda, double *w,
+ double *work, const int *lwork, int *info);
+// Same functionality as dsyev_ but with more options: E.g.
+// Compute only eigenvalues in a specific interval,
+// Compute only eigenvalues with a specific index,
+// Set tolerance for eigenvalue computation
+void dsyevx_ (const char* jobz, const char* range,
+ const char* uplo, const int* n, double* A, const int* lda,
+ const double* vl, const double* vu,
+ const int* il, const int* iu, const double* abstol,
+ int* m, double* w, double* z,
+ const int* ldz, double* work, const int* lwork, int* iwork,
+ int* ifail, int* info);
+// Generalized eigenvalues and eigenvectors of
+// 1: A*x = lambda*B*x; 2: A*B*x = lambda*x; 3: B*A*x = lambda*x
+// A and B are symmetric and B is definite
+void dsygv_ (const int* itype, const char* jobz, const char* uplo,
+ const int* n, double* A, const int* lda, double* B,
+ const int* ldb, double* w, double* work,
+ const int* lwork, int* info);
+// Same functionality as dsygv_ but with more options: E.g.
+// Compute only eigenvalues in a specific interval,
+// Compute only eigenvalues with a specific index,
+// Set tolerance for eigenvalue computation
+void dsygvx_ (const int* itype, const char* jobz, const char* range,
+ const char* uplo, const int* n, double* A, const int* lda,
+ double* B, const int* ldb, const double* vl, const double* vu,
+ const int* il, const int* iu, const double* abstol,
+ int* m, double* w, double* z,
+ const int* ldz, double* work, const int* lwork, int* iwork,
+ int* ifail, int* info);
+
+// Compute singular value decomposition using divide and conquer
+void dgesdd_ (const char* jobz,
+ const int* m, const int* n, double* A, const int* lda,
+ double* s,
+ double* u, const int* ldu,
+ double* vt, const int* ldvt,
+ double* work, const int* lwork,
+ int* iwork,
+ int* info);
+
+// Compute singular value decomposition
+void dgesvd_ (int* jobu, int* jobvt,
+ const int* n, const int* m, double* A, const int* lda,
+ double* s,
+ double* u, const int* ldu,
+ double* vt, const int* ldvt,
+ double* work, const int* lwork,
+ int* info);
+
+// Solve a least squares problem using SVD
+void dgelsd_ (const int* m, const int* n, const int* nrhs,
+ const double* A, const int* lda,
+ double* B, const int* ldb,
+ double* s, const double* rcond,
+ int* rank,
+ double* work, const int* lwork, int* iwork,
+ int* info);
+
+// Symmetric tridiagonal matrix
+void dstev_ (const char* jobz, const int* n,
+ double* d, double* e, double* z,
+ const int* ldz, double* work,
+ int* info);
+
--- /dev/null
+#!/usr/bin/python
+
+# run this script on all headers of deal.II to fix comment line wrapping for
+# doxygen comments.
+# Example:
+# cd include
+# find . -name "*h" -print | while read file;do ../contrib/utilities/wrapcomments.py $file >temp;mv temp $file;done
+
+from __future__ import print_function
+import textwrap
+import sys
+import string
+wrapper = textwrap.TextWrapper()
+
+# take an array of lines and wrap them to 78 columns and let each lines start
+# with @p startwith
+def wrap_block(lines, startwith):
+ longline = " ".join(lines)
+ wrapper.initial_indent = startwith
+ wrapper.subsequent_indent = startwith
+ wrapper.width = 78
+ return wrapper.wrap(longline)
+
+# strips whitespace and leading "*" from each lines
+def remove_junk(lines):
+ out = []
+ for line in lines:
+ line = line.strip()
+ if line.startswith("*"):
+ line = line[1:].strip()
+ out.append(line)
+ return out
+
+# returns True if at least one entry in @p list is contained in @p str
+def one_in(list, str):
+ for li in list:
+ if li in str:
+ return True
+ return False
+
+# returns True if @p str starts with one of the entries in @p list
+def starts_with_one(list, str):
+ for li in list:
+ if str.startswith(li):
+ return True
+ return False
+
+# take a doxygen comment block "/** bla ... */" given as a list of lines and
+# format it in a pretty way rewrapping lines while taking care to keep certain
+# structure.
+def format_block(lines, infostr=""):
+ if len(lines)==1 and "/*" in lines[0] and "*/" in lines[0]:
+ return lines
+
+ if (not "/**" in lines[0]
+ or not "*/" in lines[-1]):
+ print("%s not a code block"%infostr, file=sys.stderr)
+ return lines
+
+ for line in lines[1:-1]:
+ assert(not "/*" in line)
+ assert(not "*/" in line)
+
+ lines[-1]=lines[-1].replace("**/","*/")
+
+ if not lines[0].strip().startswith("/**"):
+ print ("%s error, ignoring code block with junk in same line before"%infostr, file=sys.stderr)
+ return lines
+ if not lines[-1].strip().endswith("*/"):
+ print ("%s error, ignoring code block not ending at end of line"%infostr, file=sys.stderr)
+ return lines
+
+ if lines[0].strip()!="/**":
+ #print ("%s warning code block not starting in separate line"%infostr, file=sys.stderr)
+ idx = string.find(lines[0],"/**")
+ temp = [lines[0][0:idx+3], lines[0][idx+3:]]
+ temp.extend(lines[1:])
+ lines = temp
+ if lines[-1].strip()!="*/":
+ #print ("%s warning code block not ending in separate line"%infostr, file=sys.stderr)
+ idx = string.find(lines[-1],"*/")
+ temp = lines[0:-1]
+ temp.append(lines[-1][0:idx])
+ temp.append(lines[-1][idx:])
+ lines = temp
+
+ idx = string.find(lines[0],"/**")
+ start = lines[0][:idx]+" * "
+
+ out = [lines[0]]
+ idx = 1
+ endidx = len(lines)-1
+ curlines = []
+
+ ops_startline = ["<li>", "@param", "@returns", "@warning", "@ingroup", "@author", "@date", "@related", "@deprecated"]
+
+ ops_separate_line = ["<ol>", "</ol>", "<ul>", "</ul>", "@{", "@}", "<br>"]
+
+ while idx<endidx:
+ if one_in(ops_separate_line, lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ thisline = remove_junk([lines[idx]])[0]
+ for it in ops_separate_line:
+ if it in thisline and thisline!=it:
+ print ("%s warning %s not in separate line"%(infostr, it), file=sys.stderr)
+ out.append(start + thisline)
+ elif one_in(ops_startline, lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ thisline = remove_junk([lines[idx]])[0]
+ if not starts_with_one(ops_startline, thisline):
+ for it in ops_startline:
+ if it in thisline:
+ print ("%s warning %s not at start of line"%(infostr, it), file=sys.stderr)
+ curlines.append(lines[idx])
+ elif one_in(["@code", "@verbatim", "@f["], lines[idx]):
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ while True:
+ thisline = lines[idx].rstrip()
+ if thisline.strip()=="*":
+ thisline = start
+ elif thisline.strip()=="@code" or thisline.strip()=="@endcode":
+ thisline = start + thisline.strip()
+ elif thisline.strip()[0:2]!="* ":
+ if thisline[0:len(start)].strip()=="":
+ # just a missing *, so keep old indentation
+ thisline = start + thisline[len(start):]
+ else:
+ # no way to recover indentation:
+ print ("%s Error: wrong formatting inside @code block"%infostr, file=sys.stderr)
+ thisline = start + thisline.strip()
+ else:
+ thisline = start + thisline.strip()[2:]
+ out.append(thisline.rstrip())
+ if one_in(["@endcode", "@endverbatim", "@f]"], lines[idx]):
+ break
+ idx += 1
+ elif lines[idx].strip()=="*":
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+ curlines=[]
+ out.append(start[:-1]) #skip whitespace at the end
+ else:
+ curlines.append(lines[idx])
+ idx += 1
+
+ if curlines!=[]:
+ out.extend(wrap_block(remove_junk(curlines), start))
+
+ out.append(start[0:-2] + lines[-1].strip())
+
+ return out
+
+
+# test the routines:
+lineI = [" * blub", \
+ " * two three ", \
+ " * four"]
+lineO = ["blub", \
+ "two three", \
+ "four"]
+assert(remove_junk(lineI)==lineO)
+
+lineI = ["blub", \
+ "two three", \
+ "four"]
+lineO = [" * blub two three four"]
+assert(wrap_block(lineI," * ")==lineO)
+
+lineI = [" * 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0 1 2",\
+ " * A 4 5 6 7 9 0 1 2 3 4 5 6 7 9 0"]
+assert(wrap_block(remove_junk(lineI)," * ")==lineI)
+
+lineI = [" * Structure which is passed to Triangulation::create_triangulation. It",\
+ " * contains all data needed to construct a cell, namely the indices of the",\
+ " * vertices and the material indicator."]
+assert(wrap_block(remove_junk(lineI)," * ")==lineI)
+
+lineI = [" /**", \
+ " * blub", \
+ " * two three", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub two three four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " * two three", \
+ " * ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub two three", \
+ " *", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineI)
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code ", \
+ " * two three", \
+ " * two three ", \
+ " * ", \
+ " * two three", \
+ " * @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * two three", \
+ " *", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+lineI = [" /**", \
+ " * blub", \
+ " @code ", \
+ " two three", \
+ " @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+lineI = [" /**", \
+ " * blub", \
+ " * @code ", \
+ " * two three", \
+ " * two three ", \
+ " * ", \
+ " two three", \
+ " ", \
+ " * @endcode ", \
+ " * four", \
+ " */"]
+lineO = [" /**", \
+ " * blub", \
+ " * @code", \
+ " * two three", \
+ " * two three", \
+ " *", \
+ " * two three", \
+ " *", \
+ " * @endcode", \
+ " * four", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+
+lineI = [" /**", \
+ " * blub", \
+ " * <ul>", \
+ " * <li> bla", \
+ " * <li> blub", \
+ " * </ul>", \
+ " */"]
+assert(format_block(lineI)==lineI)
+
+lineI = [" /** @addtogroup Exceptions", \
+ " * @{ */"]
+lineO = [" /**", \
+ " * @addtogroup Exceptions", \
+ " * @{", \
+ " */"]
+assert(format_block(lineI)==lineO)
+
+
+# now open the file and do the work
+
+
+args=sys.argv
+args.pop(0)
+
+if len(args)!=1:
+ print("Usage: wrapcomments.py infile >outfile")
+ exit(0)
+
+f = open(args[0])
+lines = f.readlines()
+f.close()
+
+out = []
+cur = []
+inblock = False
+lineidx = 0
+for line in lines:
+ lineidx += 1
+ line = line.replace("\n","")
+ if not inblock and "/**" in line:
+ inblock = True
+ cur = []
+ if inblock:
+ cur.append(line)
+ else:
+ out.append(line)
+ if inblock and "*/" in line:
+ out.extend(format_block(cur, args[0]+":%d"%lineidx))
+ cur = []
+ inblock = False
+
+assert(cur==[])
+
+for line in out:
+ print (line)
+
+
+
+
+
<head>
<link href="screen.css" rel="StyleSheet">
<title>deal.II Authors</title>
- <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="keywords" content="deal.II">
<meta name="svn_id" content="$Id$">
</head>
- <body>
- <h1>deal.II Authors</h1>
-
- <p>
- <acronym>deal.II</acronym> is a global project. It is
- administered by a group of <i>principal
- developers</i>. Technical decisions are made by the principal
- developers and a group of <i>developers</i> consisting of
- long-term contributors with a global overview of the library. A
- large number of <i>contributors</i> have provided substantial
- patches over the years.
- </p>
- <p>
- These three groups are listed below.
- </p>
-
-
- <h2>Principal developers</h2>
- <ul>
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">Wolfgang Bangerth</a>,
- Texas A&M University, TX, USA
- </li>
-
- <li>
- <a href="http://www.math.clemson.edu/~heister"
- target="_top">Timo Heister</a>,
- Clemson University, SC, USA
- </li>
-
- <li>
- <a href="http://www.iwr.uni-heidelberg.de/groups/MathSim/"
- target="_top">Guido Kanschat</a>,
- Universität Heidelberg, Germany
- </li>
- </ul>
-
-
- <h2>Developers</h2>
- <ul>
- <li>
- <a href="http://people.sissa.it/~heltai/"
- target="_top">Luca Heltai</a>,
- SISSA, Trieste, Italy
- </li>
-
- <li>
- <a href="http://www.lnm.mw.tum.de/en/staff/martin-kronbichler/"
- target="_top">Martin Kronbichler</a>,
- Technische Universität München, Germany
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~maier/"
- target="_top">Matthias Maier</a>,
- Universität Heidelberg, Germany
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~turcksin"
- target="_top">Bruno Turcksin</a>,
- Texas A&M University, TX, USA
- </li>
-
- <li>
- <a href="http://bluebox.ippt.pan.pl/~tyoung/"
- target="_top">Toby Young</a>,
- Polish Academy of Sciences, Poland
- </li>
-
- </ul>
-
-
-
-
- <h2>Contributors</h2>
-
- <p>Many people have contributed to deal.II over the years, some of them very
- substantial parts of the library. Their work
- is greatly appreciated: no open source project can survice without a
- community. The following people contributed major parts
- of the library (in alphabetical order), with many more that have
- sent in fixes and small enhancements:
- </p>
-
- <ul>
- <li><em>Moritz Allmaras:</em>
- Step-29 tutorial program.
-
- <li><em>Fahad Alrashed:</em>
- work in PETScWrappers, various other fixes.
-
- <li><em>Michael Anderson:</em>
- Linear complexity grid reordering algorithm in 2d and 3d.
-
- <li><em>Andrea Bonito:</em>
- Step-38.
-
- <li><em>Markus Bürg:</em>
- Conical meshes and geometries; step-45 tutorial program;
- VectorTools::project_boundary_values_curl_conforming; MUMPS
- interface, FE_Nedelec for arbitrary polynomial degrees.
-
- <li><em>Daniel Arndt:</em>
- FE_Q_DG0 element, ConstraintMatrix fixes, linear algebra, periodicity, bug fixes.
-
- <li><em>Juan Carlos Araujo Cabarcas:</em>
- Work on ARPACK.
-
- <li><em>John Burnell:</em>
- Configuration on Microsoft Windows systems.
-
- <li><em>Brian Carnes:</em>
- Hierarchical finite element classes;
- random fixes and enhancements.
-
- <li><em>Jordan Cazamias:</em>
- Work on tools for testing. Linear algebra.
-
- <li><em>Ivan Christov:</em>
- Step-25 tutorial program.
-
- <li><em>Chih-Che Chueh:</em>
- Step-43 tutorial program. Bug fixes.
-
- <li><em>Denis Davydov:</em>
- FEValuesExtractors::Tensor and associated functionality, bug fixes, various other changes.
-
- <li><em>Kevin Dugan:</em>
- Fixes in VectorTools::interpolate.
-
- <li><em>Marco Engelhard:</em>
- Better support for output for Paraview.
-
- <li><em>Jörg Frohne:</em>
- step-41. Fixes in many places.
-
- <li><em>Thomas Geenen:</em>
- Support for different geometries.
-
- <li><em>Martin Genet:</em>
- Make SparseDirectUMFPACK work with block matrices.
-
- <li><em>Christian Goll:</em>
- Abstraction of material and boundary indicators. Enhancements in
- various places.
-
- <li><em>Alexander Grayver:</em>
- Fixes in PETScWrappers.
-
- <li><em>Felix Gruber:</em>
- Documentation.
-
- <li><em>Ralf Hartmann:</em>
- Ralf was one of the original developers and maintainers of the library until
- 2011. He has written significant chunks of code throughout the library.
-
- <li><em>Eric Heien:</em>
- HDF5 output.
-
- <li><em>Bärbel Janssen:</em>
- Lots of work on multigrid for adaptive meshes; multigrid in the
- MeshWorker framework; step-16. Various fixes.
-
- <li><em>Armin Ghajar Jazi:</em>
- Small fixes.
-
- <li><em>Xing Jin:</em>
- step-24 tutorial program.
-
- <li><em>Oliver Kayser-Herold:</em>
- Lots of work on hp finite elements;
- integration of PETSc's LU decomposition;
- hanging node constraints for higher order elements in 3d.
-
- <li><em>Seungil Kim:</em>
- Help on the step-16 tutorial program.
-
- <li><em>Benjamin Shelton Kirk:</em>
- Tecplot output.
-
- <li><em>Katharina Kormann:</em>
- Support for arbitrary nodes in FE_Q. Matrix-free
- framework. step-37 and step-48 tutorial programs.
-
- <li><em>Oleh Krehel:</em>
- Documentation fixes, small fixes.
-
- <li><em>Tobias Leicht:</em>
- Lots of work on internal data structures: anisotropic refinement
- (including step-30), faces
- without level,
- support for previously unorientable meshes;
- extension of DataOut to higher order mapping functions; DataPostprocessor;
- GridIn::read_tecplot;
- made SolutionTransfer independent of Triangulation::user_pointers;
- random bug fixes and enhancements.
-
- <li><em>Yan Li:</em>
- step-21 tutorial program.
-
- <li><em>Vijay Mahadevan:</em>
- Enhancements in the interface to PETSc. Support for reading GMSH
- 2.5 format.
-
- <li><em>Cataldo Manigrasso:</em>
- Work on the codimension-one meshes, DoFHandler, and finite
- elements.
-
- <li><em>Andrew McBride:</em>
- FEValues extractors for symmetric tensors. step-44.
-
- <li><em>Craig Michoski:</em>
- Periodic boundaries
-
- <li><em>Scott Miller:</em>
- Enhancements to FE_Nothing, step-51, many smaller fixes.
-
- <li><em>Helmut Müller:</em>
- Multiprocessor detection on Mac OS X.
-
- <li><em>Jose Javier Munoz Criollo:</em>
- Improvements in PETScWrappers.
-
- <li><em>Stefan Nauber:</em>
- Postscript output.
-
- <li><em>David Neckels:</em>
- step-33 tutorial program.
-
- <li><em>M. Sebastian Pauletti:</em>
- Making meshes embedded in higher space dimensions more usable; many
- bug fixes and enhancements for codimension-one computations and
- throughout the library.
-
- <li><em>Jean-Paul Pelteret:</em>
- step-44, linear algebra, bug fixes.
-
- <li><em>Jonathan Pitt:</em>
- Enhancements to FE_Nothing. Changes in a variety of places.
-
- <li><em>Adam Powell IV:</em>
- Configuration issues, Debian packages.
-
- <li><em>Florian Prill:</em>
- Gauss Lobatto quadrature, random bug fixes.
-
- <li><em>Andreas Putz:</em>
- GridIn::read_vtk().
-
- <li><em>Daniel Castanon Quiroz:</em>
- Torus domain and boundary.
-
- <li><em>Michael Rapson:</em>
- PointValueHistory class.
-
- <li><em>Thomas Richter:</em>
- Povray output;
- multi-threading work;
- refinement functions;
- MinRes linear solver.
-
- <li><em>Mayank Sabharwal:</em>
- GridIn::read_vtk().
-
- <li><em>Abner Salgado-Gonzalez:</em>
- step-35 tutorial program. Other fixes.
-
- <li><em>Anna Schneebeli:</em>
- Help and advice for Nedelec elements, writing the excellent
- report on Nedelec elements.
-
- <li><em>Jan Schrage:</em>
- Initial parts of the tutorial.
-
- <li><em>Ralf B. Schulz:</em>
- Support for DLLs on Windows systems.
-
- <li><em>Jason Sheldon:</em>
- More generic FESystems. Enhancements in a variety of places.
-
- <li><em>Michael Stadler:</em>
- Reading 3d data in UCD, accepting boundary data in 3d;
-
- Eulerian mappings.
-
- <li><em>Martin Steigemann:</em>
- Graphical user interface for the ParameterHandler
- class. ParaSails preconditioner. Functionality in various
- places of the library.
-
- <li><em>Franz-Theo Suttmeier:</em>
- Initial parts of the linear algebra libraries.
-
- <li><em>Habib Talavatifard:</em>
- Bug fixes in the Trilinos interfaces.
-
- <li><em>Christophe Trophime:</em>
- Packaging and configuration issues.
-
- <li><em>Kainan Wang:</em>
- Extending deal.ii for 64-bit integer support.
-
- <li><em>Yaqi Wang:</em>
- The step-28 tutorial program;
-
- some grid generation functions.
-
- <li><em>Sven Wetterauer:</em>
- Step-15 tutorial program.
-
- <li><em>Joshua White:</em>
- Arbitrary order Eulerian mappings.
-
- <li><em>Christian Wülker:</em>
- GridOut::write_svg.
-
- <li><em>Yuhan Zhou:</em>
- Input to the curved boundary example in step-49.
- </ul>
-
-
- <p>
- deal.II draws from some ideas which were first implemented in the
- predecessor library,
- DEAL, developed by Guido Kanschat, Franz-Theo
- Suttmeier, and Roland Becker. It has also benefitted from
- knowing about DiffPack, a library developed in Norway in the
- 1990s.
- </p>
-
- <hr />
- <address>
- <a href="authors.html" target="body">The deal.II Authors</a>
- $Date$
- </address>
- <div class="right">
- <a href="http://validator.w3.org/check?uri=referer" target="_top">
- <img style="border:0" src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a>
- <a href="http://jigsaw.w3.org/css-validator/check/referer" target="_top">
- <img style="border:0;width:88px;height:31px" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a>
- </div>
+ <body>
+ This page is now part of the top-level project description. See
+ <a target="_top" href="http://dealii.org/authors.html">this page</a>.
</body>
+
</html>
library (no deal.II specific dependency checking, no
compatibility checking).
<li>
- It should do so by appropriate <code>FIND_LIBRARY</code> and
- <code>FIND_PATH</code> calls. The results of this calls should be the
- only cached variables.
- <li>
- <code>FIND_PACKAGE_HANDLE_STANDARD_ARGS</code> should be used for
- setting <code>FEATURE_FOUND</code> as this already respects the
- <code>QUIET</code> and <code>REQUIRED</code> keywords.
+ It should do so by appropriate <code>DEAL_II_FIND_LIBRARY</code>,
+ <code>DEAL_II_FIND_PATH</code> and <code>DEAL_II_FIND_FILE</code>
+ calls (same syntax as the native CMake functions; just a small
+ wrapper to provide some useful output). The results of this calls
+ should be the only cached variables.
<li>
A <code>WARNING</code>, <code>SEND_ERROR</code> or
<code>FATAL_ERROR</code> must be avoided (the only exception is
the <code>REQUIRED</code> keyword).
<li>
- If the feature is successfully found, a subset of the following
- <b>uncached</b> variables might be set:
-<pre>
+ The following uncached variables are recognized by the feature
+ configuration mechanism:
+<pre class="cmake">
FEATURE_FOUND
FEATURE_LIBRARIES (with optimized, debug, release keywords)
FEATURE_LIBRARIES(_DEBUG|_RELEASE)
-FEATURE_INCLUDE_DIRS
+FEATURE_INCLUDE_DIRS FEATURE_USER_INCLUDE_DIRS
FEATURE_LINKER_FLAGS(|_DEBUG|_RELEASE)
FEATURE_CXX_FLAGS(|_DEBUG|_RELEASE)
FEATURE_DEFINITIONS(|_DEBUG|_RELEASE)
-
FEATURE_VERSION
FEATURE_VERSION(_MAJOR|_MINOR|_SUBMINOR)
</pre>
-
-There are obviously valid exceptions from this rule, though.
+ The <code>DEAL_II_PACKAGE_HANDLE</code> macro should be exclusively
+ used for setting up these variables (except the version variants). An
+ example invocation is
+<pre class="cmake">
+DEAL_II_PACKAGE_HANDLE(UMFPACK
+ LIBRARIES
+ REQUIRED UMFPACK_LIBRARY
+ OPTIONAL CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY CAMD_LIBRARY ${_suitesparse_config}
+ REQUIRED AMD_LIBRARY
+ OPTIONAL METIS_LIBRARIES LAPACK_LIBRARIES rt_LIBRARY
+ INCLUDE_DIRS
+ REQUIRED UMFPACK_INCLUDE_DIR AMD_INCLUDE_DIR
+ OPTIONAL SuiteSparse_config_INCLUDE_DIR
+ LINKER_FLAGS
+ OPTIONAL LAPACK_LINKER_FLAGS
+ CLEAR
+ UMFPACK_LIBRARY CHOLMOD_LIBRARY CCOLAMD_LIBRARY COLAMD_LIBRARY
+ CAMD_LIBRARY SuiteSparse_config_LIBRARY AMD_LIBRARY UMFPACK_INCLUDE_DIR
+ AMD_INCLUDE_DIR SuiteSparse_config_INCLUDE_DIR
+ )
+</pre>
+ The macro concatenates all specified variables into the final
+ <code>FEATURE_SUFFIX</code> variable. Hereby, a feature is
+ successfully found if all <code>REQUIRED</code> variables are
+ non-empty an not set to <code>"-NOTFOUND"</code>.
+ <code>OPTIONAL</code> variables are just filtered out in this case.
+ As a last set of parameters the full list of cached search result
+ variables must be specified after the <code>CLEAR</code> keyword -
+ this is used to provide a possibility to undo a feature search.
<li>
Only "local" variables "<code>_<all lowercase></code>" or
"global" variables prefixed by <code>FEATURE_</code> may be
altered. Do not set <code>DEAL_II_*</code> or <code>CMAKE_*</code>
variables directly!
-
- <li>
- The find module must define a macro <code>FEATURE_CLEAR</code> that
- unsets all cached variables, so that a subsequent call to the find
- module starts a completely fresh features search.
<li>
A hint with <code>FEATURE_DIR</code> can be set up for
convenience. It is best to start the <code>Find</code> module by
-
<pre class="cmake">
+SET(FEATURE_DIR "" CACHE PATH "short description")
SET_IF_EMPTY(FEATURE_DIR "$ENV{FEATURE_DIR}")
</pre>
-
-and use <code>FEATURE_DIR</code> as a hint. If the external
-library could be found, hide it via
-<code>MARK_AS_ADVANCED</code>, if the external library could not
-be found, set a cache value:
-<pre class="cmake">
-SET(FEATURE_DIR "" CACHE PATH "An optional hint to a FEATURE directory")
-</pre>
- </ul>
+ and use <code>FEATURE_DIR</code> as a hint.
+</ul>
<a name="configure"></a>
<pre>
FEATURE_<FEATURE>_DEPENDS (a variable)
- a variable which contains an optional list of other features
- this feature depends on (and which have to be enabled for this feature
- to work.) The features must be given with the full option toggle:
- DEAL_II_WITH_[...]
+ this feature depends on (and which have to be enbled for this feature
+ to work.)
+ Features must be given with short name, i.e. without DEAL_II_WITH_
+
+FEATURE_<FEATURE>_AFTER (a variable)
+ - a variable which contains an optional list of other features
+ that have to be configured prior to this feature
+ Features must be given with short name, i.e. without DEAL_II_WITH_
FEATURE_<FEATURE>_FIND_EXTERNAL(var) (a macro)
- which should set var to TRUE if all dependencies for the feature are
</ul>
<li>
- For internal use, for setting necessary linker flags for the deal.II library:
+ For internal and external use, for setting necessary linker flags for
+ the deal.II library and user programs:
<ul>
<li> <code>DEAL_II_LINKER_FLAGS</code>
<li> <code>DEAL_II_LINKER_FLAGS_DEBUG</code>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>deal.II Development Navigation Bar</title>
<link href="../screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta http-equiv="content-language" content="en">
<p>
<a href="http://www.dealii.org/websvn/log.php?repname=deal.II+Repository&path=%2F&isdir=1&" target="_top">Recent changes</a><br />
<a href="http://cdash.kyomu.43-1.org/index.php?project=deal.II" target="body">CDash</a><br />
- <a href="http://www.dealii.org/cgi-bin/regression_quick.pl" target="body">Regression tests</a><br />
<a href="http://www.math.clemson.edu/~heister/bench" target="body">Performance tests</a><br />
</p>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
that future changes do not break what we have just checked in. Machines
running tests send results
back home and these are then converted into
- <a href="http://dealii.mathsim.eu/cgi-bin/regression_quick.pl"
+ <a href="http://cdash.kyomu.43-1.org/index.php?project=deal.II"
target="body">a webpage showing the status of our regression tests</a>.
</p>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<title>The deal.II Online Documentation</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<link href="screen.css" rel="StyleSheet" type="text/css">
- <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="2006/02/07 22:49:01">
<meta name="keywords" content="deal.II">
<meta name="svn_id" content="$Id$">
<li><a href="doxygen/deal.II/index.html" target="_top">Manual</a></li>
<li><a href="http://www.math.tamu.edu/~bangerth/videos.html" target="_top">Wolfgang's lectures</a></li>
<li><a href="reports/index.html" target="body">Technical reports</a></li>
- <li><a href="publications/index.html" target="body">Publications</a></li>
+ <li><a href="http://www.dealii.org/publications.html" target="body">Publications</a></li>
</ol>
</div>
</div>
<br>
<hr />
<address>
- <a href="authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
COMPONENT documentation
)
+INSTALL(FILES
+ ${CMAKE_SOURCE_DIR}/doc/deal.ico
+ DESTINATION ${DEAL_II_DOCHTML_RELDIR}/doxygen/deal.II
+ COMPONENT documentation
+ )
+
INSTALL(DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/deal.II
DESTINATION ${DEAL_II_DOCHTML_RELDIR}/doxygen
+++ /dev/null
-\documentclass[a4paper]{book}
-\usepackage{a4wide}
-\usepackage{makeidx}
-\usepackage{fancyhdr}
-\usepackage{graphicx}
-\usepackage{multicol}
-\usepackage{float}
-\usepackage{textcomp}
-\usepackage{alltt}
-\usepackage{doxygen}
-\makeindex
-\setcounter{tocdepth}{1}
-\renewcommand{\footrulewidth}{0.4pt}
-\begin{document}
-\begin{titlepage}
-\vspace*{7cm}
-\begin{center}
-{\Large deal.II Reference Manual for Version @DEAL_II_PACKAGE_VERSION@}\\
-\vspace*{1cm}
-{\large The deal.II Authors}\\
-\vspace*{0.5cm}
-{\small Generated by Doxygen, \today}\\
-\end{center}
-\end{titlepage}
-\clearemptydoublepage
-\pagenumbering{roman}
-\tableofcontents
-\clearemptydoublepage
-\pagenumbering{arabic}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2003 - 2013 by the deal.II authors
+// Copyright (C) 2003 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * @defgroup boundary Boundary description for triangulations
+ * @defgroup boundary Boundary and manifold description for triangulations
*
* The classes in this module are concerned with the description of the
- * boundary of a domain in which a Triangulation lives. This boundary
+ * geometry of a domain in which a Triangulation lives. This geometry
* description is necessary in three contexts:
* <ul>
*
- * <li> Mesh refinement: Whenever a cell at the boundary is refined, it is
- * necessary to introduce at least one new vertex on the boundary. In the
- * simplest case, one assumes that the boundary consists of straight line
- * segments (in 2d) or a bilinear surface (in 3d) between the vertices of
- * the original, coarsest mesh, and the next vertex is simply put into the
- * middle of the old ones. This is the default behavior of the Triangulation
- * class, and is described by the StraightBoundary class.
+ * <li> Mesh refinement: Whenever a cell is refined, it is necessary
+ * to introduce at least one new vertex. In the simplest case, one
+ * assumes that the cells and their faces consists of straight line
+ * segments, bilinear surface or trilinear volumes between the
+ * vertices of the original, coarsest mesh, and the next vertex is
+ * simply put into the middle of the old ones. This is the default
+ * behavior of the Triangulation class, and is described by the
+ * StraightBoundary and FlatManifold classes.
*
- * On the other hand, if one deals with curved boundaries, this is not the
- * appropriate thing to do. The classes derived from the Boundary base class
- * therefore describe the geometry of a domain. One can then attach an
- * object of a class derived from this base class to the Triangulation
- * object using the Triangulation::set_boundary() function, and the
- * Triangulation will ask the boundary object where a new vertex should be
- * located upon mesh refinement. Several classes already exist to support
- * the most common geometries, e.g., CylinderBoundary, HyperBallBoundary, or
- * HyperShellBoundary.
+ * On the other hand, if one deals with curved geometries and
+ * boundaries, this is not the appropriate thing to do. The classes
+ * derived from the Manifold and Boundary base classes describe the
+ * geometry of a domain. One can then attach an object of a class
+ * derived from this base classes to the Triangulation object using
+ * the Triangulation::set_boundary() (the old, deprecated function)
+ * or Triangulation::set_manifold() functions, and the Triangulation
+ * will ask the manifold object where a new vertex should be located
+ * upon mesh refinement. Several classes already exist to support
+ * the boundary of the most common geometries, e.g.,
+ * CylinderBoundary, HyperBallBoundary, or HyperShellBoundary.
*
- * <li> Integration: When using higher order finite element methods, it is
- * often necessary to compute cell terms (like cell contributions to the
- * matrix and right hand side of the linear system) using curved
- * approximations of the boundary, rather than the straight line
- * approximation. The actual implementation of such curved elements happens
- * in the Mapping class (see the @ref mapping module), which however obtains
- * its information about the boundary of the domain from the classes
- * described here. The same is, of course, true when integrating boundary
- * terms (e.g., inhomogenous Neumann boundary conditions).
+ * <li> Integration: When using higher order finite element methods,
+ * it is often necessary to compute cell terms (like cell
+ * contributions to the matrix and right hand side of the linear
+ * system) using curved approximations of the geometry, rather than
+ * the straight line approximation. The actual implementation of
+ * such curved elements happens in the Mapping class (see the @ref
+ * mapping module), which however obtains its information about the
+ * manifold description from the classes described here. The same
+ * is, of course, true when integrating boundary terms (e.g.,
+ * inhomogenous Neumann boundary conditions).
+ *
+ * <li> In cases where a Triangulation is embedded into a higher
+ * dimensional space, i.e., whenever the second template argument of
+ * the Triangulation class is explicitly specified and larger than
+ * the first (for an example, see step-34), the manifold description
+ * objects serve as a tool to describe the geometry not only of the
+ * boundary of the domain but of the domain itself, in case the
+ * domain is a manifold that is in fact curved. In these cases, one
+ * can use the Triangulation::set_manifold() function to indicate
+ * what manifold description to use when refining the curve, or when
+ * computing integrals using high order mappings.
*
- * <li> In cases where a Triangulation is embedded into a higher dimensional
- * space, i.e., whenever the second template argument of the Triangulation
- * class is explicitly specified and larger than the first (for an example,
- * see step-34), the boundary description objects also serve as a tool to
- * describe the geometry not only of the boundary of the domain but of the
- * domain itself, in case the domain is a manifold that is in fact curved.
* </ul>
*
- * In the context of triangulations, each face of a cell that is located at
- * the boundary of the domain stores a number called <tt>boundary_id</tt> that
- * uniquely identifies which part of the boundary this face is on. If nothing
- * is specified at creation time, each boundary face has a zero boundary
- * id. On the other hand, the boundary id of faces can be set either at
- * creation time or later by looping over all cells and querying their faces.
+ * In the context of triangulations, each object stores a number
+ * called <tt>manifold_id</tt>, and each face of a cell that is
+ * located at the boundary of the domain stores a number called
+ * <tt>boundary_id</tt> that uniquely identifies which part of the
+ * boundary this face is on. If nothing is specified at creation time,
+ * each boundary face has a zero boundary id and each triangulation
+ * object has an invalid manifold id. On the other hand, the boundary
+ * id of faces and the manifold id of objects can be set either at
+ * creation time or later by looping over all cells and querying their
+ * faces.
+ *
+ * It is then possible to associate objects describing the geometry to
+ * certain boundary_id values used in a triangulation and to certain
+ * manifold_id values.
+ *
+ * Befor version 8.2, the library allowed only boundary faces to
+ * follow a curved geometric description. Since version 8.2 this has
+ * been introduced also for interior faces and cells, and the
+ * boundary_id has been separated from the manifold_id.
+ *
+ * Although the old behavior is still supported, one should use the
+ * boundary indicator only for the physical meaning associated, for
+ * example, to boundary conditions, and revert to manifold_ids to
+ * describe the geometry of the triangulation.
+ *
+ * The behavior of the Triangulation class w.r.t. geometry
+ * descriptions is the following: Triangulation::set_boundary() and
+ * Triangulation::set_manifold() do the exact same thing: they attach
+ * a manifold descriptor to the specified id. The first function is
+ * maintained for backward compatibility, but will be deprecated in
+ * future releases.
+ *
+ * Whenever a new vertex is needed in an object that supports
+ * geometry dependent refinement (i.e., a face on the boundary, an
+ * interior face, or a cell in codimension one), the Triangulation
+ * queries the manifold_id of the object which needs refinement. If the
+ * manifold_id is set to numbers::invalid_manifold_id, then the
+ * Triangulation queries the boundary_id (if the face is on the
+ * boundary) or the material_id (if the Triangulation is of
+ * codimension one and the object is a cell). If the previous queries
+ * resulted in a number different from numbers::invalid_manifold_id,
+ * then the Triangulation looks wether a previous call to
+ * Triangulation::set_manifold() (or set_boundary()) was performed
+ * with the given id, and if yes, it uses the stored object to obtain
+ * new vertices, otherwise it uses a FlatManifold or StraightBoundary
+ * object.
*
- * It is then possible to associate objects describing the boundary to certain
- * boundary_id values used in a triangulation. Note that this is not
- * necessary: in some cases one may want to use the default straight boundary
- * approximation, and use non-zero boundary indicators for completely
- * different purposes, for example to indicate that a part of the boundary has
- * a different kind of boundary condition in the partial differential
- * equation.
+ * @note This behavior is backward compatible to that of deal.II versions
+ * prior to 8.2. If one ignores the manifold_id of an object (i.e., if it has
+ * never been set), by default it is and remains set to
+ * numbers::invalid_manifold_id. In that case, the first query above will
+ * trigger a query to the old style boundary_id. This behavior will be
+ * maintained for a while, but might eventually be changed. The suggested
+ * strategy is to use manifold_ids to describe the geometry, and boundary_ids
+ * to describe boundary conditions.
+ *
*
* @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
+ * @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*
* @ingroup grid
- * @author Wolfgang Bangerth, 1998-2006
+ * @author Wolfgang Bangerth, Luca Heltai, 1998-2014
*/
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2009 - 2013 by the deal.II authors
+// Copyright (C) 2009 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* @brief A module discussing the use of parallelism on distributed memory
* clusters.
*
+ * @dealiiVideoLecture{39,41,41.25,41.5}
+ *
* <h3>Overview</h3>
*
* deal.II can use multiple machine connected via MPI to parallelize
* represent quantities that will most definitely not be larger than 4 billion.
*
* The data type we define for these indices to keep the bulk
- * of the code base free of <code>#ifdef</code>s is types::global_dof_index.
+ * of the code base free of <code>\#ifdef</code>s is types::global_dof_index.
* If deal.II is configured as normal, this type is <code>unsigned int</code>,
* but can be switched to <code>unsigned long long int</code> if the right
* flag is provided (see the ReadMe file). This page is intended to clarify
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*
* <dt class="glossary">@anchor GlossBoundaryIndicator <b>%Boundary indicator</b></dt>
*
- * <dd>
- * In a Triangulation object, every part of the boundary is associated with
- * a unique number (of type types::boundary_id) that is used to identify which
- * boundary geometry object is responsible to generate new points when the mesh
- * is refined. By convention, this boundary indicator is also often used to
- * determine what kinds of boundary conditions are to be applied to a particular
- * part of a boundary. The boundary is composed of the faces of the cells and, in 3d,
- * the edges of these faces.
+ * <dd> In a Triangulation object, every part of the boundary may be
+ * associated with a unique number (of type types::boundary_id) that
+ * is used to determine what kinds of boundary conditions are to be
+ * applied to a particular part of a boundary. The boundary is
+ * composed of the faces of the cells and, in 3d, the edges of these
+ * faces.
*
* By default, all boundary indicators of a mesh are zero, unless you are
* reading from a mesh file that specifically sets them to something different,
* on each of the selected faces. To query the boundary indicator of a particular
* face or edge, use TriaAccessor::boundary_indicator.
*
- * The code above only sets the boundary indicators of a particular part
- * of the boundary, but it does not by itself change the way the Triangulation
- * class treats this boundary for the purposes of mesh refinement. For this,
- * you need to call Triangulation::set_boundary to associate a boundary
- * object with a particular boundary indicator. This allows the Triangulation
- * object to use a different method of finding new points on faces and edges
- * to be refined; the default is to use a StraightBoundary object for all
- * faces and edges. The results section of step-49 has a worked example that
- * shows all of this in action.
- *
- * The second use of boundary indicators is to describe not only which geometry
- * object to use on a particular boundary but to select a part of the boundary
- * for particular boundary conditions. To this end, many of the functions in
- * namespaces DoFTools and VectorTools take arguments that specify which part of
- * the boundary to work on. Examples are DoFTools::make_periodicity_constraints,
- * DoFTools::extract_boundary_dofs, DoFTools::make_zero_boundary_constraints and
+ * In older versions of the library (prior to 8.2), if you wanted also
+ * to change the way the Triangulation class treated the boundary for
+ * the purposes of mesh refinement, you could call
+ * Triangulation::set_boundary to associate a boundary object with a
+ * particular boundary indicator. This method is still supported, and
+ * it allows the Triangulation object to use a different method of
+ * finding new points on faces and edges to be refined; the default is
+ * to use a StraightBoundary object for all faces and edges. The
+ * results section of step-49 has a worked example that shows all of
+ * this in action.
+ *
+ * The suggested method from version 8.2 onwards, is to split the
+ * geometrical description of the boundary from its physical meaning,
+ * by using separately manifold_ids and boundary_ids. The former are
+ * used to describe how the geometry changes, and the latter are used
+ * to identify the boundary conditions.
+ *
+ * Many of the functions in namespaces DoFTools and VectorTools take
+ * arguments that specify which part of the boundary to work on, and
+ * they specifically refer to boundary_ids. Examples are
+ * DoFTools::make_periodicity_constraints,
+ * DoFTools::extract_boundary_dofs,
+ * DoFTools::make_zero_boundary_constraints and
* VectorTools::interpolate_boundary_values,
* VectorTools::compute_no_normal_flux_constraints.
*
* indicators is also presented in a section of the documentation of the
* Triangulation class.
*
- * @note For meshes embedded in a higher dimension (i.e., for which the
- * 'dim' template argument to the Triangulation class is less than the
- * 'spacedim' argument -- sometimes called the 'codimension one' or 'codimension
- * two' case), the Triangulation also stores boundary indicators for cells, not just
- * faces and edges. In this case, the boundary object associated with a particular
- * boundary indicator is also used to move the new center points of cells back
- * onto the manifold that the triangulation describes whenever a cell is refined.
- *
* @note For parallel triangulations of type parallel::distributed::Triangulation,
* it is not enough to set boundary indicators only once at the beginning. See
* the long discussion on this topic in the class documentation of
* is responsible to generate new points when the mesh is refined.
*
* By default, all manifold indicators of a mesh are set to
- * types::invalid_manifold_id. A typical piece of code that sets the
+ * numbers::invalid_manifold_id. A typical piece of code that sets the
* manifold indicator on a object to something else would look like
* this, here setting the manifold indicator to 42 for all cells whose
- * center has the x component located at $-1$:
+ * center has an $x$ component less than zero:
*
* @code
* for (typename Triangulation<dim>::active_cell_iterator cell =
* triangulation.begin_active();
* cell != triangulation.end(); ++cell)
- * if (cell->center()[0] == -1)
- * cell->set_manifold_id (42);
+ * if (cell->center()[0] < 0)
+ * cell->set_manifold_id (42);
* @endcode
*
- * Here we call the function TriaAccessor::set_manifold_id. It may
+ * Here we call the function TriaAccessor::set_manifold_id(). It may
* also be appropriate to call TriaAccessor::set_all_manifold_ids
* instead, to set recursively the manifold id on each face (and edge,
* if in 3d). To query the manifold indicator of a particular object
- * edge, use TriaAccessor::manifold_id.
+ * edge, use TriaAccessor::manifold_id().
*
* The code above only sets the manifold indicators of a particular
* part of the Triangulation, but it does not by itself change the way
* the Triangulation class treats this object for the purposes of mesh
- * refinement. For this, you need to call Triangulation::set_manifold
+ * refinement. For this, you need to call Triangulation::set_manifold()
* to associate a manifold object with a particular manifold
* indicator. This allows the Triangulation objects to use a different
* method of finding new points on cells, faces or edges to be
* @note Manifold indicators are inherited from parents to their
* children upon mesh refinement. Some more information about manifold
* indicators is also presented in a section of the documentation of
- * the Triangulation class.
+ * the Triangulation class as well as in the
+ * @ref manifold "Manifold documentation module".
* </dd>
*
* @see @ref manifold "The module on Manifolds"
* @ref distributed_paper "Distributed Computing paper" for more
* information.
*
+ * The layer of ghost cells consists of all cells that are face, edge, or
+ * vertex neighbors of any locally owned cell and that are not locally
+ * owned themselves. In other word, the ghost cells completely enclose the
+ * subdomain of locally owned cells (with the exception of the boundary of
+ * the domain, of course).
+ *
* The concept of ghost cells has no meaning for triangulations that
* store the entire mesh on each processor, i.e. the
* dealii::Triangulation class. </dd>
* distributed meshes, see the @ref distributed module. In such meshes, each
* cell is owned by exactly one processor. The locally owned ones are those
* owned by the current processor.
+ *
+ * Each processor in a parallel computation has a triangulation covering
+ * the entire domain that consists of cells that are locally owned, of
+ * @ref GlossGhostCell "ghost cells" and of
+ * @ref GlossArtificialCell "artificial cells".
* </dd>
*
*
* to the documentation pertaining to each of them:
*
* <ol>
- *
* <li> <b>%Triangulation</b>: Triangulations are collections of
* cells and their lower-dimensional boundary objects. Cells are
* images of the reference hypercube [0,1]<sup>dim</sup> under a
* The classes that describe triangulations and cells are located
* and documented in the @ref grid module. Iterators are described
* in the @ref Iterators module.
- *
- *
* <li> <b>Finite Element</b>: Finite element classes describe the
* properties of a finite element space as defined on the unit
* cell. This includes, for example, how many degrees of freedom are
* points on the unit cell.
*
* The finite element classes are described in the @ref feall module.
- *
- *
* <li> <b>%Quadrature</b>: As with finite elements, quadrature
* objects are defined on the unit cell. They only describe the
* location of quadrature points on the unit cell, and the weights
*
* The documentation of the classes describing particular quadrature
* formulas is found in the @ref Quadrature module.
- *
- *
* <li> <b>%DoFHandler</b>: %DoFHandler objects are the confluence
* of triangulations and finite elements: the finite element class
* describes how many degrees of freedom it needs per vertex, line,
* imply constraints on degrees of freedom, such as for hanging nodes
* or nodes at which boundary conditions apply; dealing with such
* constraints is described in the @ref constraints module.
- *
- *
* <li> <b>%Mapping</b>: The next step in a finite element program
* is that one would want to compute matrix and right hand side
* entries or other quantities on each cell of a triangulation,
* derivative and Jacobian determinants.
*
* These classes are all described in the @ref mapping module.
- *
- *
* <li> <b>%FEValues</b>: The next step is to actually take a finite
* element and evaluate its shape functions and their gradients at
* the points defined by a quadrature formula when mapped to the
* cells, and FESubfaceValues for evaluation on parts of faces of
* cells. All these classes are described in the @ref feaccess
* module.
- *
- *
* <li> <b>Linear Systems</b>: If one knows how to evaluate the
* values and gradients of shape functions on individual cells using
* FEValues and friends, and knows how to get the global numbers of
* of classes for this purpose, as well as with interfaces to other
* software packages that offer similar functionality. Documentation
* to this end can be found in the @ref LAC module.
- *
- *
* <li> <b>Linear Solvers</b>: In order to determine the solution of
* a finite-dimensional, linear system of equations, one needs
* linear solvers. In finite element applications, they are
* frequently iterative, but sometimes one may also want to use
* direct or sparse direct solvers. deal.II has quite a number of
* these. They are documented in the @ref Solvers module.
- *
- *
* <li> <b>Output</b>: Finally, once one has obtained a solution of
* a finite element problem on a given triangulation, one will often
* want to postprocess it using a visualization program. This
*
* A description of the classes that do so is given in the @ref
* output module.
- *
* </ol>
*
* In addition, deal.II has a number of groups of classes that go
// ---------------------------------------------------------------------
// $Id: manifold.h 30130 2013-07-23 13:01:18Z heltai $
//
-// Copyright (C) 2003 - 2013 by the deal.II authors
+// Copyright (C) 2003 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * @defgroup manifold Boundary description for triangulations
+ * @defgroup manifold Manifold description for triangulations
*
* The classes in this module are concerned with the description of the
- * manifold of a domain in which a Triangulation lives. This manifold
- * description is necessary in two contexts:
+ * manifold in which the domain that a Triangulation describes lives. This
+ * manifold description is necessary in two contexts:
+ *
* <ul>
*
* <li> Mesh refinement: Whenever a cell is refined, it is necessary
* to introduce some new vertices in the Triangulation. In the
* simplest case, one assumes that the objects that make up the
* Triangulation are straight line segments, a bi-linear surface or
- * a tri-linear volume, the next vertex is simply put into the
+ * a tri-linear volume. The next vertex is then simply put into the
* middle of the old ones. This is the default behavior of the
* Triangulation class, and is described by the FlatManifold class.
*
- * On the other hand, if one deals with curved geometries, or
- * geometries which require a denser refinement in some direction,
- * this is not the appropriate thing to do. The classes derived from
- * the Manifold base class therefore describe the geometry of a
- * domain. One can then attach an object of a class derived from
- * this base class to the Triangulation object using the
- * Triangulation::set_manifold() function, and the Triangulation
- * will ask the manifold object where a new vertex should be located
- * upon mesh refinement. Several classes already exist to support
- * the most common geometries, e.g., CylinderManifold, or
- * PolarManifold, which represent respectively the geometry obtained
- * when describing your space in cylindrical coordintes or in polar
- * coordinates.
+ * On the other hand, if one deals with curved geometries, or geometries
+ * which require a denser refinement in some direction, this is not the
+ * appropriate thing to do. The classes derived from the Manifold base class
+ * therefore describe the geometry of a domain. One can then attach an
+ * object of a class derived from this base class to the Triangulation
+ * object using the Triangulation::set_manifold() function associating it
+ * with a manifold id (see types::manifold_id), use this manifold id on the
+ * cells, faces or edges of the triangulation that should be described by
+ * this manifold using the TriaAccessor::set_manifold_id() function, and
+ * then the Triangulation will ask the manifold object where a new vertex to
+ * be located on a cell, face or edge so attributed should be located upon
+ * mesh refinement. Several classes already exist to support the most common
+ * geometries, e.g., CylinderManifold, or PolarManifold, which represent
+ * respectively the geometry obtained when describing your space in
+ * cylindrical coordintes or in polar coordinates.
*
* <li> Integration: When using higher order finite element methods, it is
* often necessary to compute cell terms (like cell contributions to the
*
* </ul>
*
- * In deal.II, a Manifold is seen as a collection of points, together
- * with a notion of distance between points (on the manifold). New
- * points are obtained by providing a local coordinate system on the
- * manifold, identifying existing points in the local coordinate
- * system (pulling them back using the local map to obtain their local
- * coordinates), find the new point in the local coordinate system by
- * weighted sums of the existing points, and transforming back the
- * point in the real space (pushing it forward using the local map).
+ * In deal.II, a Manifold is seen as a collection of points, together with a
+ * notion of distance between points (on the manifold). New points are
+ * typically obtained by providing a local coordinate system on the manifold,
+ * identifying existing points in the local coordinate system (pulling them
+ * back using the local map to obtain their local coordinates), find the new
+ * point in the local coordinate system by weighted sums of the existing
+ * points, and transforming back the point in the real space (pushing it
+ * forward using the local map). (However, this pull back and push forward
+ * only happens in classes that implement manifolds, and your own class can
+ * also choose other ways of figuring out where a new point should be
+ * located.)
*
* While this process is non trivial in most cases of interest, for
* most of the trivial geometries, like cylinders, spheres or shells,
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2006 - 2013 by the deal.II authors
+// Copyright (C) 2006 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* @ref MTToC "Table of Contents" below the lenghty list of members
* of this module.
*
+ * @dealiiVideoLecture{39,40}
+ *
* On machines with more than one processor (or multicore processors),
* it is often profitable to run several parts of the computations in
* %parallel. For example, one could have several threads running in
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* FESystem, which allows us to write code for systems of partial
* differential very much like we write code for single equations.
*
+ * @dealiiVideoLecture{19,20,21}
+ *
* <table class="tutorial" width="50%">
* <tr><th><b>%Table of contents</b></th></tr>
* <tr><td width="100%" valign="top">
INPUT_FILTER = ${CMAKE_SOURCE_DIR}/doc/doxygen/scripts/filter
FILTER_SOURCE_FILES = YES
+# Have some user defined commands that we can use in the documentation
+# and that expands to specific text. For some more transformations, see
+# the scripts/filter perl script that is run over the header files before
+# doxygen sees it and that can expand more complex expressions.
+ALIASES += dealiiRequiresUpdateFlags{1}="@note For this function to work properly, the underlying FEValues, FEFaceValues, or FESubfaceValues object on which you call it must have computed the information you are requesting. To do so, the <code>\1</code> flag must be an element of the list of UpdateFlags that you passed to the constructor of this object. See @ref UpdateFlagsEssay for more information."
+
+ALIASES += dealiiOperationIsMultithreaded="@note If deal.II is configured with threads, this operation will run multi-threaded by splitting the work into smaller chunks (assuming there is enough work to make this worthwhile)."
+
+
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
## ---------------------------------------------------------------------
## $Id$
##
-## Copyright (C) 2007 - 2013 by the deal.II authors
+## Copyright (C) 2007 - 2014 by the deal.II authors
##
## This file is part of the deal.II library.
##
# by replacing a "file:" at the end of a line with the text
# "file :", which doxygen doesn't recognize:
s#file:[ \t]*$#file :#g;
+
+
+
+# Handle commands such as @dealiiVideoLecture{20.5,33} by expanding it
+# into a note with some text
+if (m/(\@dealiiVideoLecture\{([0-9\.]+)(, *[0-9\.]+ *)*\})/)
+{
+ $substext = $1;
+
+ $text = "\@note The material presented here is also discussed in ";
+
+ # add links to the individual lectures
+ $text = $text . "<a href=\"http://www.math.tamu.edu/~bangerth/videos.676.$2.html\">video lecture $2</a>";
+
+ if (length($3) > 0)
+ {
+ $x = $3;
+ $x =~ s/^, *//g;
+ @otherlectures = split (',', "$x");
+
+ foreach $lecture (@otherlectures)
+ {
+ $text = $text . ", <a href=\"http://www.math.tamu.edu/~bangerth/videos.676.$lecture.html\">video lecture $lecture</a>";
+ }
+ }
+
+ $text = $text . ". (All video lectures are also available <a href=\"http://www.math.tamu.edu/~bangerth/videos.html\">here</a>.)";
+ s/(\@dealiiVideoLecture\{([0-9\.]+)(, *[0-9\.]+ *)*\})/$text/;
+}
+
+
+# @dealiiVideoLectureSeeAlso works as above, but just expands into
+# regular text, no @note
+if (m/(\@dealiiVideoLectureSeeAlso\{([0-9\.]+)(, *[0-9\.]+ *)*\})/)
+{
+ $substext = $1;
+
+ $text = "See also ";
+
+ # add links to the individual lectures
+ $text = $text . "<a href=\"http://www.math.tamu.edu/~bangerth/videos.676.$2.html\">video lecture $2</a>";
+
+ if (length($3) > 0)
+ {
+ $x = $3;
+ $x =~ s/^, *//g;
+ @otherlectures = split (',', "$x");
+
+ foreach $lecture (@otherlectures)
+ {
+ $text = $text . ", <a href=\"http://www.math.tamu.edu/~bangerth/videos.676.$lecture.html\">video lecture $lecture</a>";
+ }
+ }
+
+ $text = $text . ".";
+ s/(\@dealiiVideoLectureSeeAlso\{([0-9\.]+)(, *[0-9\.]+ *)*\})/$text/;
+}
if (m'</head>')
{
- print '<link rel="SHORTCUT ICON" href="http://www.dealii.org/deal.ico"></link>', "\n";
+ print '<link rel="SHORTCUT ICON" href="deal.ico"></link>', "\n";
print '<meta name="author" content="The deal.II Authors <authors@dealii.org>"></meta>', "\n";
print '<meta name="copyright" content="Copyright (C) 1998 - ', $year, ' by the deal.II authors"></meta>', "\n";
print '<meta name="deal.II-version" content="@DEAL_II_PACKAGE_VERSION@"></meta>', "\n";
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
@@MAP@@
* @enddot
*
- * Legend:<br />
- * <b>Green octagons:</b> programs that show basic techniques;<br />
- * <b>Orange boxes:</b> advanced techniques;<br />
- * <b>Yellow:</b> applications in fluid dynamics;<br />
- * <b>Light blue:</b> applications in solid mechanics;<br />
- * <b>Dark blue boxes:</b> time dependent problems.
+ * <b>Legend:</b><br />
+ * <blockquote>
+ * <i>Green:</i> programs that show basic techniques; <br />
+ * <i>Orange:</i> advanced techniques; <br />
+ * <i>Yellow:</i> applications in fluid dynamics; <br />
+ * <i>Light blue:</i> applications in solid mechanics; <br />
+ * <i>Dark blue:</i> time dependent problems.
+ * </blockquote>
*
* <a name="list"></a>
* <h3>Tutorial programs listed by number</h3>
* <td>Step-3</td>
* <td> Actually solve Laplace's
* problem. Object-orientation. Assembling matrices and
- * vectors. Boundary values.
+ * vectors. %Boundary values.
* </td></tr>
*
* <tr valign="top">
*
* <tr valign="top">
* <td>Step-34</td>
- * <td> Boundary element methods (BEM) of low order: Exterior irrotational
+ * <td> %Boundary element methods (BEM) of low order: Exterior irrotational
* flow. The ParsedFunction class.
* </td></tr>
*
* Step-31,
* Step-32,
* Step-33,
- * Step-40,
* Step-42,
* Step-43
* </td>
* </tr>
*
* <tr valign="top">
- * <td> Boundary element methods, curved manifolds
+ * <td> %Boundary element methods, curved manifolds
* </td>
* <td>
* Step-32,
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<head>
<title>The deal.II Readme on interfacing to PETSc</title>
<link href="../screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II">
<h4>Installing <acronym>deal.II</acronym> with PETSc</h4>
- <p style="color: red"><b>Note:</b> The latest version of PETSc tested is
- 3.4.2. Major releases after this version may cause problems, so we
- recommend sticking to this version if at all possible.
+ <p style="color: red"><b>Note:</b> The most recent version of
+ PETSc that has been reported to be compatible
+ with <acronym>deal.II</acronym> is version 3.4. If you use a
+ later version than this and encounter problems, let us know.
</p>
<p>
- PETSc usually requires you to set the
+ When you compile and install PETSc, you need to set
environment variables <code>PETSC_DIR</code> and <code>PETSC_ARCH</code>
to a path to PETSc and denoting the architecture for which PETSc is
- compiled (a string you can choose however you like, it is simply
- intended to identify one of possibly several different PETSc
- installations). If these environment variables are set, then
- <acronym>deal.II</acronym> will pick them up during
- configuration, and store them. It will then also recognize that
- PETSc shall be used, and enable the wrapper classes.
+ compiled. <code>PETSC_ARCH</code> is in reality just a name you give to
+ your installation, it is a string you can choose however you like. The
+ point of it is that it allows you to have multiple possibly different
+ PETSc installations. A consequence of this is that you need to
+ let <acronym>deal.II</acronym>'s <code>cmake</code> scripts know which
+ one of these installations you want it to use, i.e., you need to set the
+ <code>PETSC_ARCH</code> variable to the same value you used when you
+ installed PETSc. The same is true for <code>PETSC_DIR</code>. You can
+ this via environment variables. <code>cmake</code> will then also
+ recognize that PETSc shall be used, and enable the wrapper classes,
+ without you having to explicitly say that you want to use PETSc.
</p>
<p>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<head>
<title>The deal.II Readme on interfacing to Trilinos</title>
<link href="../screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II">
engines, etc. Of particular interest to deal.II is their ability to
provide this functionality both on sequential and parallel (using MPI)
computers. Compared to <a href="http://www.mcs.anl.gov/petsc/"
- target="_top">PETSc</a>, which is written in C, Trilinos is written in
+ target="_top">PETSc</a>, which is written in C, Trilinos is written in
C++ and can be
considered to be a more modern version of PETSc though both packages are
under continuing development at their respective national laboratories.
Trilinos uses <a href="http://cmake.org/">cmake</a> to configure and
build. The following slightly longish set of commands will set up a
reasonable configuration:
- <pre>
-
- cd trilinos-11.4.1
- mkdir build
- cd build
-
- cmake -D Trilinos_ENABLE_Sacado=ON \
- -D Trilinos_ENABLE_Stratimikos=ON \
- -D CMAKE_BUILD_TYPE=RELEASE \
- -D CMAKE_CXX_FLAGS="-g -O3" \
- -D CMAKE_C_FLAGS="-g -O3" \
- -D CMAKE_FORTRAN_FLAGS="-g -O5" \
- -D Trilinos_EXTRA_LINK_FLAGS="-lgfortran" \
- -D CMAKE_VERBOSE_MAKEFILE=FALSE \
- -D Trilinos_VERBOSE_CONFIGURE=FALSE \
- -D TPL_ENABLE_MPI=ON \
- -D BUILD_SHARED_LIBS=ON \
- -D CMAKE_INSTALL_PREFIX:PATH=$HOME/share/trilinos \
- ..
-
- make install
- </pre>
+ <pre>
+
+ cd trilinos-11.4.1
+ mkdir build
+ cd build
+
+ cmake -D Trilinos_ENABLE_Sacado=ON \
+ -D Trilinos_ENABLE_Stratimikos=ON \
+ -D CMAKE_BUILD_TYPE=RELEASE \
+ -D CMAKE_CXX_FLAGS="-g -O3" \
+ -D CMAKE_C_FLAGS="-g -O3" \
+ -D CMAKE_FORTRAN_FLAGS="-g -O5" \
+ -D Trilinos_EXTRA_LINK_FLAGS="-lgfortran" \
+ -D CMAKE_VERBOSE_MAKEFILE=FALSE \
+ -D Trilinos_VERBOSE_CONFIGURE=FALSE \
+ -D TPL_ENABLE_MPI=ON \
+ -D BUILD_SHARED_LIBS=ON \
+ -D CMAKE_INSTALL_PREFIX:PATH=$HOME/share/trilinos \
+ ..
+
+ make install
+ </pre>
You will need to adjust the path into which you want to install Trilinos
in the CMAKE_INSTALL_PREFIX line.
</p>
+
+ <h5>Parallel builds</h5>
+
<p>
- <b>Parallel builds:</b>
If your computer has more than one processor core, use
<code>make -jN</code> instead of <code>make</code> in the last line
above, where <code>N</code> is the number of processors you have.
</p>
+
+ <h5>BLAS and LAPACK</h5>
+
<p>
Trilinos sometimes searches for other libraries but can't find
them if they are not in the usual directories or have other
library names under which they can be found
to <code>cmake</code>. For example, this may mean to add the
following flags to the call above:
- <pre>
+ <pre>
- -D BLAS_LIBRARY_NAMES:STRING=goto \
- -D BLAS_LIBRARY_DIRS:STRING=/apps/GotoBLAS/lib64 \
- -D LAPACK_LIBRARY_NAMES:STRING=lapack \
- -D LAPACK_LIBRARY_DIRS:STRING=/apps/lapack-3.2.1/lib64
- </pre>
+ -D BLAS_LIBRARY_NAMES:STRING=goto \
+ -D BLAS_LIBRARY_DIRS:STRING=/apps/GotoBLAS/lib64 \
+ -D LAPACK_LIBRARY_NAMES:STRING=lapack \
+ -D LAPACK_LIBRARY_DIRS:STRING=/apps/lapack-3.2.1/lib64
+ </pre>
</p>
+
+ <h5>Using external direct solvers</h5>
+
+ <p>
+ Trilinos (via its Amesos package) can interface with a number of direct
+ solvers (see, for example,
+ <a href="http://trilinos.org/docs/r11.8/packages/amesos/doc/html/index.html"
+ target="_top">this page for Trilinos 11.8</a>). Most of them are external
+ packages to Trilinos and you will need to tell Trilinos configuration
+ scripts that you want to use them, for example via the
+ <code>TrilinosWrappers::SolverDirect</code> class. This can be tricky,
+ but adding defines similar to the following to the cmake command line
+ will achieve the goal to enable the UMFPACK and SuperLU/SuperLUDist
+ solvers:
+ <pre>
+
+ -D TPL_ENABLE_UMFPACK:BOOL=ON \
+ -D TPL_ENABLE_SuperLU:BOOL=ON \
+ -D TPL_ENABLE_SuperLUDist:BOOL=ON \
+ -D TPL_UMFPACK_INCLUDE_DIRS="/usr/include" \
+ -D SuperLUDist_INCLUDE_DIRS:FILEPATH="/path/to/SuperLU_DIST_3.2/SRC" \
+ -D TPL_SuperLUDist_LIBRARIES:FILEPATH="/path/to/SuperLU_DIST_3.2/lib/libsuperlu_dist.a" \
+ -D SuperLU_INCLUDE_DIRS:FILEPATH="/path/to/SuperLU_4.3/SRC" \
+ -D TPL_SuperLU_LIBRARIES:FILEPATH="/path/to/SuperLU_4.3/lib/libsuperlu_4.3.a"
+ </pre>
+ Similarly, to enable MUMPS, commands should include
+ <pre>
+
+ -D TPL_ENABLE_MUMPS:BOOL=ON \
+ -D TPL_ENABLE_SCALAPACK:BOOL=ON
+ </pre>
+ and possibly followed by
+ <pre>
+
+ -D TPL_MUMPS_INCLUDE_DIRS:PATH=/usr/include/openmpi-x86_64 \
+ -D SCALAPACK_LIBRARY_DIRS:PATH=/lib64/openmpi/lib \
+ </pre>
+ where you need to adjust the exact paths, of course.
+ </p>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<head>
<title>The deal.II License</title>
<link href="screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II license">
<p>
<b>However, <acronym>deal.II</acronym> is not in the public domain, it
is property of and copyrighted by the
- <a href="authors.html"><acronym>deal.II</acronym> Authors</a>, and
+ <a href="http://www.dealii.org/authors.html" target="_top"><acronym>deal.II</acronym> Authors</a>, and
there are restrictions on its use:</b>
The legally binding license is the <a href="#license-text">GNU Lesser
General Public License</a> (LGPL) as published by the Free Software
In this document, as well as in the program files, the terms
<i>authors of <acronym>deal.II</acronym></i> and
<i><acronym>deal.II</acronym> authors</i> generally refer to all
- people mentioned at the <a href="authors.html">deal.II Authors</a>
+ people mentioned at the <a href="http://www.dealii.org/authors.html" target="_top">deal.II Authors</a>
page.
</p>
<li> Every publication presenting numerical results obtained with the
help of <acronym>deal.II</acronym> should state the name of the
library and cite the canonical deal.II reference listed at the top of
- <a href="publications/index.html">the publications page</a>.
+ <a href="http://www.dealii.org/publications.html">the publications page</a>.
</ul>
</p>
<p>
developing deal.II as an academic undertaking.
</p>
<p>
- We keep a <a href="publications/index.html">list of publications
+ We keep a <a href="http://www.dealii.org/publications.html">list of publications
using deal.II</a>. Feel free to let us know about your publications.
</p>
<hr />
<address>
- <a href="authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<head>
<title>deal.II Communications</title>
<link href="screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II">
<hr />
<address>
- <a href="authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<head>
<title>deal.II navigation bar</title>
<link href="screen.css" rel="StyleSheet">
- <meta name="copyright" content="Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012, 2013 by the deal.II Authors">
+ <meta name="copyright" content="Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II Authors">
<meta name="date" content="2006/02/07 22:49:06">
<meta name="svn_id" content="$Id$">
</head>
<b><small>Online Resources</small></b>
<p>
<a href="https://code.google.com/p/dealii/wiki/FrequentlyAskedQuestions" target="_top">FAQ</a><br />
- <a href="news/news.html" target="body">News</a><br />
+ <a href="http://www.dealii.org/news.html" target="_top">News</a><br />
<a href="http://www.dealii.org/download/" target="body">Download</a><br />
<a href="http://www.dealii.org/mail.html" target="body">Mailing list</a><br />
<a href="https://code.google.com/p/dealii/w/list" target="_top">Wiki</a><br />
<b><small>Resources</small></b>
<p>
<a href="reports/index.html" target="body">Reports</a><br />
- <a href="publications/index.html" target="body">Publications</a><br />
- <a href="authors.html" target="body">Authors</a> <br />
+ <a href="http://www.dealii.org/publications.html" target="body">Publications</a><br />
+ <a href="http://www.dealii.org/authors.html" target="_top">Authors</a> <br />
<a href="license.html" target="body">License</a> <br />
<a href="mail.html" target="body">Contact</a>
</p>
- // ---------------------------------------------------------------------
+// ---------------------------------------------------------------------
// $Id$
//
// Copyright (C) 2013, 2014 by the deal.II authors
</p>
<ol>
+ <li> Removed: Class PointerMatrixBase (and, consequently, the various
+ classes derived from it) had comparison operators that were intended to
+ work generically for any kind of derived class. However, the implementation
+ used a scheme that was not robust enough to handle the various situations
+ that derived classes implemented and, consequently, was not always correct.
+ These operators were not previously used inside the library and, likely,
+ were not widely used in applications either. They have now been removed.
+ <br>
+ (Wolfgang Bangerth, 2014/02/15)
+ </li>
+
+ <li> The change from functionparser to muparser introduced a small number of
+ incompatibilies: units, use_degress, and recursion with 'eval' are not
+ longer supported. Comparing for equality is done using '==' instead of '='.
+ <br>
+ (Timo Heister, 2014/02/10)
+ </li>
+
<li> Changed: The various classes generating graphical output, such
as DataOut or DataOutStack, are all derived from a common interface
class DataOutInterface which, in turn was derived from DataOutBase
<ol>
+ <li> New: Added support for curved interior boundaries, and general
+ manifold id description.
+ <br>
+ A new attribute was added to each triangulation object
+ (types::manifold_id) which allows one to specify a manifold
+ description, much in the same way we do for boundaries, also for
+ interior edges and faces. At the moment this information is used
+ only for objects of topological dimension less than spacedim, but a
+ generalization of the class Boundary<dim,spacedim> is on its way to
+ allow also curved cells.
+ <br>
+ For the moment, full backward compatibility is granted, and one can
+ keep using the old Boundary<dim,spacedim>, together with
+ Triangulation::set_boundary(), and Triangulation::get_boundary()
+ methods. However, this change suggests to use the types::boundary_id associated
+ with each boundary face to indicate only boundary condition types, and
+ it allows to separate the geometric meaning from the physical meaning. The
+ suggested usage is
+ - types::boundary_id is used for the physical meaning
+ - types::manifold_id is used for the geometric meaning.
+ <br>
+ (Luca Heltai, 2014/07/14)
+ </li>
+
+ <li> New: Tutorial programs (and a few other places) are now cross-linked
+ to their corresponding video lectures.
+ <br>
+ (Wolfgang Bangerth, 2014/07/10)
+ </li>
+
+ <li> Changed: The functionparser library bundled with deal.II got replaced
+ by the muparser library.
+ <br>
+ (Timo Heister, 2014/02/10)
+ </li>
+
<li> Changed: It was possible to call DoFAccessor::set_active_fe_index()
on non-active cells. However, this made no sense: Since degrees of
freedoms only exist on active cells
<h3>Specific improvements</h3>
<ol>
+ <li> New: The GridReordering::reorder_cells() function used a
+ numbering format for the vertices in a cell that was last used in
+ deal.II version 5.2. This format is still used internally, but
+ the function now also understands the numbering that has been
+ used in deal.II ever since. The choice is made by an additional
+ argument to the function that defaults to the old-style
+ format for backward compatibility.
+ <br>
+ (Wolfgang Bangerth, 2014/07/14)
+ </li>
+
+ <li> New: There are now functions GridOut::write_vtk() and
+ GridOut::write_vtu() that can
+ write a mesh in VTK/VTU format.
+ <br>
+ (Wolfgang Bangerth, 2014/07/14)
+ </li>
+
+ <li> Fixed: PETSc up to at least version 3.5 has a bug where it does
+ not zero-initialize the ghost elements of a newly created ghosted
+ parallel vector. This is now worked around inside deal.II.
+ <br>
+ (Wolfgang Bangerth, Michal Wichrowski, 2014/07/12)
+ </li>
+
+ <li> Improved: The Trilinos direct solver, TrilinosWrappers::SolverDirect,
+ now takes a string to select among the available Amesos solvers. Moreover,
+ the solver now also supports deal.II's distributed vectors.
+ <br>
+ (Uwe Köcher, Martin Kronbichler, 2014/07/09)
+ </li>
+
+ <li> New: There are now three new preconditioner classes
+ TrilinosWrappers::PreconditionBlockJacobi,
+ TrilinosWrappers::PreconditionBlockSSOR, and
+ TrilinosWrappers::PreconditionBlockSOR that work on small dense blocks of
+ the global matrix instead of the point-wise relaxation methods in
+ TrilinosWrappers::Precondition{Jacobi,SSOR,SOR} that work on each row
+ separately.
+ <br>
+ (Martin Kronbichler, 2014/07/04)
+ </li>
+
+ <li> Fixed: Some versions of DoFTools::extract_boundary_dofs() were
+ not instantiated for some combinations of arguments. This could lead
+ to missing symbol errors during linking of applications on some
+ platforms and with some compiler versions. This is now
+ fixed.
+ <br>
+ (Wolfgang Bangerth, 2014/07/04)
+ </li>
+
+ <li> Fixed: GridGenerator::merge_triangulations produced sometimes invalid
+ orientations of faces. This is now fixed.
+ <br>
+ (Daniel Arndt, 2014/06/30)
+ </li>
+
+ <li> Fixed: TrilinosWrappers::PreconditionAMG did not read user-provided
+ constant modes (aka null space) when the null space dimension is one but not
+ just the trivial one vector. This is now fixed.
+ <br>
+ (Martin Kronbichler, 2014/06/30)
+ </li>
+
+ <li> Simplified interfaces for FEEvaluation: Previously, the user had to
+ select the appropriate kernel (FEEvaluation, FEEvaluationGeneral,
+ FEEvaluationDGP, FEEvaluationGL) for the matrix-free evaluation
+ routines. This made it difficult to write compact code that needs to select
+ between different elements. Therefore, all the functionality has been merged
+ into FEEvaluation and one should only use FEEvaluation, while the other
+ interfaces have been marked deprecated and will be removed in a future
+ version. The internal data structures for the various special cases have
+ been kept in order to provide for the most efficient routines, which is
+ selected at construction of FEEvaluation.
+ <br>
+ (Martin Kronbichler, 2014/06/27)
+ </li>
+
+ <li> Bugfix: TBB specific include directories have to be added to the
+ list of user include directories because of direct inclusion of header
+ files in base/thread_local_storage.h.
+ <br>
+ (Matthias Maier, Kainan Wang, 2014/06/25)
+ </li>
+
+ <li> Improved: GridGenerator::hyper_cube() accepts a
+ <code>colorize</code> argument.
+ <br>
+ (Guido Kanschat, 2014/06/23)
+ </li>
+
+ <li> New: Functions DoFTools::extract_locally_relevant_dofs(),
+ parallel::distributed::refine_and_coarsen_fixed_number() and
+ parallel::distributed::refine_and_coarsen_fixed_fraction() are
+ now also instantiation for objects of codimension 1.
+ <br>
+ (Michal Wichrowski, 2014/06/15)
+ </li>
+
+ <li> New: There are now functions Triangulation::has_hanging_nodes()
+ and parallel::distributed::Triangulation::has_hanging_nodes().
+ <br>
+ (Denis Davydov, 2014/06/15)
+ </li>
+
+ <li> New: There is now function Triangulation::n_global_active_cells().
+ <br>
+ (Denis Davydov, 2014/06/19)
+ </li>
+
+ <li> New: The class FEEvaluation now provides optimized matrix-free
+ evaluation routines for FE_Q_DG0 elements.
+ <br>
+ (Martin Kronbichler, 2014/06/13)
+ </li>
+
+ <li> Bugfix: Filter libclang_rt* from the PETSc link line.
+ <br>
+ (Matthias Maier, 2014/06/04)
+ </li>
+
+ <li> Improved: ParameterHandler parsing added to DoFOutputOperator
+ <br>
+ (Guido Kanschat, 2014/06/03)
+ </li>
+
+ <li> Improved: ThetaTimestepping and other operators now use AnyData
+ to communicate with operators they rely on. This way, time step data
+ can be forwarded using the same mechanism, and no complicated back
+ access to member data is required
+ anymore. MeshWorker::IntegrationInfo uses AnyData as well.
+ <br>
+ (Guido Kanschat, 2014/06/03)
+ </li>
+
+ <li> Bugfix: CMake: Also clean CMAKE_MODULE_PATH prior to call to
+ FIND_PACKAGE(Boost) inside FindBOOST.cmake because apparently
+ "Boost" == "BOOST" for the Mac file system...
+ <br>
+ (Matthias Maier, 2014/05/28)
+ </li>
+
+ <li> Improved: CMake: Search results and error conditions for external
+ libraries are now much more verbose. Added an MPI sanity check.
+ <br>
+ (Matthias Maier, 2014/05/28)
+ </li>
+
+ <li> Fixed: The MatrixTools::apply_boundary_values() variant that works
+ on PETSc matrices could produce a deadlock in parallel if one processor
+ had no boundary values to apply. This is now fixed.
+ <br>
+ (Michal Wichrowski, 2014/05/19)
+ </li>
+
+ <li> New: AnyData::try_read() is a function that allows users to check
+ whether an entry exists and get a pointer to it without throwing an
+ exception in case of failure.
+ <br>
+ (Guido Kanschat, 2014/05/16)
+ </li>
+
+ <li> New: The GMRES solver of deal.II can now write an estimate of
+ eigenvalues to the log file, in analogy to the CG solver. This is enabled
+ by the flag SolverGMRES::AdditionalData::compute_eigenvalues.
+ <br>
+ (Martin Kronbichler, 2014/05/11)
+ </li>
+
+ <li> New: The GridIn::read_vtk() function places fewer restrictions
+ on the VTK files it wants to read and should, consequently, be able
+ to read more correctly formatted VTK files than before.
+ <br>
+ (Giorgos Kourakos, 2014/05/08)
+ </li>
+
+ <li> New: There is now a QSorted quadrature which takes an
+ arbitrary quadrature at construction time and reorders the quadrature
+ points according to the weigths, from smaller to bigger. This should
+ improve stability of higher order polynomial integration.
+ <br>
+ (Luca Heltai, 2014/05/07)
+ </li>
+
+ <li> New: The class VectorizedArray<Number> now provides methods
+ VectorizedArray::load(ptr) to read from arbitrary pointer addresses and
+ VectorizedArray::store(ptr) to write to arbitrary pointer addresses,
+ as opposed to the data layout of VectorizedArray that requires pointers
+ to be aligned by the size of the array in bytes. This also circumvents
+ a (rare) compiler optimization bug with gcc-4.6 on SSE code in combination
+ with function calls, e.g. to std::sin.
+ <br>
+ (Martin Kronbichler, 2014/05/05)
+ </li>
+
+ <li> Changed: Namespace SparsityTools had a local typedef <code>size_type</code>
+ that was set equal to types::global_dof_index. This typedef has been removed
+ and we now use SparsityPattern::size_type wherever applicable as this is the
+ type we really want to use. (The code worked previously because
+ types::global_dof_index and SparsityPattern::size_type happen to be the same
+ as far as the underlying type is concerned; however, they are different
+ semantically.)
+ <br>
+ (Wolfgang Bangerth, 2014/05/04)
+ </li>
+
+ <li> Updated: The step-16 tutorial program was updated to the new layout
+ multigrid objects and thus avoids using deprecated interfaces.
+ <br>
+ (Martin Kronbichler, 2014/05/03)
+ </li>
+
+ <li> Fixed: FE_DGQArbitraryNodes::has_support_on_face was broken when
+ polynomials with support points not on the element boundary were used.
+ This is now fixed.
+ <br>
+ (Martin Kronbichler, 2014/04/30)
+ </li>
+
+ <li> Fixed: parallel::distributed::Triangulation::load now has an
+ additional parameter <code>autopartition</code> to control p4est's behavior of
+ rebalancing triangulations between MPI nodes upon reading. It is
+ particularly useful to disable this behavior when data is stored
+ separately (examples for this are in the regression tests mpi/p4est_save_0?).
+ <br>
+ (Alexander Grayver, Matthias Maier, 2014/04/26)
+ </li>
+
+ <li> Fixed: GridTools::find_active_cell_around_point() could get into an infinite
+ loop if the point we are looking for is in fact not within the domain. This is now
+ fixed.
+ <br>
+ (Giorgos Kourakos, Timo Heister, Wolfgang Bangerth, 2014/04/14)
+ </li>
+
+ <li> Changed: TableBase<N,T> now uses AlignedVector for storing data
+ instead of std::vector, which allows its use for VectorizedArray<Number>
+ data fields which require more alignment.
+ <br>
+ (Martin Kronbichler, 2014/04/09)
+ </li>
+
+ <li> Improved: Piola transformation for FE_BDM is now active.
+ <br>
+ (Guido Kanschat, 2014/04/09)
+ </li>
+
+ <li> Changed: operator< for cell iterators no longer looks at
+ (level-)subdomain ids but only compares level() and index(). This makes the
+ ordering inconsistent between processes on a
+ parallel::distributed::Triangulation, but fixes the problem that the
+ ordering of cells changes under mesh refinement or other causes for changing
+ the subdomain id.
+ <br>
+ (Timo Heister, 2014/04/08)
+ </li>
+
+ <li> New: GridTools::laplace_transform() now takes an addition, optional
+ parameter that indicates the "stiffness" of the mapping.
+ <br>
+ (Denis Davydov, Jean-Paul Pelteret, 2014/04/07)
+ </li>
+
+ <li> Fixed: DoFTools::extract_constant_modes now correctly identifies both
+ constant modes in the scalar element FE_Q_DG0, which has been realized by a
+ few modifications in how the constant modes propagate from the element to
+ the extract_constant_modes() function.
+ <br>
+ (Martin Kronbichler, 2014/04/04)
+ </li>
+
+ <li> Fixed: GridTools::laplace_transform had previously announced in
+ the documentation that one can also set the location of interior points,
+ but this was not in fact what was implemented. This has now been fixed:
+ the code can now do that.
+ <br>
+ (Denis Davydov, Wolfgang Bangerth, 2014/03/23)
+ </li>
+
+ <li> Improved: Inhomogeneous tangential and normal flow constraints can
+ now be treated via VectorTools::compute_nonzero_normal_flux_constraints
+ and VectorTools::compute_nonzero_tangential_flux_constraints.
+ <br>
+ (Daniel Arndt, 2014/03/16)
+ </li>
+
+ <li> Changed: Class TriaAccessor had a function parent_index(), but this function
+ could only work for cell accessors. The function has consequently been moved
+ to class CellAccessor.
+ <br>
+ (Wolfgang Bangerth, 2014/03/15)
+ </li>
+
+ <li> Fixed: step-32 had a piece of code where we accessed an internal
+ representation of how Trilinos vectors are actually stored. This is poor
+ style and has been rewritten.
+ <br>
+ (Wolfgang Bangerth, 2014/03/14)
+ </li>
+
+ <li> Fixed: VectorTools::project_boundary_values_curl_conforming contained
+ a bug for some cases. This is now fixed.
+ <br>
+ (Markus Bürg, 2014/03/10)
+ </li>
+
+ <li> Fixed: ParameterHandler will no longer output an error if the file
+ to be read ends with "end" without a newline.
+ <br>
+ (Timo Heister, 2014/02/28)
+ </li>
+
+ <li>Improved: DoFRenumbering::Cuthill_McKee can now run with distributed
+ triangulations with the renumbering only done within each processor's
+ subdomain.
+ <br>
+ (Martin Kronbichler, 2014/02/20)
+
+ <li>Fixed: There was an indexing error in GridIn::read_vtk() that triggered
+ for some input files. This is now fixed.
+ <br>
+ (Mayank Sabharwal, 2014/02/19)
+
+ <li>New: There is a new namespace TimeStepping for the algorithms that do time
+ integrations. In this new namespace, several Runge-Kutta methods have been
+ implemented: explicit methods, implicit methods, and embedded explicit methods.
+ <br>
+ (Damien Lebrun-Grandie, Bruno Turcksin, 2014/02/17)
+
+ <li>New: There is now a class FEEvaluationDGP that implements matrix-free
+ evaluation routines by truncated tensor products for FE_DGP elements.
+ <br>
+ (Martin Kronbichler, 2014/02/17)
+
+ <li>Changed: The InverseMatrixRichardson used to eat all exceptions
+ that may have been produced by the underlying Richardson solver, leaving
+ no trace that the underlying solver may have failed when you call functions
+ such as InverseMatrixRichardson::vmult(). These exceptions are now propagated
+ out to the caller.
+ <br>
+ (Wolfgang Bangerth, 2014/02/16)
+
+
+ <li>New: FE_TraceQ implements finite elements on faces, which
+ correspond to the traces of H<sup>1</sup>-conforming elements.
+ <br>
+ (Angela Klewinghaus, 2014/02/14)
+
+ <li>New: FE_FaceQ and FE_FaceP now also work in 1D (with a single dof
+ on each vertex).
+ <br>
+ (Martin Kronbichler, 2014/02/11)
+
+ <li>Fixed: FE_DGQ::has_support_on_face returned a wrong number for element
+ degree larger than 1 in 1D. This is now fixed.
+ <br>
+ (Martin Kronbichler, 2014/02/10)
+
<li>Changed: DerivativeApproximation used to be a class that only had
static members. It is now a namespace.
<br>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
+ "http://www.w3.org/TR/html4/loose.dtd">
<html>
-<head>
- <link href="../screen.css" rel="StyleSheet">
- <title>The deal.II news page</title>
- <meta name="copyright" content="Copyright (C) 2000 - 2013 by the deal.II Authors">
- <meta name="date" content="$Date$">
- <meta name="keywords" content="deal.II">
- <meta name="svn_id" content="$Id$">
-</head>
+ <head>
+ <title>The deal.II news page</title>
-<body>
- <h2>News on <acronym>deal.II</acronym></h2>
+ <link href="../screen.css" rel="StyleSheet">
- <p>
- This page lists news and announcements on
- <acronym>deal.II</acronym> in reverse chronological order. If you
- send us extensions to the library, please feel free to also send a
- patch to this file such that we can announce your contributions in
- your own words.
- </p>
+ <meta name="copyright" content="Copyright (C) 2000 - 2014 by the deal.II Authors">
+ <meta name="date" content="$Date$">
+ <meta name="keywords" content="deal.II">
+ <meta name="svn_id" content="$Id$">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <p>
- Please refer to the archive of the <a target="_top"
- href="http://www.dealii.org/mail.html">deal.II
- mailing list</a> for additional news.
- </p>
+ <meta http-equiv="refresh" content="0;url=http://dealii.org/news.html">
-
- <p>
- <dt><strong>Recent changes</strong></dt>
- <dd>
- Changes in the library since the last major release are
- <strong><a href="../doxygen/deal.II/changes_after_8_1.html">here.</a></strong>
- </dd>
- </p>
-
-
- <dl>
- <dt>
- <strong style="color:red">2013/12/24: Version 8.1 released</strong>
- </dt>
- <dd>
- deal.II version 8.1 was released today. A full list of changes can be
- found <a href="../doxygen/deal.II/changes_between_8_0_and_8_1.html"
- target="body">here</a>.
- <br>
- deal.II can be downloaded at
- <a href="https://code.google.com/p/dealii/downloads/list"
- target="_top">this site</a>.
- </dd>
-
- <dt>
- <strong>2013/12/18: step-26 for the heat equation </strong>
- </dt>
- <dd>
- step-26 fills a long-standing gap: There was no tutorial
- program solving the heat equation. There was also no tutorial
- showing in relatively easy terms how to do adaptive meshes
- in time dependent problems. This program fills both of these
- needs.
- </dd>
-
- <dt>
- <strong>2013/11/01: step-42 solves an elasto-plastic contact problem </strong>
- </dt>
- <dd>
- step-42, written by Jörg Frohne, Timo Heister and Wolfgang
- Bangerth, shows how to solve an elasto-plastic contact problem.
- The program is an extension of step-41 to a much more complex
- equation (nonlinear elasto-plasticity) and also demonstrates
- how to compute solutions for such problems in parallel.
- </dd>
-
- <dt>
- <strong>2013/10/01: step-51 implements an HDG method </strong>
- </dt>
- <dd>
- step-51, contributed by Martin Kronbichler and Scott Miller,
- implements a hybridized discontinuous Galerkin method for the scalar
- convection-diffusion equation. The method uses standard DG terms for
- describing the element interior but couples the local sub-problems
- using face elements. The local contribution is eliminated from the
- global linear system by a static condensation process.
- </dd>
-
- <dt>
- <strong style="color:red">2013/07/24: Version 8.0 released</strong>
- </dt>
- <dd>
- deal.II version 8.0 was released today. This is a major new
- release, featuring the conversion of the configuration and
- build system to <a href="http://www.cmake.org/">CMake</a>,
- support for parallel computations with more than 4 billion
- unknowns, and many more. A full list of changes can be
- found <a href="../doxygen/deal.II/changes_between_7_3_and_8_0.html"
- target="body">here</a>.
- <br>
- deal.II can be downloaded at
- <a href="https://code.google.com/p/dealii/downloads/list"
- target="_top">this site</a>.
- </dd>
-
- <dt>
- <strong>2013/06/05: 64-bit version of deal.II</strong>
- </dt>
- <dd>
- Because the global dof index variables in deal.II were of type
- unsigned int, it was not possible to create a dof_handler with more than
- 4.3 billions of unknowns. The 64-bit version of deal.II uses unsigned long
- long int and thus, allows for 18e18 unknowns.
- </dd>
-
-
- <dt>
- <strong>2013/03/07: Build system switched to CMake</strong>
- </dt>
- <dd>
- After having used Autoconf as the configuration and build system
- since the beginning of deal.II in 1997, we have now switched to
- <a href="http://www.cmake.org/">CMake</a>. This implementation,
- contributed by Matthias Maier of Heidelberg University, has taken
- more than half a year, consists of more than 10,000 lines, and
- touches every aspect of the installation process. It provides a more
- modern interface to and more reliable way of interacting with other
- packages. Furthermore, it no longer relies on shell scripts and
- therefore integrates more easily with integrated development
- environments as well as Microsoft Windows without Cygwin.
- </dd>
-
- <dt>
- <strong style="color:red">2013/02/27: Version 7.3 released</strong>
- </dt>
- <dd>
- Version 7.3.0 was released today. This release provides one new
- tutorial, work on parallel linear algebra, the new FE_Q_DG0 element,
- and a large number of enhancements and bug fixes throughout the
- entire library. A complete list of new features is
- found <a href="../doxygen/deal.II/changes_between_7_2_and_7_3.html"
- target="body">here</a>.
- </dd>
-
- <dt>
- <strong style="color:red">2012/09/03: Version 7.2 released</strong>
- </dt>
- <dd>
- Version 7.2.0 was released today. This release provides four
- new tutorial programs, a framework for matrix-free
- computations, and a large number of enhancements and bug fixes
- throughout the entire library. A complete list of new
- features is found <a
- href="../doxygen/deal.II/changes_between_7_1_and_7_2.html" target="body">here</a>.
- </dd>
-
-
- <dt>
- <strong>2012/06/06: step-43 — an efficient solver for
- two-phase flow</strong>
- </dt>
- <dd>
- The step-21 tutorial program was the first program in the
- deal.II tutorial to demonstrate the solution of two-phase flow
- problems, but it suffered from the fact that it was very
- slow. step-43 demonstrates some of the techniques that can be
- used to make solvers for such problems more efficient and
- accurate.
- </dd>
-
-
- <dt>
- <strong>2012/06/03: New step-15</strong>
- </dt>
- <dd>
- Step-15 used to be a program that demonstrated techniques for solving
- a rather quirky, nonlinear, 1d problem. It was an interesting problem,
- but it served little purpose in teaching deal.II or in demonstrating
- nonlinear solution techniques. It has now been replaced by a more
- illustrative example, contributed in large part by Sven Wetterauer, in
- which we solve the nonlinear elliptic minimal surface equation using a
- Newton iteration.
- </dd>
-
-
- <dt>
- <strong>2012/05/05: Matrix-free implementation framework</strong>
- </dt>
- <dd>
- A matrix-free framework has been contributed by Katharina
- Kormann and Martin Kronbichler. The implementation is memory
- efficient and includes parallelism via MPI for distributed
- meshes, threads for shared-memory computations, and usage of
- processors' vector units. The two new tutorial programs step-37
- (multigrid solver) and step-48 (nonlinear wave equation with
- distributed grid) demonstrate the new features.
- </dd>
-
-
- <dt>
- <strong>2012/04/02: step-44 — a finite strain
- elasticity solver</strong>
- </dt>
- <dd>
- step-44, contributed by Andrew McBride and Jean-Paul
- Pelteret, demonstrates one approach to modelling large
- deformations of nearly-incompressible elastic solids. The
- elastic response is governed by a non-linear, hyperelastic
- free-energy function. The geometrical response is also
- nonlinear, i.e., the program considers finite deformations.
- </dd>
-
-
- <dt>
- <strong>2012/04/02: step-41 solves the obstacle problem</strong>
- </dt>
- <dd>
- step-41, a program contributed by Jörg Frohne, shows
- how to solve the obstacle problem. This problem describes
- the deformation of a body subject to an inequality
- constraint that arises from the fact that the deformation is
- constrained by contact of the body with some external
- obstacle. The program uses the primal-dual active set method
- to solve this problem.
- </dd>
-
-
- <dt>
- <strong style="color:red">2011/10/09: Version 7.1 released</strong>
- </dt>
- <dd>
- Version 7.1.0 was released today. This release provides two
- new tutorial programs and many smaller enhancements
- throughout the entire library. A complete list of new
- features is found <a
- href="../doxygen/deal.II/changes_between_7_0_and_7_1.html" target="body">here</a>.
- </dd>
-
-
- <dt>
- <strong>2011/10/06: step-32, a massively parallel thermal
- convection solver</strong>
- </dt>
- <dd>
- Long in the making, the step-32 tutorial program
- demonstrates how to solve the Boussinesq equations
- describing thermal convection on large numbers of
- processors.
- </dd>
-
-
- <dt>
- <strong>2011/04/30: step-46 demonstrates coupling different models
- on different parts of the domain</strong>
- </dt>
- <dd>
- step-46 shows how to couple different models defined on subsets of
- the domain, in this case Stokes flow around an elastic solid. The
- trick here is that variables (here the flow velocity and pressure,
- and the solid displacement) do not live on the entire domain, but
- only on a part. The point of the program is how to represent this in
- source code.
- </dd>
-
-
- <dt>
- <strong style="color:red">2011/01/09: Version 7.0 released</strong>
- </dt>
- <dd>
- Version 7.0.0 was released today. This release is a huge step
- forward, with several significant new features such as support for
- thousands or tens of thousands of processors. A complete list of new
- features is found <a
- href="../doxygen/deal.II/changes_between_6_3_and_7_0.html" target="body">here</a>.
- </dd>
-
-
- <dt>
- <strong>2011/01/02: step-38 shows how to solve partial differential
- equations on curved manifolds</strong>
- </dt>
- <dd>
- The new step-38 program, contributed by Andrea Bonito and M. Sebastian
- Pauletti, shows how to discretize and solve partial differential
- equations posed on curved manifolds embedded in higher dimensional
- spaces.
- </dd>
-
- <dt>
- <strong>2010/12/20: Graphical frontend to edit parameter files</strong>
- </dt>
- <dd>
- Contributed by Martin Steigemann, deal.II now has Qt based graphical
- user interface to edit input parameter files for
- the <code>ParameterHandler</code> class. The executable is located in
- <code>lib/bin/dealii_parameter_gui</code>.
- </dd>
-
- <dt>
- <strong>2010/10/25: New directory and library structure</strong>
- </dt>
- <dd>
- deal.II has had a somewhat quirky directory and library structure for
- historical reasons, but this has now changed: All include and source
- files are now under the top-level <code>include/</code>
- and <code>source</code> directories. Furthermore, we no longer build a
- plethora of libraries but only <code>libdeal_II.g.so</code> (debug
- version) and <code>libdeal_II.so</code> (optimized version). In
- particular, we no longer build different versions of the library for
- different space dimensions.
- </dd>
-
- <dt>
- <strong>2010/10/23: Distributed mesh functionality available</strong>
- </dt>
- <dd>
- After more than 2 years of work by Timo Heister, Martin Kronbichler,
- and Wolfgang Bangerth, and with help by Carsten Burstedde, we have
- merged a branch on which we have implemented the functionality
- necessary to distribute meshes on hundreds, thousands, or more
- processors. An overview of the framework
- in which this is implemented is presented in a documentation module,
- an accompanying paper, as well as in the new step-40 tutorial program.
- </dd>
-
- <dt>
- <strong style="color:red">2010/07/18: Version 6.3.1 released</strong>
- </dt>
- <dd>
- Version 6.3.1 was released today. This release addresses a number of
- problems in release 6.3.0 related to compatibility with certain
- compilers, operating systems, and versions of external libraries.
- A list of changes between
- versions 6.3.0 and 6.3.1 can be found <a
- href="../doxygen/deal.II/changes_between_6_3_0_and_6_3_1.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2010/06/25: deal.II on Facebook</strong>
- </dt>
- <dd>
- We built a facebook page titled <b>deal.II</b> today. Please, feel free
- to join us there!
- </dd>
-
- <dt>
- <strong style="color:red">2010/06/25: Version 6.3 released</strong>
- </dt>
- <dd>
- Version 6.3.0 was released today, containing several new
- tutorial programs, a new threading framework and a framework
- for assembling linear systems by just providing the local integrals.
- A complete list of changes between
- versions 6.2.0 and 6.3.0 can be found <a
- href="../doxygen/deal.II/changes_between_6_2_and_6_3.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2010/06/24: step-39 solves Poisson's equation with
- the interior penalty discontinuous Galerkin method on
- adaptively refined meshes with multigrid</strong>
- </dt>
- <dd>
- Using the MeshWorker framework, this program highlights the
- fact that loops over meshes are very generic and that
- building matrices and level matrices and evaluating error
- estimates are really the same task.
- </dd>
-
- <dt>
- <strong> 2010/06/24: The Meshworker framework has been released</strong>
- </dt>
- <dd>
- Using its generic loop and the provided auxiliary classes,
- this framework relieves the application programmer from coding
- loops over cells, faces, and subfaces, such that focus can remain
- on implementation of the local integrals.
- </dd>
-
- <dt>
- <strong>2010/06/23: step-45 shows periodic boundary
- conditions</strong>
- </dt>
- <dd>
- Contributed by Markus Bürg, the new tutorial program step-45
- demonstrates an often requested feature: periodic boundary
- conditions.
- </dd>
-
-
- <dt>
- <strong>2010/02/13: New multigrid, new step-16</strong>
- </dt>
- <dd>
- Over the last few months, the multigrid implementation has seen
- significant rewrites, with much of the work done by Bärbel
- Janssen. The goal — now achieved — was to finally fully
- support multigrid also for continuous finite elements on adaptively
- refined meshes (uniformly refined meshes and discontinuous elements
- have worked for a long time). As part of this process, step-16 has
- been rewritten and now solves the same problem step-6 solves, just
- with a multigrid solver.
- </dd>
-
-
- <dt>
- <strong>2009/10/07: step-35 shows the solution of the
- Navier-Stokes equations</strong>
- </dt>
- <dd>
- Step-35, a tutorial program contributed by Abner
- Salgado-Gonzalez, shows an implementation of a projection
- scheme for the numerical solution of the Navier-Stokes
- equations.
- </dd>
-
-
- <dt>
- <strong>2009/07/30: New tutorial program step-36</strong>
- </dt>
- <dd>
- The new step-36 tutorial program, contributed by Toby D. Young and
- Wolfgang Bangerth, shows how to solve eigenvalue problems, using the
- Schrödinger equation as an example.
- </dd>
-
-
- <dt>
- <strong style="color:red">2009/06/05: Version 6.2.1 released</strong>
- </dt>
- <dd>
- deal.II version 6.2.0 contained a couple of minor but
- annoying bugs in its interaction with PETSc. The
- documentation package also did not include any typeset
- formulas. Release 6.2.1 corrects these mistakes.
- A complete list of changes between
- versions 6.2.0 and 6.2.1 can be found <a
- href="../doxygen/deal.II/changes_between_6_2_0_and_6_2_1.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong style="color:red">2009/04/27: Version 6.2 released</strong>
- </dt>
- <dd>
- Version 6.2.0 was released today!
- A complete list of changes between
- versions 6.1.0 and 6.2.0 can be found <a
- href="../doxygen/deal.II/changes_between_6_1_and_6_2.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2009/04/14: New tutorial program step-34</strong>
- </dt>
- <dd>
- step-34, written by Luca Heltai, demonstrates the ability of
- deal.II to discretize and solve boundary integral equations
- on curved manifolds.
- </dd>
-
-
- <dt>
- <strong>2008/12/05: Support for meshes embedded in
- higher dimensions</strong>
- </dt>
- <dd>
- Based on work by Cataldo Manigrasso and Luca Heltai
- developed over the last few months on a branch, deal.II now
- supports meshes that are embedded in higher space
- dimensions. This allows, for example, to solve equations on
- the surface of a sphere (e.g. to use boundary element
- methods for exterior problems).
- </dd>
-
-
- <dt>
- <strong>2008/11/14: New tutorial program step-31</strong>
- </dt>
- <dd>
- The latest tutorial program, step-31, is contributed by
- Martin Kronbichler and Wolfgang Bangerth and shows the
- solution of the Boussinesq approximation to thermally driven
- convection in an incompressible fluid.
- </dd>
-
-
- <dt>
- <strong>2008/09/10: New tutorial program step-28</strong>
- </dt>
- <dd>
- step-28, contributed by Yaqi Wang, illustrates the solution
- of a coupled system of diffusion equations relevant to
- nuclear reactor physics where we use different meshes for
- different components of a vector-valued solution.
- </dd>
-
-
- <dt>
- <strong>2008/08/21: <acronym>deal.II</acronym> now exceeds
- of 400,000 lines of code</strong>
- </dt>
- <dd>
- Since today, <acronym>deal.II</acronym> has more than 400,000
- lines of code. The rate of growth continues to be close on
- par with the 3000 lines of code per month that we have had
- over many years already, with no signs of abating activity!
- </dd>
-
-
- <dt>
- <strong>2008/07/08: Support for anisotropic mesh refinement</strong>
- </dt>
- <dd>
- Contributed by Tobias Leicht as well as Ralf Hartmann, deal.II
- now supports anisotropic refinement of meshes. This functionality
- is explained in the step-30 tutorial program.
- </dd>
-
-
- <dt>
- <strong style="color:red">2008/05/28: Version 6.1 released</strong>
- </dt>
- <dd>
- Version 6.1.0 was released today!
- A complete list of changes between
- versions 6.0.0 and 6.1.0 can be found <a
- href="../doxygen/deal.II/changes_between_6_0_and_6_1.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2008/05/23: step-33 illustrates the Euler equations</strong>
- </dt>
- <dd>
- <a href="../doxygen/deal.II/step_33.html">step-33</a>,
- a tutorial program written mostly by David Neckels, illustrates how
- the Euler equations of compressible inviscid gas dynamics can be
- solved. More generally, the program also provides a framework for
- the solution of arbitrary hyperbolic, nonlinear conservation laws.
- </dd>
-
- <dt>
- <strong>2008/03/28: step-22 demonstrates solving the Stokes
- equations</strong>
- </dt>
- <dd>
- The new <a href="../doxygen/deal.II/step_22.html">step-22</a>
- tutorial program, written by Martin Kronbichler and Wolfgang
- Bangerth, shows how to solve, and in particular how to solve
- efficiently, the Stokes equations that describe viscous
- incompressible fluid flow.
- </dd>
-
- <dt>
- <strong>2007/10/31: step-29 tutorial program added</strong>
- </dt>
- <dd>
- Contributed by Moritz Allmaras, the <a
- href="../doxygen/deal.II/step_29.html">step-29</a> tutorial program
- explains how problems involving complex numbers can be treated in
- <acronym>deal.II</acronym>. In the example,
- the complex-valued solution to a Helmholtz equation is split into
- real and imaginary parts and a vector-valued finite element field
- is used to discretize them seperately. The program also demonstrates
- how quantities derived from the finite element solution can be directly
- included in the output by using the new <code>DataPostprocessor</code>
- class.
- </dd>
-
- <dt>
- <strong style="color:red">2007/09/07: Version 6.0 released</strong>
- </dt>
- <dd>
- Version 6.0.0 was released today!
- A complete and long list of changes between
- versions 5.2.0 and 6.0.0 can be found <a
- href="5.2.0-vs-6.0.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2007/08/09: step-27 demonstrates hp technology</strong>
- </dt>
- <dd>
- The new <a href="../doxygen/deal.II/step_27.html">step-27</a>
- tutorial program finally demonstrates how to use the
- hp finite element technology that has been part of deal.II for some
- 18 months now. It solves a Laplace equation with hp finite elements
- and shows how to set finite element degrees, assemble matrices on
- cells with varying polynomial degrees, and how to compute a simple
- criterion for estimating the local Sobolev smoothness of a function.
- </dd>
-
- <dt>
- <strong>2007/07/16: Wilkinson Prize</strong>
- </dt>
- <dd>
- The principal authors of <acronym>deal.II</acronym>—Wolfgang
- Bangerth, Ralf Hartmann and Guido Kanscht—have received the <a
- href="http://www.mcs.anl.gov/WilkinsonPrize/">J. H. Wilkinson
- Prize for Numerical Software</a> for their creation of and work on
- the deal.II library. The prize committee particularly noted the
- reliability and usability of the software and the quality of the
- documentation.
- <p>
- We want to take the opportunity to thank our user community for their
- support over the years that kept us working on this software. We
- consider this award motivation to continue this work!
- </dd>
-
- <dt>
- <strong>2007/02/09: Support for previously unorientable meshes</strong>
- </dt>
- <dd>
- Up to now, in 3D only 'orientable' meshes could be used in
- deal.II, where all lines are in standard orientation and the
- faces can be either in standard orientation or with a
- reversed normal. This has been generalized such that now all
- hexahedral meshes can be used.
- </dd>
-
- <dt>
- <strong>2006/10/30: step-21 is finished</strong>
- </dt>
- <dd>
- Step-21 demonstrates the time dependent flow of a multiphase fluid
- through a porous medium. It is an extension of step-20, using a mixed
- formulation and block solvers.
- </dd>
-
- <dt>
- <strong>2006/10/03: step-23/24/25 are finished</strong>
- </dt>
- <dd>
- The step-23, step-24 and step-25 tutorial programs have been added,
- demonstrating how to solve the time dependent wave equation
- and a nonlinear variant of it, the sine-Gordon equation.
- </dd>
-
- <dt>
- <strong>2006/08/24: <acronym>deal.II</acronym> is now part of the
- SPEC CPU 2006 benchmark</strong>
- </dt>
- <dd>
- A modified version of the <acronym>deal.II</acronym> library and the
- step-14 tutorial program has been incorporated into the industry
- standard <a href="http://www.spec.org/cpu2006/" target="_top">SPEC CPU 2006</a>
- benchmark testsuite that is used to determine the speed of
- computers. It is part of the floating point testsuite <a
- href="http://www.spec.org/cpu2006/CFP2006/" target="_top">CFP2006</a> as benchmark
- <a
- href="http://www.spec.org/cpu2006/Docs/447.dealII.html" target="_top">447.dealII</a>.
- <p>
- The inclusion of our software into an industry
- standard benchmark testsuite will lead to better support of compilers
- and machines for the kind of program we write, in particular for
- unstructured hierarchical mesh computations. This will in turn
- help make our codes run faster on future systems.
- </dd>
-
- <dt>
- <strong>2006/2/12: step-20 is finished</strong>
- </dt>
- <dd>
- The new step-20 tutorial program shows how to use Raviart-Thomas
- elements to solve a mixed formulation of the Laplace equation. It
- also demonstrates the use of block matrices and vectors, and how they
- can be used to define more complex solvers and preconditioners
- working on the Schur complement.
- </dd>
-
- <dt>
- <strong>2006/1/3-5: First User Workshop</strong>
- </dt>
- <dd>
- After 8 years of existence, it was time to have the first user
- meeting. During a 3-day workshop held in Heidelberg, topics of
- software development, use of deal.II for applications, and future
- directions were discussed by about a dozen developers and users.
- </dd>
-
- <dt>
- <strong>2005/12/20: hp functionality merged</strong>
- </dt>
- <dd>
- After the code had been developed and maintained on a branch for 3
- years by Oliver Kayser-Herold and Wolfgang Bangerth, it has now been
- merged into the main development, and will be available for the next
- release.
- </dd>
-
- <dt>
- <strong style="color:red">2005/09/17: Version 5.2 released</strong>
- </dt>
- <dd>
- Version 5.2.0 was released today!
- A complete and long list of changes between
- versions 5.1.0 and 5.2.0 can be found <a
- href="5.1.0-vs-5.2.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2005/09/09: Two more tutorial programs</strong>
- </dt>
- <dd>
- Two more tutorial programs, step-18 and step-19, are now
- available. step-18 shows how to solve time-dependent but quasi-static
- elasticity programs in parallel. step-19 demonstrates some data
- handling and parameter file techniques.
- </dd>
-
- <dt>
- <strong>2005/03/29: <acronym>deal.II</acronym> now has a Wiki</strong>
- </dt>
- <dd>
- Hosted by Luca Heltai, there is now a wiki. See the link from the
- <acronym>deal.II</acronym> front page. Users of
- <acronym>deal.II</acronym> are encouraged to visit it, and,
- as is usual with wikis, edit pages freely and post their
- experiences and code snippets they want others to know about.
- </dd>
-
- <dt>
- <strong>2005/03/07: Function parser library integrated</strong>
- </dt>
- <dd>
- Luca Heltai has contributed code that integrates a third
- party <a
- href="http://warp.povusers.org/FunctionParser/">function
- parser library</a>) that takes a string describing a
- mathematical function, and returns an object that can be used in
- all places where function objects are used in deal.II.
- </dd>
-
- <dt>
- <strong style="color:red">2004/12/24: Version 5.1 released</strong>
- </dt>
- <dd>
- Version 5.1.0 was released today!
- A complete and long list of changes between
- versions 5.0.0 and 5.1.0 can be found <a
- href="5.0.0-vs-5.1.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2004/10/21: Q<sub>r</sub> elements of arbitrary order now
- support hanging node constraints also in 3d</strong>
- </dt>
-
- <dd>
- Lagrange elements previously had hanging node constraint matrices
- hard coded in 3d, which were only available for r=1,2. Thanks to
- code written by Oliver Kayser-Herold, this information is now
- computed on-the-fly, which allows the use of Lagrange elements of
- arbitrary order also in 3d on meshes with hanging nodes.
- </dd>
-
- <dt>
- <strong>2004/05/25: Version 5.0 released</strong>
- </dt>
- <dd>
- Version 5.0.0 was released today!
- A complete and long list of changes between
- versions 4.0.0 and 5.0.0 can be found <a
- href="4.0.0-vs-5.0.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2004/03/08: Interfaces to PETSc and METIS</strong>
- </dt>
- <dd>
- In order to support parallel computations, we now have interfaces to
- both the PETSc library for sequential and parallel linear algebra,
- as well as to the METIS library for domain partitioning.
- </dd>
-
- <dt>
- <strong>2004/03/08: MIPSpro compiler version 7.41 supported</strong>
- </dt>
- <dd>
- deal.II now also supports compilation on SGIs by the MIPSpro
- compiler version 7.41.
- </dd>
-
- <dt>
- <strong>2003/06/06: Version 4.0 released</strong>
- </dt>
- <dd>
- After one year, we made it and released Version 4.0.0 today!
- A complete list of changes between
- versions 3.4.0 and 4.0.0 can be found <a
- href="3.4.0-vs-4.0.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2003/04/27: <acronym>deal.II</acronym> now exceeds
- of 200,000 lines of code</strong>
- </dt>
- <dd>
- Since today, <acronym>deal.II</acronym> has now more than 200,000
- lines of code. The rate of growth continues to be close to
- 3000 lines of code per month.
- </dd>
-
- <dt>
- <strong>2003/01/24: deal.II runs on AIX 5.1</strong>
- </dt>
- <dd>
- Using gcc3.2, deal.II can now also be compiled on AIX systems
- with the PowerPC chip.
- </dd>
-
- <dt>
- <strong>2002/12/18: deal.II runs on Mac OS X 10.2</strong>
- </dt>
- <dd>
- Some changes have been made to allow compiling and running deal.II on
- Mac OS X 10.2 systems.
- </dd>
-
- <dt>
- <strong>2002/12/05: Intel ICC 7.0 compiler supported</strong>
- </dt>
- <dd>
- deal.II now also supports compilation by the recently released
- Intel icc 7.0 compiler.
- </dd>
-
- <dt>
- <strong>2002/06/28: deal.II 64-bit ready</strong>
- </dt>
- <dd>
- deal.II also runs on 64-bit systems without changes, as
- tests on a Sparc machine with Solaris 9 in 64-bit mode have
- shown. We also have reports of people running deal.II on
- IA64 systems.
- </dd>
-
- <dt>
- <strong>2002/06/06: Version 3.4 released</strong>
- </dt>
- <dd>
- Today, version 3.4 of the <acronym>deal.II</acronym> library
- has been released. A complete list of changes between
- versions 3.3.0 and 3.4.0 can be found <a
- href="2002/3.3.0-vs-3.4.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2002/05/22: Intel ECC Itanium compiler now supported</strong>
- </dt>
- <dd>
- <code>aclocal.m4</code> has been changed to detect the Intel ECC
- compiler for Itanium systems. The ECC compiler can produce
- optimized code for Intel's new IA-64 architecture.
- </dd>
-
- <dt>
- <strong>2002/03/07: New web home www.dealii.org and new
- email addresses</strong>
- </dt>
- <dd>
- The <acronym>deal.II</acronym> homepage has been moved to <a
- href="http://www.dealii.org"
- target="_top">www.dealii.org</a>. Also the <a
- href="../mail.html">email addresses</a> have been
- changed. Though the old web home and the old addresses will
- be supported for some time we recommend to adjust the
- bookmarks and mail addresses accordingly.
- </dd>
-
- <dt>
- <strong>2002/02/01: Version 3.3 released</strong>
- </dt>
- <dd>
- Today, version 3.3 of the <acronym>deal.II</acronym> library
- has been released. A complete list of changes between
- versions 3.2.0 and 3.3.0 can be found <a
- href="2002/3.2.0-vs-3.3.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2002/01/31: <acronym>deal.II</acronym> now consists
- of 160,000 lines of code</strong>
- </dt>
- <dd>
- All <code>.cc</code> and <code>.h</code> files of
- <acronym>deal.II</acronym> now sum up to more than 160,000(!)
- lines of code. <acronym>deal.II</acronym> continues to grow
- with a rate almost constant at 3000 lines of code per month.
- </dd>
-
- <dt>
- <strong>2001/09/28: Version 3.2 released</strong>
- </dt>
- <dd>
- After a long phase of implementation and testing, we today
- released version 3.2 of the <acronym>deal.II</acronym>
- library. There are many changes between version 3.1 and
- release 3.2. A complete list of these changes can be found
- <a href="2001/3.1.0-vs-3.2.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2001/07/06: Compaq's cxx compiler supported</strong>
- </dt>
- <dd>
- The present development version now also supports
- compilation by Compaq's cxx compiler. See the <a
- href="../readme.html#prerequisites" target="body">ReadMe</a>
- file for more information on using this compiler.
- </dd>
-
- <dt>
- <strong>2001/06/28: deal.II 3.1.2 released</strong>
- </dt>
- <dd>
- Version 3.1.2 is a bug-fix release based on 3.1. A list of
- changes between the two versions can be found on
- <a href="2001/3.1.1-vs-3.1.2.html" target="body">this
- page</a>.
- </dd>
-
- <dt>
- <strong>2001/05/23: Intel ICC compiler supported</strong>
- </dt>
- <dd>
- The present development version of the library is now fixed
- so that it can also be compiled by
- Intel's ICC C++ compiler for Linux.
- </dd>
-
- <dt>
- <strong>2001/05/17: deal.II 3.1.1 released</strong>
- </dt>
- <dd>
- Version 3.1.1 is a bug-fix release based on 3.1. A list of
- changes between the two versions can be found on
- <a href="2001/3.1.0-vs-3.1.1.html" target="body">this
- page</a>.
- </dd>
-
- <dt>
- <strong>2001/02/26: Support for Subroutines from the Harwell Subroutine
- Library (HSL)</strong>
- </dt>
- <dd>
- The <a href="http://www.hsl.rl.ac.uk/"
- target="_top">Harwell Subroutine Library (HSL)</a> is a
- library that, among much other functionality, offers some
- sparse direct solvers. We have added support for an
- interface to these solvers to the library.
- </dd>
-
- <dt>
- <strong>2001/02/20: Version 3.1 released</strong>
- </dt>
- <dd>
- After a long testing phase, we today released version 3.1 of
- the <acronym>deal.II</acronym> library.
- There are many changes between version 3.0 and release
- 3.1. A complete list of these changes can be found
- <a href="2000/3.0.0-vs-3.1.0.html" target="body">here</a>.
- </dd>
-
- <dt>
- <strong>2000/08/07: deal.II 3.0.1</strong>
- </dt>
- <dd>
- Version 3.0.1 is a bug-fix release based on 3.0. A list of
- changes between the two versions can be found on
- <a href="2000/3.0.0-vs-3.0.1.html" target="body">this
- page</a>.
- (<a href="2000/03.html" target="body">Announcement</a>)
- </dd>
-
- <dt>
- <strong>2000/04/13: deal.II 3.0 announced</strong>
- </dt>
- <dd>
- Today, after 2½ years of development and testing, the
- first public release of the <acronym>deal.II</acronym>
- library was announced (<a href="2000/01.html"
- target="body">full text</a>).
- </dd>
- </dl>
-
-
-</body>
+ </head>
+
+ <body>
+ This page is now part of the top-level project description. See
+ <a target="_top" href="http://dealii.org/news.html">this page</a>.
+ </body>
</html>
li { margin-bottom: 1ex; }
</style>
</head>
- <body>
-
-
- <h1>Publications on and with <acronym>deal.II</acronym></h1>
-
- <p>
- Our institutes are evaluated at regular intervals. Consequently,
- we are interested in documenting the use of the programs and
- libraries we create. To this end, this page collects
- publications written on or with the help of
- <acronym>deal.II</acronym>. If you have written
- something, please let us know about it: the more comprehensive this
- list is, the simpler it is for us to justify to our departments and
- sponsors the effort we put into the library — something that helps all
- of us in the end.
- </p>
-
- <p align="left">
- <table class="tutorial">
- <tr>
- <th><b><small>Table of contents</small></b></th>
- </tr>
-
- <tr>
- <td valign="top">
- <ol>
- <li> <a href="#referencing"
- >Referencing <acronym>deal.II</acronym></a>
- <li> <a href="#details">Publications on details
- of <acronym>deal.II</acronym></a>
- <li> Publications per year:<br>
- <a href="#2010">2010</a>
- <a href="#2011">2011</a>
- <a href="#2012">2012</a>
- <a href="#2013">2013</a>
- <br>
- <a href="#2000">2000</a>
- <a href="#2001">2001</a>
- <a href="#2002">2002</a>
- <a href="#2003">2003</a>
- <a href="#2004">2004</a>
- <a href="#2005">2005</a>
- <a href="#2006">2006</a>
- <a href="#2007">2007</a>
- <a href="#2008">2008</a>
- <a href="#2009">2009</a>
- <br>
- <a href="#1998">1998</a>
- <a href="#1999">1999</a>
- </ol>
- </td>
- </tr>
- </table>
-
-
- <a name="referencing"> </a>
- <h2>Referencing <acronym>deal.II</acronym></h2>
-
- <p>
- If you write a paper using results obtained with the help of
- <acronym>deal.II</acronym>, please cite one or both of the following
- references:
- </p>
-
- <ol>
- <li>
- Wolfgang Bangerth, Timo Heister, Luca Heltai, Guido Kanschat, Martin Kronbichler, Matthias Maier, and Toby D. Young <br/>
- <strong>The <acronym>deal.II</acronym> Library, Version 8.1
- </strong>
- <br>
- <a href="http://arxiv.org/abs/1312.2266v4" target="_top">arxiv:1312.2266v4</a>, 2013.
- <br>
-<pre>
-@article{dealII81,
- title = {The {\tt deal.{I}{I}} Library, Version 8.1},
- author = {W. Bangerth and T. Heister and L. Heltai and G. Kanschat
- and M. Kronbichler and M. Maier and B. Turcksin and T. D. Young},
- journal = {arXiv preprint \url{http://arxiv.org/abs/1312.2266v4}},
- year = {2013},
-}
-</pre>
- </li>
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a> and
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>
- deal.II — a general-purpose object-oriented finite element library
- </strong>
- <br>
- ACM Transactions on Mathematical Software, vol. 33, no. 4, article 24
- <br>
- DOI <a href="http://doi.acm.org/10.1145/1268776.1268779">10.1145/1268776.1268779</a>
- (<a
- href="http://www.isc.tamu.edu/publications-reports/tr/0602.pdf">Preprint</a>)
- <br>
-<pre>
-@Article{BangerthHartmannKanschat2007,
- author = {W. Bangerth and R. Hartmann and G. Kanschat},
- title = {{deal.II} -- a General Purpose Object Oriented Finite Element Library},
- journal = {ACM Trans. Math. Softw.},
- year = 2007,
- volume = 33,
- number = 4,
- pages = {24/1--24/27}
-}
-</pre>
- </li>
- </ol>
-
- <p>
- For your convenience, we provide a <a href="dealii.bib">BibTeX file</a> with entries
- for the publications in this section.
- </p>
-
-
- <h4>Older Releases</h4>
-
- <ol>
- <li>
- Wolfgang Bangerth, Timo Heister, Luca Heltai, Guido Kanschat, Martin Kronbichler, Matthias Maier, and Toby D. Young <br/>
- <strong>The <acronym>deal.II</acronym> Library, Version 8.0
- </strong>
- <br>
- <a href="http://arxiv.org/abs/1312.2266v3" target="_top">arxiv:1312.2266v3</a>, 2013.
- <br>
-<pre>
-@article{dealII80,
- title = {The {\tt deal.{I}{I}} Library, Version 8.0},
- author = {W. Bangerth and T. Heister and L. Heltai and G. Kanschat
- and M. Kronbichler and M. Maier and B. Turcksin and T. D. Young},
- journal = {arXiv preprint \url{http://arxiv.org/abs/1312.2266v3}},
- year = {2013},
-}
-</pre>
- </li>
- </ol>
-
-
- <!-- check on Freddi papers, conference at http://www.eurosim2007.org -->
- <!-- watch for the papers here -->
- <!-- http://www-sop.inria.fr/tosca/personnel/Claire.Chauvin/ to appear -->
- <!-- check GAKUTO (and possibly other papers by Natalini at
- http://www.iac.cnr.it/~natalini/papers.html -->
-
- <!-- Check Martin Steigemann papers
- http://www.martin-steigemann.net/index_uni_kassel.html
- Pieter Ghysels
- R. Ziegler -->
-
- <a name="details"> </a>
- <h4>Publications on details of <acronym>deal.II</acronym></h4>
-
- <p>
- The following publications explain in great detail the
- implementation of algorithms and data structures of the hp, multigrid,
- distributed mesh, and matrix-free components of deal.II:
- </p>
-
- <ol>
- <li>
- B. Janssen,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>,
- <br>
- <strong>Adaptive Multilevel Methods with Local Smoothing for H<sup>1</sup>-
- and H<sup>curl</sup>-Conforming High Order Finite Element Methods</strong>
- <br>
- SIAM J. Sci. Comput., vol. 33/4, pp. 2095-2114, 2011
- <br>
- DOI: <a href="http://dx.doi.org/10.1137/090778523">10.1137/090778523</a>
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- <a href="http://users.ices.utexas.edu/~carsten/"
- target="_top">C. Burstedde</a>,
- T. Heister,
- M. Kronbichler
- <br>
- <strong>Algorithms and Data Structures for Massively Parallel Generic
- Finite Element Codes</strong>
- <br>
- ACM Trans. Math. Softw., vol. 38, pp. 14/1-28, 2011.
- <br>
- DOI: <a href="http://dx.doi.org/10.1145/2049673.2049678">10.1145/2049673.2049678</a>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, O. Kayser-Herold,
- <br>
- <strong>Data Structures and Requirements for hp Finite Element
- Software
- </strong>
- <br>
- ACM Trans. Math. Softw., vol. 36, pp. 4/1-31, 2009
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Multi-level methods for discontinuous Galerkin FEM on locally refined meshes</strong>
- <br>
- Comput. & Struct., vol. 82, pp. 2437-2445, 2004
- </li>
-
- <li> M. Kronbichler, K. Kormann
- <br>
- <strong>A generic interface for parallel cell-based finite element
- operator application
- </strong>
- <br>
- Computers and Fluids, vol. 63, pp. 135-147, 2012
- <br>
- DOI: <a href="http://dx.doi.org/10.1016/j.compfluid.2012.04.012">10.1016/j.compfluid.2012.04.012</a>
- </li>
-
- <li> W. Bangerth, T. Heister
- <br>
- <strong>What makes computational open source software libraries successful?</strong>
- <br>
- Computational Science & Discovery, vol. 6, article 015010, 2013.
- </li>
- </ol>
-
- <p> For massively parallel
- computations, <acronym>deal.II</acronym> builds on the
- <a href="http://www.p4est.org/" target="_top">p4est</a>
- library. If you use this functionality, please also cite the
- p4est paper listed at their website.
- </p>
- <p>
- <acronym>deal.II</acronym> is a component of the <a
- href="http://www.spec.org/cpu2006/">SPEC CPU2006</a> benchmark
- suite. There are hundreds of papers that use and describe this
- testsuite as a reference for compiler and hardware
- optimizations. The following special issue gives a detailed
- comparison with respect to many different metrics of the
- benchmarks in SPEC CPU2006, including <acronym>deal.II</acronym>:
- <ul>
- <li>
- <strong>Special Issue: SPEC CPU2006 analysis (Editor: John Henning)
- </strong>
- <br>
- ACM SIGARCH Computer Architecture News, vol. 35, issue 1, 2007.
- </li>
- </ul>
-
-
-
- <a name="2014"> </a>
- <h2>Publications in 2014</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> A. Bertei, C.-C. Chueh, J. Pharoah, C. Nicolella
- <br>
- <strong>Modified Collective Rearrangement Sphere-assembly Algorithm for Random Packings of Nonspherical Particles: Towards Engineering Applications
- </strong>
- <br>
- Powder Technology, vol. 253, pp. 311-324, 2014.
- </li>
-
- <li> C.-C. Chueh, A. Bertei, J. Pharoah, C. Nicolella
- <br>
- <strong>Effective Conductivity in Random Porous Media with Convex and Non-Convex Porosity
- </strong>
- <br>
- International Journal of Heat and Mass Transfer, vol. 71, pp. 183-188, 2014.
- </li>
-
- <li>
- M. Hintermüller, A. Schiela, W. Wollner
- <br>
- <strong>The length of the primal-dual path in
- Moreau-Yosida-based path-following for state constrained
- optimal control
- </strong>
- <br>
- SIAM J. Optim., vol. 24, pp. 108-126, 2014.
- </li>
-
- <li> T. Wick, G. Singh, M.F. Wheeler
- <br>
- <strong>Pressurized-Fracture propagation using a phase-field approach coupled to a reservoir simulator
- </strong>
- <br>
- SPE 168597-MS, SPE HFTC Proc., 2014.
- </li>
-
- <li> M.F. Wheeler, T. Wick, W. Wollner
- <br>
- <strong>An Augmented-Lagrangian Method for the Phase-Field Approach for
-Pressurized Fractures
- </strong>
- <br>
- Comput. Methods Appl. Mech. Engrg., vol. 271, pp. 69-85, 2014.
- </li>
-
- <li> J. Willems
- <br>
- <strong>Robust Multilevel Methods for General Symmetric Positive Definite Operators
- </strong>
- <br>
- SIAM J. Numer. Anal. 52 (2014), no. 1, 103-124.
- </li>
-
- </ol>
-
-
- <a name="2013"> </a>
- <h2>Publications in 2013</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> M. Alexe, A. Sandu
- <br>
- <strong>Space-time adaptive solution of inverse problems with the
- discrete adjoint method
- </strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> G. Alam
- <br>
- <strong>Fast iterative solution of large scale statistical
- inverse problems
- </strong>
- <br>
- Master Thesis, Stockholm University, 2013.
- </li>
-
- <li> J. C. Araujo-Cabarcas
- <br>
- <strong>Numerical methods for glacial isostatic adjustment models
- </strong>
- <br>
- MSc thesis, Uppsala University, Uppsala, Sweden, 2013.
- </li>
-
- <li> P. Argul, G. Ruocci, F. Freddi, K. Benzarti
- <br>
- <strong>An improved damage modelling to deal with the variability of
- fracture mechanisms in FRP reinforced concrete structures
- </strong>
- <br>
- International Journal of Adhesion and Adhesives 45 , 7-20, 2013.
- </li>
-
- <li> D. Arndt
- <br>
- <strong>Augmented Taylor-Hood Elements for Incompressible Flow
- </strong>
- <br>
- Msc thesis, University of Göttingen, Germany, 2013.
- </li>
-
- <li> O. Axelsson, P. Boyanova, M. Kronbichler, M. Neytcheva, X. Wu
- <br>
- <strong>Numerical and computational efficiency of solvers for
- two-phase problems
- </strong>
- <br>
- Comput. Math. Appl., 65, 301-314, 2013.
- </li>
-
- <li> A. Barker, T. Rees, M. Stoll
- <br>
- <strong>A fast solver for an H<sub>1</sub> regularized
- PDE-constrained optimization problem</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> W. Bangerth, T. Heister
- <br>
- <strong>What makes computational open source software libraries successful?</strong>
- <br>
- Computational Science & Discovery, vol. 6, article 015010, 2013.
- </li>
-
- <li> S. Bartels, R. H. Nochetto, A. J. Salgado
- <br>
- <strong>A total variation diminishing interpolation operator
- and applications</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> P. Benner, M. Stoll
- <br>
- <strong>Optimal control for Allen-Cahn equations enhanced by model predictive control</strong>
- <br>
- Preprint, MPI Magdeburg, 2013.
- </li>
-
-
- <li> A. Bonito, D. Devaud
- <br>
- <strong>Adaptive Finite Element Methods for the Stokes Problems with Discontinuous Coefficients</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> A. Bonito, R. DeVore, R. H. Nochetto
- <br>
- <strong>Adaptive Finite Element Methods for Elliptic Problems with Discontinuous Coefficients</strong>
- <br>
- SIAM J. Numer. Anal. 51 (2013), no. 6, 3106-3134.
- </li>
-
- <li> A. Bonito, R. Glowinski
- <br>
- <strong>On the Nodal Set of the Eigenfunctions of the Laplace-Beltrami Operator for Bounded Surfaces in R3: A Computational Approach</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> A. Bonito, J.-L. Guermond, S. Lee
- <br>
- <strong>Two Modified Pressure-Correction Projection Methods for the Time-Dependent Stokes Equations</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> A. Bonito, I. Kyza, R. H. Nochetto
- <br>
- <strong>A dG Approach to Higher Order ALE Formulations in Time
- </strong>
- <br>
- 2012 Barrett Lectures, The IMA Volume in Mathematics and its Applications, Vol. 157, 36 pages, 2013, Springer.
- </li>
-
- <li> A. Bonito, I. Kyza, R. H. Nochetto
- <br>
- <strong>Time-discrete higher order ALE formulations: A
- priori error analysis</strong>
- <br>
- Numer. Math., 23 pages, 2013, 10.1007/s00211-013-0539-3.
- </li>
-
- <li> A. Bonito, I. Kyza, R. H. Nochetto
- <br>
- <strong>Time-discrete higher order ALE formulations: Stability</strong>
- <br>
- SIAM J. Numer. Anal., 51(1), 577-608, 2013.
- </li>
-
- <li> A. Bonito, J. E. Pasciak
- <br>
- <strong>Numerical Approximation of Fractional Powers of Elliptic Operators</strong>
- <br>
- submitted, 2013.
- </li>
-
- <li> J. Bosch, M. Stoll, P. Benner
- <br>
- <strong>Fast solution of Cahn-Hilliard variational
- inequalities using implicit time discretizations and finite
- elements</strong>
- <br>
- Preprint 13/01, MPI Magdeburg, 2013.
- </li>
-
- <li> J. Bosch, D. Kay, M. Stoll, A. J. Wathen
- <br>
- <strong>Fast solvers for Cahn-Hilliard inpainting</strong>
- <br>
- Technical report 1705, The Mathematical Institute,
- University of Oxford; submitted, 2013.
- </li>
-
- <li> A. Cangiani, J. Chapman, E. Georgoulis, M. Jensen
- <br>
- <strong>Implementation of the Continuous-Discontinuous
- Galerkin Finite Element Method</strong>
- <br>
- Numerical Mathematics and Advanced Applications 2011,
- pp. 315-322, 2013.
- </li>
-
- <li> T. Carraro, J. Joos
- <br>
- <strong>Parameter estimation for a reconstructed SOFC
- mixed-conducting LSCF-cathode</strong>
- <br>
- Model Based Parameter Estimation, H. G. Bock et al., eds.,
- pp. 267-285, Springer, 2013.
- </li>
-
- <li> T. Carraro, C. Goll, A. Marciniak-Czochra, A. Mikelic
- <br>
- <strong>Pressure jump interface law for the Stokes-Darcy
- coupling: Confirmation by direct numerical simulation</strong>
- <br>
- arXiv:1301.6580v0, 2013.
- </li>
-
- <li> C.-C. Chueh, N. Djilali, W. Bangerth
- <br>
- <strong>An h-adaptive Operator Splitting Method for
- Two-phase Flow in 3D Heterogeneous Porous Media</strong>
- <br>
- SIAM Journal on Scientific Computing, vol. 35, pp. B149-175, 2013.
- </li>
-
- <li> D. Devaud
- <br>
- <strong>Adaptive Methods for the Stokes System with Discontinuous Viscosities
- </strong>
- <br>
- MSc thesis, EPFL, 2013.
- </li>
-
- <li> T. Dohnal, W. Dörfler
- <br>
- <strong>Coupled Mode Equation Modeling for Out-of-Plane Gap
- Solitons in 2D Photonic Crystals</strong>
- <br>
- Multiscale Modeling and Simulation, vol. 11, pp. 162-191, 2013.
- </li>
-
- <li> I. Donev
- <br>
- <strong>Time Dependent Finite Element Simulations of a Generalized Oldroyd-B Fluid
- </strong>
- <br>
- MSc Thesis, University of Cape Town, 2013.
- </li>
-
- <li> W. Dörfler, S. Findeisen
- <br>
- <strong>Numerical optimization of a waveguide transition
- using finite element beam propagation</strong>
- <br>
- IWRMM, Preprint 13/01, Karlsruhe Institute of Technology,
- 2013.
- <!-- http://www.math.kit.edu/ianm2/~doerfler/seite/pub/de -->
- </li>
-
- <li> K. Dugan
- <br>
- <strong>Dynamic adaptive multimesh refinement for coupled
- physics applicable to nuclear engineering
- </strong>
- <br>
- MSc thesis, Texas A&M University, 2013.
- </li>
-
- <li> Y. Efendiev, J. Galvis, S. Pauletti
- <br>
- <strong>Multiscale finite element methods for flows on rough
- surfaces
- </strong>
- <br>
- Communications in Computational Physics, accepted, 2013.
- </li>
-
- <li> E. Emmrich, A. Wróblewska-Kamińska
- <br>
- <strong>Convergence of a Full Discretization of Quasi-linear Parabolic Equations in Isotropic and Anisotropic Orlicz Spaces
- </strong>
- <br>
- SIAM Journal on Numerical Analysis, vol. 51, pp. 1163-1184, 2013.
- </li>
-
- <li> J. Fang, X. Gao, A. Zhou
- <br>
- <strong>A finite element recovery approach to eigenvalue
- approximations with applications to electronic structure
- calculations
- </strong>
- <br>
- Journal of Scientific Computing, vol. 55, pp. 432-454, 2013.
- </li>
-
- <li> T. Fankhauser, T. Wihler, M. Wirz
- <br>
- <strong>The hp-adaptive FEM based on continuous Sobolev embeddings: Isotropic
- refinements</strong>
- <br>
- Computers & Mathematics with Applications (in press), 2013.
- </li>
-
- <li> F. Freddi, G. Royer-Carfagni
- <br>
- <strong>Plastic flow as an energy minimization problem. Numerical
- Experiments
- </strong>
- <br>
- Journal of Elasticity, in press, 2013.
- </li>
-
- <li> S. Frei, T. Richter, T. Wick
- <br>
- <strong>Eulerian Techniques for Fluid-Structure Interactions - Part
- I: Modeling and Simulation
- </strong>
- <br>
- ENUMATH Proc., submitted Nov 2013.
- </li>
-
- <li> S. Frei, T. Richter, T. Wick
- <br>
- <strong>Eulerian Techniques for Fluid-Structure Interactions - Part II: Applications
- </strong>
- <br>
- ENUMATH Proc., submitted Nov 2013.
- </li>
-
- <li> A. Geringer, B. Lenhof, S. Diebels
- <br>
- <strong>Macroscopic modeling of foams: an order-parameter
- approach vs. a micropolar model
- </strong>
- <br>
- Technische Mechanik, vol. 33, pp. 87-96, 2013.
- </li>
-
- <li> F. Gimbel
- <br>
- <strong>Modelling and numerical simulation of contact and lubrication
- </strong>
- <br>
- PhD thesis, University of Siegen, Germany, 2013.
- </li>
-
- <li> C. Goll, R. Rannacher, W. Wollner
- <br>
- <strong>Goal-Oriented Mesh Adaptation in the Space-Time
- Finite Element Approximation of the Black-Scholes Equation
- </strong>
- <br>
- Journal of Computational Finance, accepted, 2013.
- </li>
-
- <li> S. Härting, A. Marciniak-Czochra
- <br>
- <strong>Spike patterns in a reaction-diffusion-ode model with Turing instability</strong>
- <br>
- arXiv:1303.5362, submitted, 2013.
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Higher-order and adaptive discontinuous Galerkin
- methods with shock-capturing applied to transonic turbulent
- delta wing flow
- </strong>
- <br>
- International Journal for Numerical Methods in Fluids,
- vol. 72, pp. 883-894, 2013.
- </li>
-
- <li> T. Heister, G. Rapin
- <br>
- <strong>Efficient augmented Lagrangian-type preconditioning
- for the Oseen problem using Grad-Div stabilization</strong>
- <br>
- Int. J. Num. Meth. Fluids, 71, 118–134, 2013
- (<a href="http://dx.doi.org/10.1002/fld.3654">DOI</a>)
- </li>
-
- <li> M. Hinze, U. Mathes
- <br>
- <strong>Model order reduction for networks of ODE and PDE systems
- </strong>
- <br>
- System Modeling and Optimization, IFIP Advances in
- Information and Communication Technology Volume 391,
- pp 92-101, 2013.
- </li>
-
- <li> S. Joshi, J, Walton
- <br>
- <strong>Reconstruction of the residual stresses in a hyperelastic body using ultrasound techniques
- </strong>
- <br>
- International Journal on Engineering Science, vol. 70,
- pp. 46-72, 2013.
- </li>
-
- <li> S. Kim
- <br>
- <strong>Analysis of the convected Helmholtz equation with a
- uniform mean flow in a waveguide with complete radiation
- boundary conditions
- </strong>
- <br>
- Journal of Mathematical Analysis and Applications,
- in press,
- <!-- http://www.sciencedirect.com/science/article/pii/S0022247X1300749X -->
- 2013.
- </li>
-
- <li> N. Klein
- <br>
- <strong>Consistent FE-Analysis of elliptic Variational Inequalities
- </strong>
- <br>
- PhD thesis, University of Siegen, Germany, 2013.
- </li>
-
- <li> T. Krüger
- <br>
- <strong>Regularization-based fictitious domain methods
- </strong>
- <br>
- PhD thesis, University of Siegen, Germany, 2013.
- </li>
-
- <li> K. Kumar, T. van Noorden, M. F. Wheeler, T. Wick
- <br>
- <strong>An ALE-based method for reaction-induced boundary movement towards clogging
- </strong>
- <br>
- ENUMATH Proc., submitted Nov 2013.
- </li>
-
- <li> K. Kumar, M.F. Wheeler, T. Wick
- <br>
- <strong>Reactive flow reaction-induced boundary movement in
- a thin channel
- </strong>
- <br>
- SIAM J. Sci. Comput. 35(6), pp. B1235-B1266, 2013
- </li>
-
- <li> B. Lenhof, A. Geringer, S. Diebels
- <br>
- <strong>Macroscopic modeling of size effects in foams using
- an order parameter
- </strong>
- <br>
- Generalized Continua as Models for Materials,
- Advanced Structured Materials, vol. 22, pp. 237-254, 2013.
- </li>
-
- <li> S. H. Lim
- <br>
- <strong>Numerical Simulation of Two-phase Heat Flow and Transient
- Partial Melting in the Lower Crust with Adaptive Mesh Refinement
- </strong>
- <br>
- Undergraduate honors thesis, University of Michigan, Ann Arbor, 2013.
- </li>
-
- <li> A. Mikelic, M.F. Wheeler, T. Wick
- <br>
- <strong>A phase field approach to the fluid filled fracture surrounded by a poroelastic medium
- </strong>
- <br>
- submitted, ICES preprint on http://www.ices.utexas.edu/research/reports/
- </li>
-
- <li> A. Mola, L. Heltai, A. DeSimone
- <br>
- <strong>A stable and adaptive semi-Lagrangian potential
- model for unsteady and nonlinear ship-wave
- interactions</strong>
- <br>
- Engineering Analysis with Boundary Elements, vol. 37,
- pp. 128-143, 2013.
- </li>
-
- <li> R. H. Nochetto, A. J. Salgado, I. Tomas
- <br>
- <strong>The micropolar Navier-Stokes equations: A priori error analysis</strong>
- <br>
- arXiv:1303.7005, submitted, 2013.
- </li>
-
- <li> M. R. Opmeer, T. Reis, W. Wollner
- <br>
- <strong>Finite-Rank ADI Iteration for Operator Lyapunov Equations</strong>
- <br>
- SIAM J. Control Optim., vol. 51, pp. 4084-4117, 2013.
- </li>
-
- <li> T. Povall
- <br>
- <strong>Single Crystal Plasticity at Finite Strains: A Computational Investigation of Hardening Relations</strong>
- <br>
- MSc Thesis, University of Cape Town, 2013.
- </li>
-
- <li> T. Reis, W. Wollner
- <br>
- <strong>Iterative solution of operator Lyapunov equations
- arising in heat transfer
- </strong>
- <br>
- 2013 European Control Conference, Zurich Switzerland,
- pp. 41-46, 2013.
- </li>
-
- <li> T. Richter, T. Wick
- <br>
- <strong>Solid growth and clogging in fluid-structure interaction computed in ALE and fully Eulerian coordinates
- </strong>
- <br>
- submitted Oct 2013 (peer-reviewed journal)
- </li>
-
- <li> T. Richter, T. Wick
- <br>
- <strong>On time discretizations of fluid-structure interactions
- </strong>
- <br>
- submitted Oct 2013 (book proceedings)
- </li>
-
-
- <li> T. Richter, T. Wick
- <br>
- <strong>Optimal Control and Parameter Estimation for Stationary Fluid-Structure Interaction Problems
- </strong>
- <br>
- SIAM J. Sci. Comput., accepted in May, 2013.
- </li>
-
- <li> S. Roy, L. Heltai, D. Drapaca, F. Costanzo
- <br>
- <strong>An immersed finite element method approach for brain biomechanics</strong>
- <br>
- Mechanics of Biological Systems and Materials, Volume 5,
- Conference Proceedings of the Society for Experimental Mechanics
- Series, pp. 79-86, 2013.
- </li>
-
- <li> J. Reinhardt, F. Weysser, J. M. Brader
- <br>
- <strong>Density functional approach to nonlinear rheology</strong>
- <br>
- Europhysics Letters, vol. 102, article 28011, 2013.
- </li>
-
- <li> S. Rudraraju, K. L. Mills, R. Kemkemer, K. Garikipati
- <br>
- <strong>Multiphysics Modeling of Reactions, Mass Transport and Mechanics of Tumor Growth
- </strong>
- <br>
- Computer Models in Biomechanics, G. Holzapfel and E. Kuhl
- (eds.), Spinger Verlag, pp. 293-303, 2013.
- </li>
-
- <li> M. Sagebaum, N. R. Gauger, U. Naumann, J. Lotz, K. Leppkes
- <br>
- <strong>Algorithmic differentiation of a complex C++ code with underlying libraries
- </strong>
- <br>
- Procedia Computer Science, vol. 18, pp. 208-217, 2013.
- </li>
-
- <li> P. Siehr
- <br>
- <strong>Stabilisierungsmethoden für die Stokes-Gleichungen
- </strong>
- <br>
- Bachelor thesis, University of Heidelberg, Germany, 2013.
- </li>
-
- <li>
- M. Steigemann, B. Schramm
- <br>
- <strong>Precise computation and error control of stress
- intensity factors and certain integral characteristics in
- anisotropic inhomogeneous materials
- </strong>
- <br>
- International Journal of Fracture, vol. 182, pp. 67-91, 2013.
- </li>
-
- <li> M. Stoll, T. Breiten
- <br>
- <strong>A low-rank in time approach to PDE-constrained optimization</strong>
- <br>
- Max Planck Institute Magdeburg, Preprint MPIMD/13-08, 2013.
- </li>
-
- <li> N. Vakulin, R. Shaw, T. Livingston
- <br>
- <strong>ELEC 490, final report: High performance computing with GPUs
- </strong>
- <br>
- Semester project for ELEC 490, final report. Queen's University,
- 2013
- </li>
-
- <li> A. Vidal-Ferrandiz, R. Fayez, D. Ginestar, G. Verdú
- <br>
- <strong>Solution of the Lambda modes problem of a nuclear
- power reactor using an h-p finite element method
- </strong>
- <br>
- Conference abstract, Mathematical Modelling in Engineering &
- Human Behaviour 2013, 2013.
- </li>
-
- <li> T. Wick, A. H. Elsheikh, M.F. Wheeler
- <br>
- <strong>Parameter Estimation for the Coupled Biot-Lam\'e-Navier Problem in Subsurface Modeling
- </strong>
- <br>
- ARMA Conference in San Francisco, Jun 23-26, 2013.
- </li>
-
-
-
- <li> J. Weinbub, K. Rupp, S. Selberherr
- <br>
- <strong>ViennaX: a parallel plugin execution framework for
- scientific computing
- </strong>
- <br>
- Engineering with Computers, DOI 10.1007/s00366-013-0314-1, February 2013.
- </li>
-
- <li> T. Wick
- <br>
- <strong>Flapping and Contact FSI Computations with the
- Fluid-Solid Interface-Tracking/Interface-Capturing Technique
- and Mesh Adaptivity
- </strong>
- <br>
- Computational Mechanics, DOI: 10.1007/s00466-013-0890-3, 2013.
- </li>
-
- <li> T. Wick
- <br>
- <strong>Coupling of fully Eulerian and arbitrary Lagrangian-Eulerian
- methods for fluid-structure interaction computations
- </strong>
- <br>
- Computational Mechanics, DOI: 10.1007/s00466-013-0866-3, 2013.
- </li>
-
- <li> T. Wick
- <br>
- <strong>Solving monolithic fluid-structure interaction
- problems in arbitrary
- Lagrangian Eulerian coordinates
- with the deal.II library
- </strong>
- <br>
- ANS, vol. 1, pp. 1-19, 2013. http://www.archnumsoft.org/
- </li>
-
- <li> T. Wick
- <br>
- <strong>Fully Eulerian fluid-structure interaction for time-dependent problems
- </strong>
- <br>
- Comp. Methods Appl. Mech. Engrg., vol. 255, pp. 14-26, 2013.
- </li>
-
- <li> J. Willems
- <br>
- <strong>Robust Multilevel Solvers for High-Contrast Anisotropic
- Multiscale Problems
- </strong>
- <br>
- Journal of Computational and Applied Mathematics, 251:47-60, 2013, doi:10.1016/j.cam.2013.03.030.
- </li>
-
- <li> J. Willems
- <br>
- <strong>Spectral Coarse Spaces in Robust Two-Level Schwartz Methods
- </strong>
- <br>
- O. Iliev, S. Margenov, P. Minev, P. Vassilevski, L. Zikatanov, editors, Numerical Solution of Partial Differential Equations: Theory, Algorithms and their Applications, 303-326, Springer Proceedings in Mathematics & Statistics, Springer, 2013.
- </li>
-
- <li> S. Yoon, Y. T. Kang
- <br>
- <strong>Mass transfer enhancement in non-Brownian particle
- suspension under a confined shear</strong>
- <br>
- International Journal of Heat and Mass Transfer, vol. 60,
- pp. 114-124, 2013.
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>
- <br>
- <strong>A finite basis grid analysis of the Hartree-Fock wavefunction method for one- and two-electron atoms
- </strong>
- <br>
- AIP Conf. Proc., vol. 1558, pp. 1524, 2013.
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>, E. Romero, J. E. Roman
- <br>
- <strong>Parallel finite element density functional theory exploiting grid refinement and subspace recycling
- </strong>
- <br>
- Comput. Phys. Commun., vol. 184, 1, pp. 66-72, 2013.
- </li>
-
- <li> V. Zingan, J.-L. Guermond, J. Morel, B. Popov
- <br>
- <strong>Implementation of the entropy viscosity method with
- the Discontinuous Galerkin Method
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 253, pp. 479-490, 2013.
- </li>
- </ol>
-
- <a name="2012"> </a>
- <h2>Publications in 2012</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> M. Bause, U. Köcher
- <br>
- <strong>Numerical simulation of elastic wave propagation
- in composite material</strong>
- <br>
- Proceedings of the European Congress on Computational Methods
- in Applied Sciences and Engineering (ECCOMAS 2012)
- J. Eberhardsteiner et.al. (eds.)
- Vienna, Austria, September 10-14, 2012.
- </li>
-
- <li> M. Besier, W. Wollner
- <br>
- <strong>On the pressure approximation in nonstationary
- incompressible flow simulations on dynamically varying
- spatial meshes</strong>
- <br>
- International Journal for Numerical Methods in Fluids,
- vol. 69, pp. 1045-1064, 2012.
- </li>
-
- <li> L. Blank, L. Sarbu, M. Stoll
- <br>
- <strong>Preconditioning for Allen-Cahn variational
- inequalities with non-local constraints</strong>
- <br>
- Journal of Computational Physics, vol. 231, pp. 5406-5402, 2012.
- </li>
-
- <li> C. Boehm, M. Ulbrich
- <br>
- <strong>A Newton-CG method for full-waveform inversion in a
- coupled solid-fluid system</strong>
- <br>
- submitted, 2012.
- <!-- http://www-m1.ma.tum.de/bin/view/Lehrstuhl/PublikationenUlbrich -->
- </li>
-
- <li>
- M. Braack, G. Lube, L. Röhe
- <br>
- <strong>Divergence preserving interpolation on anisotropic
- quadrilateral meshes
- </strong>
- <br>
- Comput. Methods Appl. Math., Vol. 12, pp. 123-138, 2012.
- </li>
-
- <li> <a href="http://www.math.kit.edu/ianm2/~buerg/"
- target="_top">M. Bürg</a>
- <br>
- <strong>A Residual-Based A Posteriori Error Estimator for the
- <it>hp</it>-Finite Element Method for Maxwell's Equations
- </strong>
- <br>
- Appl. Numer. Math., vol. 62, pp. 922-940, 2012.
- </li>
-
- <li> <a href="http://www.math.kit.edu/ianm2/~buerg/"
- target="_top">M. Bürg</a>
- <br>
- <strong>Convergence of an automatic
- <it>hp</it>-adaptive finite element strategy for Maxwell's equations
- </strong>
- <br>
- Preprint 12/04, Karlsruhe Institute of Technology (KIT), 2012.
- </li>
-
- <li> <a href="http://www.math.kit.edu/ianm2/~buerg/"
- target="_top">M. Bürg</a>
- <br>
- <strong>A Fully Automatic <it>hp</it>-Adaptive Refinement Strategy
- </strong>
- <br>
- PhD Thesis, Karlsruhe Institute of Technology (KIT), 2012.
- </li>
-
- <li> A. Cangiani, J. Chapman, E. Georgoulis, M. Jensen
- <br>
- <strong>On Local Super-Penalization of Interior Penalty Discontinuous Galerkin Methods</strong>
- <br>
- arXiv:1205.5672v1 [math.NA], 2012.
- <!-- http://www2.le.ac.uk/departments/mathematics/extranet/staff-material/staff-profiles/eg64/publications -->
- <!-- http://arxiv.org/abs/1205.5672 -->
- </li>
-
- <li> A. Cangiani, E. Georgoulis, S. Metcalfe
- <br>
- <strong>An a posteriori error estimator for discontinuous
- Galerkin methods for non-stationary convection-diffusion
- problems
- </strong>
- <br>
- submitted, 2012.
- <!-- http://www2.le.ac.uk/departments/mathematics/extranet/staff-material/staff-profiles/eg64/publications -->
- </li>
-
- <li> A. Cangiani, E. Georgoulis, M. Jensen
- <br>
- <strong>Discontinuous Galerkin methods for mass transfer through
- semi-permeable membranes
- </strong>
- <br>
- submitted, 2012.
- <!-- http://www2.le.ac.uk/departments/mathematics/extranet/staff-material/staff-profiles/eg64/publications -->
- </li>
-
- <li> T. Carraro, J. Joos, B. Rüger, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>3D finite element model for reconstructed mixed-conducting
- cathodes: I. Performance quantification</strong>
- <br>
- Electrochimica Acta, Volume 77, pp. 315-323, 2012.
- </li>
-
- <li> T. Carraro, J. Joos, B. Rüger, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>3D finite element model for reconstructed mixed-conducting
- cathodes: II. Parameter sensitivity analysis</strong>
- <br>
- Electrochimica Acta, Volume 77, pp. 309-314, 2012.
- </li>
-
- <li> A. Demlow, A. H. Georgoulis
- <br>
- <strong>Pointwise a posteriori error control for
- discontinuous Galerkin methods for elliptic problems</strong>
- <br>
- SIAM Journal on Numerical Analysis, vol. 50, pp. 2159-2181, 2012.
- </li>
-
- <li> P. Dobson, C. Lei, T. Navessin, M. Secanell
- <br>
- <strong>Characterization of the PEM Fuel Cell Catalyst Layer
- Microstructure by Nonlinear Least-Squares Parameter
- Estimation</strong>
- <br>
- Journal of the Electrochemical Society, 159(5), B1-B10, 2012.
- </li>
-
- <li> Y. Efendiev, J. Galvis, R. Lazarov, J. Willems
- <br>
- <strong>Robust domain decomposition preconditioners for abstract
- symmetric positive definite bilinear forms
- </strong>
- <br>
- ESAIM: Mathematical Modelling and Numerical Analysis, vol. 46,
- pp. 1175-1199, 2012.
- </li>
-
- <li> Y. Efendiev, J. Galvis, R. Lazarov, J. Willems
- <br>
- <strong> Robust solvers for symmetric positive definite operators
- and weighted Poincaré inequalities
- </strong>
- <br>
- In I. Lirkov, S. Margenov, and J. Wasniewski, editors, Large-Scale
- Scientific Computing: 8th International Conference, LSSC 2011,
- Sozopol, Bulgaria, 43-51, Lecture Notes in Computer Science,
- Springer, 2012.
- </li>
-
- <li> J. Fang, X. Gao, A. Zhou
- <br>
- <strong>A Kohn-Sham equation solver based on hexahedral finite elements</strong>
- <br>
- Journal of Computational Physics, vol. 231, pp. 3166–3180, 2012.
- </li>
-
- <li> T. Fankhauser
- <br>
- <strong>An hp-adaptive strategy based on smoothness
- estimation in 2d
- </strong>
- <br>
- Master Thesis, University of Bern, Switzerland, 2012.
- </li>
-
- <li> T. Fankhauser, T. P. Wihler, M. Wirz
- <br>
- <strong>hp-adaptive FEM based on continuous Sobolev
- embeddings: isotropic refinements
- </strong>
- <br>
- Research report 2012-10, University of Bern, Switzerland, 2012.
- </li>
-
- <li> L. Ferguson
- <br>
- <strong>Brittle fracture modeling with a surface tension
- excess property
- </strong>
- <br>
- PhD thesis, Texas A&M University, 2012.
- </li>
-
- <li> A. Frisani, Y. Hassan
- <br>
- <strong>A Projection Approach for the Immersed Finite Element Method
- </strong>
- <br>
- Transactions of the American Nuclear Society, vol. 106, 2012.
- </li>
-
- <li> J. J. Gaitero, J. S. Dolado, C. Neuen, F. Heber, E. Koenders
- <br>
- <strong>Computational 3d simulation of Calcium leaching in
- cement matrices
- </strong>
- <br>
- Institut für numerische Simulation, Rheinische
- Friedrich-Wilhelms-Universität Bonn, INS Preprint 1203, 2012.
- </li>
-
- <li> T. George, A. Gupta, V. Sarin
- <br>
- <strong>An empirical analysis of the performance of iterative
- solvers for SPD systems
- </strong>
- <br>
- Submitted to ACM Trans. Math. Softw., 2011.
- </li>
-
- <li> C. Goll, T. Wick, W. Wollner
- <br>
- <strong>DOpElib: Differential Equations and Optimization Environment;
-A Goal Oriented Software Library for Solving PDEs and Optimization Problems with PDEs
- </strong>
- <br>
- submitted in Dec 2012.
- </li>
-
- <li> N. Gupta, N. Nataraj
- <br>
- <strong>A posteriori error estimates for an optimal control
- problem of laser surface hardening of steel
- </strong>
- <br>
- Adv. Comp. Math., published online, 2011.
- <!-- http://www.springerlink.com/content/q25382q384582667/ -->
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Higher-order and adaptive discontinuous Galerkin
- methods with shock-capturing applied to transonic turbulent
- delta wing flow
- </strong>
- <br>
- 50<sup>th</sup> AIAA Aerospace Sciences Meeting, AIAA 2012-459, 2012.
- </li>
-
- <li>
- S. Kramer
- <br>
- <strong>Finite-element methods for spatially resolved mesoscopic
- electron transport
- </strong>
- <br>
- Phys. Rev. B 88, p. 125308, 2013
- <br>
- <a href="http://link.aps.org/doi/10.1103/PhysRevB.88.125308">DOI:
- 10.1103/PhysRevB.88.125308</a>
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Higher-order and adaptive Discontinuous Galerkin
- methods applied to turbulent delta wing flow </strong>
- <br>
- In H. P. Kreplin, editor, New Results in Numerical and
- Experimental Fluid Mechanics VIII: Contributions to the 17th
- STAB/DGLR Symposium Berlin, Germany, 2010, Notes on
- Numerical Fluid Mechanics and Multidisciplinary Design,
- Springer. In press.
- </li>
-
- <li> L. Heltai, S. Roy, F. Costanzo
- <br>
- <strong>A Fully Coupled Immersed Finite Element Method for
- Fluid Structure Interaction via the Deal.II Library</strong>
- <br>
- arXiv:1209.2811 [math.NA], 2012.
- </li>
-
- <li> M. Hinze, M. Kunkel, A. Steinbrecher, T. Stykel
- <br>
- <strong>Model order reduction of coupled circuit-device systems
- </strong>
- <br>
- International Journal of Numerical Modelling: Electronic
- Networks, Devices and Fields,
- vol. 25, pp. 362-377, 2012.
- </li>
-
- <li> O. Jirousek, P. Zlamal
- <br>
- <strong>Large-scale micro-finite element simulation of
- compressive behavior of trabecular bone microstructure</strong>
- <br>
- Proceedings of the 18th Conference on Engineering Mechanics,
- Svratka, Czech Republic, May 14-17, 2012; paper #206,
- pp. 543-549, 2012.
- </li>
-
- <li> J. Joos, M. Ender, T. Carraro, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>Representative Volume Element Size for Accurate Solid Oxide
- Fuel Cell Cathode Reconstructions from Focused Ion Beam Tomography
- Data</strong>
- <br>
- Electrochimica Acta, in press, 2012.
- <!-- http://www.sciencedirect.com/science/article/pii/S001346861200761X -->
- </li>
-
- <li> S. Joshi
- <br>
- <strong>A model for the estimation of residual stresses in
- soft tissues
- </strong>
- <br>
- Ph.D. thesis, Texas A&M University, 2012.
- </li>
-
- <li> M. Kronbichler, T. Heister, W. Bangerth
- <br>
- <strong>High Accuracy Mantle Convection Simulation through Modern
- Numerical Methods
- </strong>
- <br>
- Geophysical Journal International, vol. 191, pp. 12-29, 2012.
- </li>
-
- <li> K. Kormann
- <br>
- <strong>A time-space adaptive method for the
- Schrödinger equation
- </strong>
- <br>
- University of Uppsala, research report, 2012.
- </li>
-
- <li> M. Kunkel
- <br>
- <strong>Nonsmooth Newton Methods and Convergence of
- Discretized Optimal Control Problems subject to DAEs
- </strong>
- <br>
- PhD thesis, Universität der Bundeswehr München, 2012.
- </li>
-
- <li> A. T. McBride, J. Mergheim, A. Javili, P. Steinmann, S. Bargmann
- <br>
- <strong>Micro-to-macro transitions for heterogeneous material
- layers accounting for in-plane stretch
- </strong>
- <br>
- Journal of the Mechanics and Physics of Solids, vol. 60, pp. 1221-1239, 2012.
- </li>
-
- <li> C. Neuen, M. Griebel, J. Hamaekers
- <br>
- <strong>Multiscale simulation of ion migration for battery system
- </strong>
- <br>
- Institut für numerische Simulation, Rheinische
- Friedrich-Wilhelms-Universität Bonn, INS Preprint 1208, 2012.
- </li>
-
- <li> M. J. Rapson, J. C. Tapson, D. Karpul
- <br>
- <strong>Unification and Extension of Monolithic State Space
- and Iterative Cochlear Models
- </strong>
- <br>
- Journal of the Acoustical Society of America, vol. 131, pp. 3935-3952, 2012.
- </li>
-
- <li> N. Richardson
- <br>
- <strong>An Investigation into Aspects of Rate-Independent Single Crystal Plasticity
- </strong>
- <br>
- Master's thesis, University of Cape Town, South Africa, 2012.
- </li>
-
- <li> D. Riedlbauer, J. Mergheim, A. McBride, P. Steinmann
- <br>
- <strong>Macroscopic modelling of the selective beam melting process
- </strong>
- <br>
- PAMM, vol. 12, p. 381-382, 2012.
- </li>
-
- <li> E. Romero Alcalde
- <br>
- <strong>Parallel implementation of Davidson-type methods for large-scale eigenvalue problems
- </strong>
- <br>
- PhD thesis,
- Universitat Politecnica de Valencia, 2012.
- </li>
-
- <li> S. Roy
- <br>
- <strong>Numerical simulation using the generalized immersed boundary
- method: An application to Hydrocephalus
- </strong>
- <br>
- PhD thesis, The Pennsylvania State University, 2012.
- </li>
-
- <li> J.-P. V. Pelteret, B. D. Reddy
- <br>
- <strong>Computational model of soft tissues in the human upper airway
- </strong>
- <br>
- International Journal for Numerical Methods in Biomedical Engineering,
- Vol. 28, pp. 111–132, 2012.
- </li>
-
- <li> D. Schötzau, C. Schwab, T. Wihler, M. Wirz
- <br>
- <strong>Exponential convergence of the hp-DGFEM for elliptic
- problems in polyhedral domains
- </strong>
- <br>
- Research Report 2012-40, Seminar für Angewandte
- Mathematik, ETH Zurich, 2012.
- </li>
-
- <li> J. Sheldon
- <br>
- <strong>A comparison of fluid-structure interaction coupling
- algorithms using the finite element method
- </strong>
- <br>
- MSc thesis, The Pennsylvania State University, 2012.
- </li>
-
- <li>
- M. Stoll, A. Wathen
- <br>
- <strong>Preconditioning for partial differential equation
- constrained optimization with control constraints
- </strong>
- <br>
- Numerical Linear Algebra with Applications, vol. 19, pp. 53-71,
- 2012.
- </li>
-
- <li> M. Stoll, A. Wathen
- <br>
- <strong>All-at-once solution of time-dependent PDE-constrained optimization problems
- </strong>
- <br>
- Preprint, University of Magdeburg, 2012
- <!-- http://www.mpi-magdeburg.mpg.de/people/stollm/pub.html -->
- </li>
-
- <li> M. Stoll, A. Wathen
- <br>
- <strong>All-at-once solution of time-dependent Stokes control
- </strong>
- <br>
- Journal of Computational Physics, vol. 232, pp. 498-515, 2012.
- </li>
-
- <li> W. Symes, X. Wang
- <br>
- <strong>Harmonic coordinate finite element method for acoustic waves
- </strong>
- <br>
- SEG Technical Program Expanded Abstracts 2012, pp. 1-5, 2012.
- </li>
-
- <li> S. Taylor, K. Dontsova, S. Bigl, C. Richardson, J. Lever,
- J. Pitt, J. P. Bradley, M. Walsh. J. Simunek
- <br>
- <strong>Dissolution Rate of Propellant Energetics from Nitrocellulose Matrices
- </strong>
- <br>
- Engineer Research and Development Center, Cold Regions
- Research and Engineering Laboratory, US Army Corps of
- Engineers,
- Technical Report ER-1691, 2012.
- </li>
-
- <li> M. Thalhammer, J. Abhau
- <br>
- <strong>A numerical study of adaptive space and time discretisations for Gross–Pitaevskii equations
- </strong>
- <br>
- Journal of Computational Physics, vol. 231, pp. 6665-6681, 2012.
- </li>
-
- <li> J. Trangenstein
- <br>
- <strong>Numerical Solution of Elliptic and Parabolic Partial
- Differential Equations
- </strong>
- <br>
- Cambridge University Press, 2012.
- </li>
-
- <li> M. Vavalis, M. Mu, G. Sarailidis
- <br>
- <strong>Finite element simulations of window Josephson junctions
- </strong>
- <br>
- Journal of Computational and Applied Mathematics, vol. 236,
- pp. 3186-3197, 2012.
- </li>
-
- <li> M. Wallraff, T. Leicht, M. Lange-Hegermann
- <br>
- <strong>Numerical flux functions for Reynolds-averaged Navier-Stokes
- and kω turbulence model computations with a line-preconditioned
- p-multigrid discontinuous Galerkin solver</strong>
- <br>
- Int. J. Numer. Meth. Fluids, published online, 2012.
- <!-- http://onlinelibrary.wiley.com/doi/10.1002/fld.3702/full -->
- </li>
-
- <li> M. Wallraff, T. Leicht, M. Lange-Hegermann
- <br>
- <strong>Numerical flux functions for RANS-kω computations with a
- line-implicit p-multigrid DG solver</strong>
- <br>
- 50<sup>th</sup> AIAA Aerospace Sciences Meeting, AIAA 2012-458, 2012.
- </li>
-
-
- <li> T. Wick
- <br>
- <strong>Goal-oriented mesh adaptivity for fluid-structure interaction with application to heart-valve settings
- </strong>
- <br>
- Arch. Mech. Engrg., vol. 59, pp. 73-99, 2012.
- </li>
-
-
-
- <li> J. Willems
- <br>
- <strong>Robust multilevel methods for general symmetric positive
- definite operators
- </strong>
- <br>
- RICAM Report 2012-06, 2012.
- </li>
-
- <li> S. Yoon, M. A. Walkley, O. G. Harlen
- <br>
- <strong>Two particle interactions in a confined viscoelastic fluid under shear
- </strong>
- <br>
- Journal of Non-Newtonian Fluid Mechanics, vol. 185/186, pp. 39-48, 2012.
- </li>
-
- <li> S. Zhang, X. Lin, H. Zhang, D. A. Yuen, Y. Shi
- <br>
- <strong>A new method for calculating displacements from
- elastic dislocation over arbitrary 3-D fault surface with
- extended FEM and Adaptive Mesh Refinement (AMR)</strong>
- <br>
- Proceedings of the International Workshop on Deep Geothermal
- Systems, Wuhan, China, June 29-30, 2012.
- </li>
- </ol>
-
- <a name="2011"> </a>
- <h2>Publications in 2011</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> I. Adeniran, M. J. McPate, H. J. Wichtel, J. C. Hancox,
- H. Zhang
- <br>
- <strong>Increased vulnerability of human ventricle to
- re-entrant excitation in hERG-linked variant 1 short QT
- syndrome
- </strong>
- <br>
- PLoS Computational Biology, vol. 7, e1002313, 2011.
- </li>
-
- <li> M. Allmaras
- <br>
- <strong>Modeling aspects and computational methods for some recent
- problems of tomographic imaging
- </strong>
- <br>
- PhD thesis, Texas A&M University, 2011.
- </li>
-
- <li> M. Allmaras, W. Bangerth
- <br>
- <strong>Reconstructions in ultrasound modulated optical tomography
- </strong>
- <br>
- J. Inverse and Ill-posed Problems, vol. 19, pp. 801-823, 2011.
- </li>
-
- <li> F. Alouges, A. DeSimone, L. Heltai
- <br>
- <strong>Numerical strategies for stroke optimization of
- axisymmetric microswimmers
- </strong>
- <br>
- Mathematical Models and Methods in Applied Sciences, vol. 21, pp. 361-387, 2011.
- </li>
-
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- <a href="http://users.ices.utexas.edu/~carsten/"
- target="_top">C. Burstedde</a>, T. Heister, M. Kronbichler
- <br>
- <strong>Algorithms and Data Structures for Massively Parallel Generic
- Finite Element Codes</strong>
- <br>
- ACM Trans. Math. Softw., vol. 38, article 124, 2011.
- </li>
-
- <li> K. Benzarti, F. Freddi, M. Frémond
- <br>
- <strong>A damage model to predict the durability of bonded
- assemblies. Part I: Debonding behavior of FRP strengthened
- concrete structures</strong>
- <br>
- Construction and Building Materials, 25(2), 547-555, 2011.
- </li>
-
- <li> A. Buehler, A. Rosenthal, T. Jetzfellner, A. Dima,
- D. Razansky, V. Ntziachristos
- <br>
- <strong>Model-based optoacoustic inversions with incomplete projection
- data</strong>
- <br>
- Med. Phys., vol. 38, pp. 1694-1704, 2011.
- </li>
-
- <li> M. Bürg, W. Dörfler
- <br>
- <strong>Convergence of an adaptive hp finite element strategy in higher
- space-dimensions</strong>
- <br>
- Appl. Numer. Math. 61, pp. 1132-1146, 2011.
- </li>
-
- <li> A. Cangiani, E. Georgoulis, M. Jensen
- <br>
- <strong>Discontinuous Galerkin methods for convection-diffusion
- problems modelling mass transfer through semipermeable membranes.
- </strong>
- <br>
- Proceedings of the Congress on Numerical Methods in Engineering,
- Coimbra, 2011.
- </li>
-
- <li> P. Carrara, D. Ferretti, F. Freddi, G. Rosati
- <br>
- <strong>Shear tests of carbon fiber plates bonded to concrete with
- control of snap-back
- </strong>
- <br>
- Engineering Fracture Mechanics, vol. 78, pp. 2663-2678, 2011.
- </li>
-
- <li>
- S. Chandrasekaran, K. R. Jayaraman, M. Gu, H. N. Mhaskar, J. Moffitt
- <br>
- <strong>MSNFD: A Higher Order Finite Difference Method for Solving Elliptic
- PDEs on scattered points (An Extended version of our paper
- submitted to ICCS 2011)</strong>
- <br>
- submitted, 2011.
- <!-- http://scg.ece.ucsb.edu/msnpub.html -->
- </li>
-
- <li> B. Crestel
- <br>
- <strong>Moving meshes on general surfaces
- </strong>
- <br>
- Ph.D. thesis, Simon Fraser University, 2011
- </li>
-
- <li> E. Emmrich, D. Šiška
- <br>
- <strong>Full discretization of second-order nonlinear evolution
- equations: Strong convergence and applications
- </strong>
- <br>
- Preprint, University of Bielefeld, 2011.
- </li>
-
- <li> F. Freddi, G. Royer-Carfagni
- <br>
- <strong>Variational fracture mechanics for
- compressive splitting of masonry-like materials
- </strong>
- <br>
- Annals of Solid and Structural Mechanics, vol. 2, pp. 57-67, 2011.
- </li>
-
- <li> M. Freyer
- <br>
- <strong>Automatische Segmentierung anatomischer Strukturen in
- CT-Bildern eines hybriden FMT/XCT-Systems zur Verbesserung der
- optischen Bildgebung
- </strong>
- <br>
- Ph.D. thesis, Ludwig-Maximilians-University Munich, Germany, 2011.
- </li>
-
- <li> J. Frohne
- <br>
- <strong>FEM-Simulation der Umformtechnik metallischer
- Oberflächen im Mikrokosmos
- </strong>
- <br>
- Ph.D. thesis, University of Siegen, Germany, 2011.
- </li>
-
- <li>
- S. Gladkov, T. Kayser, B. Svendsen
- <br>
- <strong>FE-modeling of ideal grain growth based on
- preprocessed EBSD data
- </strong>
- <br>
- PAMM, vol. 11, pp.471-472 2011.
- </li>
-
- <li> A. Ginzburg
- <br>
- <strong>Introduction to Geophysics (in Hebrew)
- </strong>
- <br>
- The Open University of Israel, 2011.
- </li>
-
- <li> J.-L. Guermond, A. Salgado
- <br>
- <strong>Error analysis of a fractional time-stepping technique for
- incompressible
- flows with variable density.
- </strong>
- <br>
- SIAM J. of Numerical Analysis, vol. 49, pp. 917-944, 2011.
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, J. Held, T. Leicht
- <br>
- <strong>Adjoint-based error estimation and adaptive mesh refinement
- for the RANS and k-ω turbulence model equations
- </strong>
- <br>
- J. Comput. Phys., vol. 230, pp. 4268-4284, 2011.
- </li>
-
- <li> T. Heister
- <br>
- <strong>A Massively Parallel Finite Element Framework with
- Application to Incompressible Flows</strong>
- <br>
- Ph.D. thesis, University of Göttingen, Germany, 2011
- </li>
-
- <li> L. Heltai, F. Costanzo
- <br>
- <strong>Variational implementation of immersed finite
- element methods
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 229–232, pp. 110–127, 2012.
- </li>
-
- <li> M. Hinze, M. Kunkel, M. Vierling
- <br>
- <strong>POD model order reduction of drift-diffusion equations in electrical networks
- </strong>
- <br>
- in: Model Reduction for Circuit Simulation, P. Benner,
- M. Hinze, and J. ter Maten (eds.), Lecture Notes in
- Electrical Engineering, vol. 74, Berlin-Heidelberg:
- Springer-Verlag, p. 177–192, 2011.
- </li>
-
- <li> M. Hinze, M. Kunkel, U. Matthes, M. Vierling
- <br>
- <strong>Model order reduction of integrated circuits in
- electrical networks</strong>
- <br>
- Hamburger Beiträge zur Angewandten Mathematik, Nr. 2011-14.
- </li>
-
- <li> M. Hinze, M. Kunkel, A. Steinbrecher, T. Stykel
- <br>
- <strong>Model order reduction of coupled circuit-device systems</strong>
- <br>
- Hamburger Beiträge zur Angewandten Mathematik, Nr. 2011-08.
- </li>
-
- <li> O. P. Iliev, R. D. Lazarov, J. Willems
- <br>
- <strong>Variational multiscale finite element method for flows in
- highly porous media</strong>
- <br>
- SIAM Multiscale Modeling and Simulation, submitted, 2011
- </li>
-
- <li> <a
- href="http://numerik.uni-hd.de/~baer"
- target="_top">B. Janssen</a>, G. Kanschat
- <br>
- <strong>Adaptive multilevel methods with local smoothing</strong>
- <br>
- submitted, 2010.
- </li>
-
- <li> G. Jegert, A. Kersch, W. Weinreich, P. Lugli
- <br>
- <strong>Monte Carlo Simulation of Leakage Currents in
- TiN/ZrO<sub>2</sub>/TiN Capacitors</strong>
- <br>
- IEEE Transactions on Electron Devices, vol. 58, pp. 327-334, 2011.
- </li>
-
- <li> N. Johansson
- <br>
- <strong> Implementation of a standard level set method for
- incompressible two-phase flow simulations</strong>
- <br>
- Master's thesis, Uppsala University, Uppsala, Sweden, 2011.
- </li>
-
-
- <li> J. Joos, T. Carraro, M. Ender, B. Rüger, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>Detailed Microstructure Analysis and 3D Simulations of Porous Electrodes</strong>
- <br>
- ECS Trans. 35, pp. 2357-2368, 2011.
- </li>
-
- <li> F. Keller, H. Nirschl, W. Dörfler
- <br>
- <strong>Primary charge effects on prolate spheroids with moderate aspect ratios
- </strong>
- <br>
- Journal of Colloid and Interface Science, vol. 363, pp. 690-702, 2011.
- </li>
-
- <li> K. Kormann, M. Kronbichler
- <br>
- <strong>Parallel finite element operator application: Graph
- partitioning and coloring</strong>
- <br>
- In proceedings of the 2011 IEEE 7th international conference
- on e-Science, pp. 332-339, 2011.
- </li>
-
- <li> M. Kronbichler
- <br>
- <strong>Computational Techniques for Coupled Flow-Transport Problems
- </strong>
- <br>
- PhD Thesis, Uppsala University, Uppsala, Sweden, 2011.
- </li>
-
- <li> M. Kronbichler, C. Walker, G. Kreiss, B. Müller
- <br>
- <strong>Multiscale modeling of capillary-driven contact
- line dynamics
- </strong>
- <br>
- submitted, 2011.
- </li>
-
- <li>
- W. Layton, L. Röhe, H. Tran
- <br>
- <strong>Explicitly uncoupled VMS stabilization of fluid flow
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 200, pp. 3183-3199, 2011.
- </li>
-
- <li> T. Leicht, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Error estimation and hp-adaptive mesh refinement for
- discontinuous Galerkin methods
- </strong>
- <br>
- In Z. J. Wang, editor, Adaptive High-Order Methods in
- Computational Fluid Dynamics - with applications in aerospace
- engineering, World Science Books, pp. 67-94, 2011.
- </li>
-
- <li> T. Leicht, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Goal-oriented error estimation and hp-adaptive mesh
- refinement for aerodynamic flows.
- </strong>
- <br>
- 49<sup>th</sup> AIAA Aerospace Sciences Meeting AIAA 2011-212, 2011.
- </li>
-
- <li>
- K. Leonard
- <br>
- <strong>Multiphase Modelling of Tissue Engineering
- </strong>
- <br>
- Proceedings of the University of Oxford Department of
- Computer Science Student Conference 2011, pp. 18-19, 2011.
- </li>
-
- <li>
- J. Löwe, G. Lube, L. Röhe
- <br>
- <strong>A Projection-Based Variational Multiscale Method for
- the Incompressible Navier–Stokes/Fourier Model
- </strong>
- <br>
- BAIL 2010 - Boundary and Interior Layers, Computational and
- Asymptitic Methods. Lecture Notes in Computational Science
- and Engineering, Volume 81, pp. 165-175, 2011.
- </li>
-
- <li> C. E. Michoski, J. A. Evans, P. G. Schmitz
- <br>
- <strong>Modeling Chemical Reactors I: Quiescent Reactors
- </strong>
- <br>
- Preprint, arXiv, 2010
- </li>
-
- <li> M. T. Myers, B. H. Sencer, L. Shao
- <br>
- <strong>Multi-scale modeling of localized heating caused by ion bombardment
- </strong>
- <br>
- Nuclear Instruments and Methods in Physics Research Section
- B: Beam Interactions with Materials and Atoms, in press,
- 2011.
- <!-- http://www.sciencedirect.com/science/article/pii/S0168583X11000760 -->
- </li>
-
- <li> A. Nigro, S. Renda, C. De
- Bartolo, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, F. Bassi
- <br>
- <strong>A discontinuous Galerkin method for laminar low Mach number flows
- </strong>
- <br>
- 66th National Congress ATI in Rende, Italy, 5-9
- Sept. 2011. University of Calabria, 2011.
- </li>
-
- <li> R. H. Nochetto, A. Salgado, S. W. Walker
- <br>
- <strong>A diffuse interface model for electrowetting
- with moving contact lines
- </strong>
- <br>
- Arxiv preprint arXiv:1112.5758. Submitted to M3AS, 2011.
- </li>
-
- <li>
- J. A. Norato, A. J. Wagoner Johnson
- <br>
- <strong>A Computational and Cellular Solids Approach to the
- Stiffness-Based Design of Bone Scaffolds
- </strong>
- <br>
- J. Biomech. Eng., vol. 133, 091003/1-8, 2011.
- </li>
-
- <li>
- J. Pearson, M. Stoll, A. Wathen
- <br>
- <strong>Regularization-robust preconditioners for
- time-dependent PDE constrained optimization problems
- </strong>
- <br>
- Preprint 1398, The Mathematical Institute, University of Oxford,
- submitted to SIAM, 2011.
- <!-- http://eprints.maths.ox.ac.uk/1398/ -->
- </li>
-
- <li> D. Pilipenko, M. Fleck, H. Emmerich
- <br>
- <strong>On numerical aspects of phase field fracture modelling
- </strong>
- <br>
- European Phys. J. Plus, vol. 126, 100/1-16, 2011.
- </li>
-
- <li> K. J. Raghuram
- <br>
- <strong>Higher Order Numerical Discretization on Scattered Grids
- </strong>
- <br>
- PhD thesis, University of California, Santa Barbara, 2011.
- </li>
-
- <li> M. J. Rapson, J. C. Tapson
- <br>
- <strong>Emulating the theoretical
- bifurcation diagram of a cochlear model in computation
- </strong>
- <br>
- Second African Conference on Computational Mechanics - AfriCOMP11,
- 2011
- </li>
-
- <li> M. J. Rapson, J. C. Tapson
- <br>
- <strong>Investigations into Time
- Stepping Methods for Cochlear Models
- </strong>
- <br>
- International Journal for Numerical Methods in Biomedical Engineering,
- accepted, 2011
- </li>
-
- <li> T. Richter, T. Wick
- <br>
- <strong>Fluid-Structure Interactions in ALE and
- Fully Eulerian Coordinates
- </strong>
- <br>
- PAMM, vol. 10, pp. 487-488, 2011.
- </li>
-
- <li> D. Riedlbauer
- <br>
- <strong>Thermomechanical Modelling and Simulation of Electron Beam Melting
- </strong>
- <br>
- Master's thesis, Friedrich-Alexander-University, Erlangen-Nuremberg, 2011.
- </li>
-
- <li>
- L. Röhe, G. Lube
- <br>
- <strong> Large-Eddy Simulation of Wall-Bounded Turbulent
- Flows: Layer-Adapted Meshes vs. Weak Dirichlet Boundary
- Conditions
- </strong>
- <br>
- BAIL 2010 - Boundary and Interior Layers, Computational and
- Asymptitic Methods. Lecture Notes in Computational Science
- and Engineering, Volume 81, pp. 197-205, 2011.
- </li>
-
- <li> A. Salgado
- <br>
- <strong>A diffuse interface fractional time-stepping technique
- for incompressible two-phase flows with moving contact lines
- </strong>
- <br>
- Submitted to Comp. Meths. Appl. Mech. Engrg., 2011.
- </li>
-
- <li> A. Salgado
- <br>
- <strong>A general framework for the implementation of
- mulitphysics and multidomain problems using the deal.II
- library
- </strong>
- <br>
- Submitted to Archive of Numerical Software, 2011.
- </li>
-
- <li>
- M. Stoll, J. Pearson, A. Wathen
- <br>
- <strong>Preconditioners for state constrained optimal
- control problems with Moreau-Yosida penalty function
- </strong>
- <br>
- Submitted to Numerical Linear Algebra with Applications,
- 2011.
- <!-- http://www.mpi-magdeburg.mpg.de/mpcsc/mitarbeiter/stollm/Data/SC_NLA11.pdf -->
- <!-- http://www.mpi-magdeburg.mpg.de/people/stollm/pub.html -->
- </li>
-
- <li>
- J. White, R. I. Borja
- <br>
- <strong>Block-preconditioned Newton–Krylov solvers for fully coupled flow and geomechanics
- </strong>
- <br>
- Comp. Geosc., vol. 15, pp. 647-659, 2011.
- </li>
-
- <li> T. Wick
- <br>
- <strong>Fluid-structure interactions using different mesh motion techniques
- </strong>
- <br>
- Computers and Structures, vol. 89, pp. 1456-1467, 2011.
- </li>
-
- <li> T. Wick
- <br>
- <strong>Adaptive finite element simulation of fluid-structure
- interaction
- </strong>
- <br>
- PhD thesis, University of Heidelberg, Germany, 2011.
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>
- <Br>
- <strong>A qualitative semi-classical treatment of an isolated
- semi-polar quantum dot
- </strong>
- <br>
- J. Phys.: Conf. Ser., 28(10), 2011.
- </li>
-
- <li> S. Zahedi, <a href="http://www.it.uu.se/katalog/martinkr"
- target="_top">M. Kronbichler</a>, G. Kreiss
- <br>
- <strong>Spurious currents in finite element based level set methods
- for two-phase flow</strong>
- <br>
- Int. J. Numer. Meth. Fluids., vol. 67, 2011.
- </li>
-
- <li> L. Zhou, B. Yazici
- <br>
- <strong>Discretization Error Analysis and Adaptive Meshing
- Algorithms for Fluorescence Diffuse Optical Tomography in the
- Presence of Measurement Noise</strong>
- <br>
- IEEE Trans. Image Processing, vol. 20, pp. 1094-1111, 2011.
- </li>
-
- <li> L. Zhu, D. Schötzau
- <br>
- <strong>A robust a posteriori error estimate for hp-adaptive DG
- methods for convection-diffusion equations
- </strong>
- <br>
- IMA J. Numer. Math., vol. 31, pp. 971-1005, 2011.
- </li>
- </ol>
-
-
-
- <a name="2010"> </a>
- <h2>Publications in 2010</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> M. Alexe, A. Sandu
- <br>
- <strong>Space-time adaptive solution of inverse problems with the
- discrete adjoint method
- </strong>
- <br>
- Technical Report TR-10-14, Computational Science Laboratory,
- Department of Computer Science, Virginia Tech, 2010.
- </li>
-
- <li> M. S. Alnæs, K.-A. Mardal
- <br>
- <strong>On the efficiency of symbolic computations combined with code
- generation for finite element methods
- </strong>
- <br>
- ACM Transactions on Mathematical Software, vol. 37, 8/1-26, 2010.
- </li>
-
- <li> M. Arroyo, A. DeSimone, L. Heltai
- <br>
- <strong>The role of membrane viscosity in the dynamics of fluid
- membranes
- </strong>
- <br>
- arXiv:1007.4934, 2010.
- <!-- http://arxiv.org/abs/1007.4934 -->
- </li>
-
- <li> W. Bangerth, M. Geiger, R. Rannacher
- <br>
- <strong>Adaptive Galerkin finite element methods
- for the wave equation
- </strong>
- <br>
- Computational Methods in Applied Mathematics, vol. 10, pp.3-48, 2010.
- </li>
-
- <li> S. Bartle, A. McBride, B. D. Reddy
- <br>
- <strong>Shell finite elements, with applications in biomechanics</strong>
- <br>
- In: Kok, S. (Ed.): Proceedings of 7th South African Conference on
- Computational and Applied Mechanics (University of Pretoria, Pretoria,
- South Africa). 2010.
- </li>
-
- <li> A. Cangiani, R. Natalini
- <br>
- <strong>A spatial model of cellular molecular trafficking
- including active transport along microtubules</strong>
- <br>
- Journal of Theoretical Biology, vol. 267, pp. 614-625, 2010.
- </li>
-
- <li> C.-C. Chueh, M. Secanell, W. Bangerth, N. Djilali
- <br>
- <strong>Multi-level Adaptive Simulation of Transient Two-phase Flow in
- Heterogeneous Porous Media</strong>
- <br>
- Computers and Fluids, vol. 39, pp. 1585-1596, 2010.
- </li>
-
- <li> C.-C. Chueh
- <br>
- <strong>Integrated adaptive numerical methods for transient
- two-phase flow in heterogeneous porous medi</strong>
- <br>
- Ph.D. thesis, University of Victoria, 2010.
- </li>
-
- <li> T. Dally
- <br>
- <strong>FE-Modelladaptivität für P-Laplace
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2010
- </li>
-
- <li> M. Freyer, A. Ale, R. Schulz, M. Zientkowska,
- V. Ntziachristos, K.-H. Englmeier
- <br>
- <strong>Fast automatic segmentation of anatomical structures
- in x-ray computed tomography images to improve fluorescence
- molecular tomography reconstruction</strong>
- <br>
- Journal of Biomedical Optics, vol. 15, pp. 036006/1-8, 2010.
- <br>
- </li>
-
- <li> F. Freddi, M. Frémond
- <br>
- <strong>Collision and Fractures: a predictive theory
- </strong>
- <br>
- European Journal of Mechanics - A/Solids, vol. 29, pp. 998-1007, 2010.
- </li>
-
- <li> F. Freddi, G. Royer-Carfagni
- <br>
- <strong>Regularized Variational Theories of Fracture: a
- Unified Approach</strong>
- <br>
- Journal of the Mechanics and Physics of Solids, vol. 58,
- pp. 1154-1174, 2010.
- </li>
-
- <li> P. Ghysels, G. Samaey, P. Van Liedekerke, E. Tijskens,
- H. Ramon, D. Roose
- <br>
- <strong>Multiscale modeling of viscoelastic plant tissue
- </strong>
- <br>
- Int. J. Multisc. Comput. Engrg., vol. 8, pp. 379-396, 2010
- </li>
-
- <li> P. Ghysels, G. Samaey, P. Van Liedekerke, E. Tijskens,
- H. Ramon, D. Roose
- <br>
- <strong>Coarse implicit time integration of a cellular scale particle
- model for plant tissue deformation
- </strong>
- <br>
- Int. J. Multisc. Comput. Engrg., vol. 8, pp. 411-422, 2010
- </li>
-
- <li> V. Girault, F. Murat, A. Salgado
- <br>
- <strong>Finite element discretization of Darcy's equations with
- pressure dependent porosity.
- </strong>
- <br>
- M2AN, vol. 44, pp. 1155-1191, 2010
- </li>
-
- <li> M. Guven, L. Reilly-Raska, L. Zhou, B. Yazici
- <br>
- <strong>Discretization Error Analysis and Adaptive Meshing
- Algorithms for Fluorescence Diffuse Optical Tomography: Part
- I</strong>
- <br>
- IEEE Trans. Medical Imaging, vol. 29, pp. 217-229, 2010
- </li>
-
- <li> M. Guven, L. Zhou, L. Reilly-Raska, B. Yazici
- <br>
- <strong>Discretization Error Analysis and Adaptive Meshing
- Algorithms for Fluorescence Diffuse Optical Tomography: Part
- II</strong>
- <br>
- IEEE Trans. Medical Imaging, vol. 29, pp. 230-245, 2010
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, J. Held, T. Leicht, F. Prill
- <br>
- <strong>Discontinuous Galerkin methods for computational aerodynamics
- — 3D adaptive flow simulation with the DLR PADGE code
- </strong>
- <br>
- Aerospace Science and Technology, vol. 14, pp. 512-529, 2010.
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, J. Held, T. Leicht, F. Prill
- <br>
- <strong>Error estimation and adaptive mesh refinement for aerodynamic flows
- </strong>
- <br>
- In N. Kroll, H. Bieler, H. Deconinck, V. Couallier, H. van der Ven
- and K. Sorensen, editors, ADIGMA - A European Initiative on the
- Development of Adaptive Higher-Order Variational Methods for
- Aerospace Applications,
- <br>
- vol. 113 of Notes on numerical fluid mechanics and
- multidisciplinary design, pp. 339-353, Springer, 2010.
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Error estimation and adaptive mesh refinement for aerodynamic flows</strong>
- <br>
- In H. Deconinck, editor,
- VKI LS 2010-01: 36th CFD/ADIGMA course on hp-adaptive and
- hp-multigrid methods, Oct. 26-30, 2009.
- <br>
- Von Karman Institute for Fluid Dynamics, Rhode Saint Genese,
- Belgium, 2010.
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, T. Leicht
- <br>
- <strong>Discontinuous Galerkin Verfahren in der Aerodynamik:
- Höhere Ordnung, Fehlerschätzung und Gitteradaption
- </strong>
- <br>
- STAB Mitteilungen. 17. DGLR-Fach-Symposium der STAB, 9.-10. Nov. 2010, Berlin, 2010.
- </li>
-
- <li> T. Heister, G. Lube, G. Rapin
- <br>
- <strong>On robust parallel preconditioning for incompressible
- flow problems</strong>
- <br>
- In Numerical Mathematics and Advanced Applications, ENUMATH 2009.
- Springer, Berlin, 2010.
- </li>
-
- <li> T. Heister, M. Kronbichler, W. Bangerth
- <br>
- <strong>Generic Finite Element programming for massively parallel
- flow simulations</strong>
- <br>
- Eccomas CFD 2010 proceedings, 2010.
- </li>
-
- <li> T. Heister, M. Kronbichler, W. Bangerth
- <br>
- <strong>Massively Parallel Finite Element Programming</strong>
- <br>
- Recent Advances in the Message Passing Interface,
- Lecture Notes in Computer Science, vol. 6305/2010, pp. 122-131,
- 2010.
- </li>
-
- <li> M. Hinze, M. Kunkel
- <br>
- <strong>Discrete empirical interpolation in POD Model Order
- Reduction of Drift-Diffusion Equations in Electrical
- Networks</strong>
- <br>
- Scientific Computing in Electrical Engineering, SCEE 2010
- Mathematics in Industry, Volume 16, Part 5, 423-431, 2012.
- </li>
-
- <li> M. Hinze, M. Kunkel
- <br>
- <strong>Residual Based Sampling in POD Model Order Reduction
- of Drift-Diffusion Equations in Parametrized Electrical
- Networks</strong>
- <br>
- arXiv:1003.0551v1 [math.NA], 2010.
- </li>
-
- <li> O. P. Iliev, R. D. Lazarov, J. Willems
- <br>
- <strong>Discontinuous Galerkin Subgrid Finite Element Method for
- Heterogeneous Brinkman Equations</strong>
- <br>
- Large-Scale Scientific Computing, Lectures Notes in Computer Science,
- vol. 5910, pp. 14-25, 2010
- </li>
-
- <li> O. P. Iliev, R. D. Lazarov, J. Willems
- <br>
- <strong>Fast numerical upscaling of heat equation for fibrous
- materials</strong>
- <br>
- J. Computing and Visualization in Science, vol. 13, pp. 275-285, 2010
- </li>
-
- <li> <a
- href="http://numerik.uni-hd.de/~baer"
- target="_top">B. Janssen</a>,
- <a
- href="http://numerik.uni-hd.de/~twick"
- target="_top">T. Wick</a>
- <br>
- <strong>Block preconditioning with Schur complements
- for monolithic fluid-structure interactions</strong>
- <br>
- Proceedings of the Eccomas CFD 2010 conference,
- J. C. F. Pereira and A. Sequeira (eds.), 2010.
- </li>
-
- <li> J. Joos, B. Rüger, T. Carraro, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>Electrode Reconstruction by FIB/SEM and Microstructure
- Modeling</strong>
- <br>
- ECS Trans. 28, pp. 81-91, 2010.
- </li>
-
- <li> G. Kanschat, B. Rivière
- <br>
- <strong>A strongly conservative finite element method for the coupling
- of Stokes and Darcy flow
- </strong>
- <br>
- J. Computational Physics, vol. 229, pp. 5933-5943, 2010
- </li>
-
- <li> F. Keller, M. Feist, H. Nirschl, W. Dörfler
- <br>
- <strong>Investigation of the nonlinear effects during the
- sedimentation process of a charged colloidal particle by
- direct numerical simulation
- </strong>
- <br>
- Journal of Colloid and Interface Science, vol. 344, pp. 228-236, 2010.
- </li>
-
- <li> S. Kim, J. E. Pasciak
- <br>
- <strong>Analysis of a Cartesian PML approximation to acoustic
- scattering problems in R<sup>2</sup></strong>
- <br>
- J. Math. Anal. Appl., vol. 370, pp. 168-186, 2010
- </li>
-
- <li>
- R. King, V. Mehrmann, W. Nitsche
- <br>
- <strong>Active Flow Control—A Mathematical Challenge</strong>
- <br>
- Production Factor Mathematics, Part 1, pp. 73-80, 2010
- </li>
-
- <li>
- R. King, V. Mehrmann, W. Nitsche
- <br>
- <strong>Aktive Strömungsbeeinflussung — Eine
- Mathematische Herausforderung</strong>
- <br>
- Produktionsfaktor Mathematik, Part 2, pp. 99-109, 2010
- </li>
-
- <li>
- T. Leicht, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Error estimation and anisotropic mesh refinement for
- 3d laminar aerodynamic flow simulations
- </strong>
- <br>
- J. Comput. Phys., vol. 229, pp. 7344-7360, 2010.
- </li>
-
- <li>
- T. Leicht, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Error estimation and anisotropic mesh refinement for
- aerodynamic flow simulations
- </strong>
- <br>
- In Numerical Mathematics and Advanced Applications, ENUMATH
- 2009, pp. 579-587. Springer, Berlin, 2010.
- </li>
-
- <li>
- G. Lube, B. Tews
- <br>
- <strong>Optimal control of singularly perturbed
- advection-diffusion-reaction problems</strong>
- <br>
- Math. Model. Meths. Appl. Sc., Vol. 20, No. 3, 375-395, 2010.
- (<a href="http://dx.doi.org/10.1142/S0218202510004271">DOI</a>)<br>
- Preprint 2008-15, Institute for Numerical and Applied
- Mathematics, University of Göttingen, Germany, 2008
- </li>
-
- <li> C. P. T. Neuen
- <br>
- <strong>A multiscale approach to the Poisson-Nernst-Planck equation
- </strong>
- <br>
- Diploma Thesis, University of Bonn, Germany, 2010
- </li>
-
- <li>
- A. Nigro, C. De Bartolo, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, F. Bassi
- <br>
- <strong>Discontinuous Galerkin solution of preconditioned Euler equations for very low Mach number flows
- </strong>
- <br>
- Int. J. Numer. Meth. Fluids, vol. 63, no. 4, pp. 449-467, 2010.
- </li>
-
- <li>
- F. Prill
- <br>
- <strong>Diskontinuierliche Galerkin-Methoden und schnelle iterative
- Löser zur Simulation kompressibler Strömungen
- </strong>
- <br>
- PhD thesis, TU Hamburg-Harburg, 2010. (in German)
- <br>
- Also available as DLR-FB 2010-17, DLR, 2010. ISSN 1434-8454.
- </li>
-
- <li> M. J. Rapson, J. C. Tapson
- <br>
- <strong>Capturing low‐frequency
- cochlear impedance in time domain models: The role of viscosity
- </strong>
- <br>
- J. Acoust. Soc. Am. Volume 127, Issue 3, pp. 1869-1869, 2010.
- </li>
-
- <li> K. Rupp
- <br>
- <strong>Symbolic integration at compile time in finite element methods
- </strong>
- <br>
- Proceedings of the 2010 International Symposium on Symbolic
- and Algebraic Computation, 347-354, 2010.
- </li>
-
- <li>
- T. Rees, M. Stoll, A. Wathen
- <br>
- <strong>All-at-once preconditioning in PDE-constrained
- optimization
- </strong>
- <br>
- Kybernetica, vol. 46, pp. 341-360, 2010.
- </li>
-
- <li>
- T. Richter, T. Wick
- <br>
- <strong>Finite Elements for Fluid-Structure
- Interaction in ALE and Fully Eulerian Coordinates
- </strong>
- <br>
- Comput. Meth. Appl. Mech. Engrg., vol. 199, pp. 2633-2642, 2010.
- </li>
-
- <li>
- L. Röhe, G. Lube
- <br>
- <strong>Analysis of a variational multiscale method for large-eddy
- simulation and its application to homogeneous isotropic turbulence
- </strong>
- <br>
- Comput. Meth. Appl. Mech. Engrg., vol. 199, pp. 2331-2342, 2010.
- </li>
-
- <li>
- A. Salgado
- <br>
- <strong>Approximation Techniques for Incompressible Flows
- with Heterogeneous Properties</strong>
- <br>
- Ph.D. thesis, Texas A&M University, 2010.
- </li>
-
- <li> R. Schulz, A. Ale, A. Sarantopoulos, M. Freyer, E. Soehngen,
- M. Zientkowska, V. Ntziachristos
- <br>
- <strong>Hybrid System for Simultaneous Fluorescence and X-Ray
- Computed Tomography</strong>
- <br>
- IEEE Trans. Medical Imaging, vol. 29, pp. 465-473, 2010
- </li>
-
- <li> M. Secanell, R. Songprakorp, N. Djilali, A. Suleman
- <br>
- <strong>Optimization of a proton exchange membrane fuel cell
- electrode assembly
- </strong>
- <br>
- Structural and Multidisciplinary Optimization, vol. 40, pp. 563-583,
- 2010
- </li>
-
- <li>
- M. Steigemann, M. Specovius-Neugebauer, M. Fulland, H. A. Richard
- <br>
- <strong>Simulation of crack paths in functionally graded materials
- </strong>
- <br>
- Engineering Fracture Mechanics, vol. 77, pp. 2145-2157, 2010
- </li>
-
- <li>
- M. Stoll, A. Wathen
- <br>
- <strong>All-at-once preconditioning of time-dependent PDE-constrained
- optimization problems
- </strong>
- <br>
- Preprint 1017, University of Oxford, 2010.
- </li>
-
- <li>
- B. Turcksin, J. C. Ragusa, W. Bangerth
- <br>
- <strong>Goal-oriented h-adaptivity for the multigroup SP<sub>N</sub>
- equations
- </strong>
- <br>
- Nuclear Science and Engineering, vol. 165, pp. 305-319, 2010.
- </li>
-
- <li> M. Vdroljak
- <br>
- <strong>On Hashin-Shtrikman bounds for mixtures of two isotropic
- materials
- </strong>
- <br>
- Nonlinear Analysis: Real world applications, vol. 11, pp. 4597-4606, 2010
- </li>
-
- <li> C. Weiler
- <br>
- <strong>Stromfunktionsformulierung der
- Navier-Stokes-Gleichungen und Methoden der
- Druckrekonstruktion
- </strong>
- <br>
- Diploma Thesis, University of Heidelberg, Germany, 2010
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>, R. Armiento
- <Br>
- <strong>Strategies for <i>h</i>-adaptive refinement for a
- finite element treatment of harmonic oscillator
- Schrödinger eigenproblem
- </strong>
- <br>
- Commun. Theor. Phys. (Beijing, China), vol. 53(6),
- pp. 1017-1023, 2010.
- </li>
-
- <li>
- L. Zhu
- <br>
- <strong>Robust a posteriori error estimation for discontinuous
- Galerkin methods for convection-diffusion equations
- </strong>
- <br>
- Ph.D. thesis, University of British Columbia, 2010
- </li>
- </ol>
-
- <a name="2009"> </a>
- <h2>Publications in 2009</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. Joshi
- <br>
- <strong>Adaptive finite element methods for nonlinear inverse
- problems
- </strong>
- <br>
- Proceedings of the 2009 ACM Symposium on Applied Computing, 2009.
- </li>
-
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, O. Kayser-Herold
- <br>
- <strong>Data Structures and Requirements for hp Finite Element
- Software
- </strong>
- <br>
- ACM Trans. Math. Softw., vol. 36, pp. 4/1-31, 2009.
- </li>
-
- <li> S. Bartle
- <br>
- <strong>Shell finite elements with applications in biomechanics</strong>
- <br>
- M.Sc. thesis, University of Cape Town, South Africa, 2009.
- </li>
-
- <li>
- F. Bassi, C. De Bartolo, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, A. Nigro
- <br>
- <strong>A discontinuous Galerkin method for inviscid low Mach number flows
- </strong>
- <br>
- J. Comput. Phys., vol. 228, no. 11, pp. 3996-4011, 2009.
- </li>
-
- <li> B. Brendel, T. Nielsen
- <br>
- <strong>Selection of optimal wavelengths for spectral reconstruction
- in diffuse optical tomography</strong>
- <br>
- J. Biomed. Optics, vol. 14, 034041/1-034041/10, 2009.
- </li>
-
- <li>C. Clason, P. Hepperger
- <br>
- <strong>A forward approach to numerical data assimilation</strong>
- <br>
- SIAM J. Sc. Comput., vol. 31, pp. 3090-3115, 2009
- </li>
-
- <li> B. Cockburn, G. Kanschat, and D. Schötzau
- <br>
- <strong>An equal-order DG method for the incompressible Navier-Stokes
- equations</strong>
- <br>
- J. Sci. Comput., vol. 40, pp. 188-210, 2009.
- <a href="http://dx.doi.org/10.1007/s10915-008-9261-1">DOI: 10.1007/s10915-008-9261-1</a>
- </li>
-
- <li> A. DeSimone, L. Heltai, C. Manigrasso
- <br>
- <strong>Tools for the Solution of PDEs Defined on
- Curved Manifolds with the deal.II Library
- </strong>
- <br>
- Prep. SISSA 42/2009/M.
- </li>
-
- <li>
- F. Freddi, G. Royer-Carfagni
- <br>
- <strong>From Non-Linear Elasticity to Linearized Theory:
- Examples Defying Intuition
- </strong>
- <br>
- J. of Elasticity, vol. 96, pp. 1-26, 2009
- </li>
-
- <li>
- F. Freddi, G. Royer-Carfagni
- <br>
- <strong>Variational models for cleavage and shear fractures
- </strong>
- <br>
- Proceedings of the XIX Congresso Aimeta, Ancona, 2009.
- </li>
-
- <li> T. George, A. Gupta, V. Sarin
- <br>
- <strong>An empirical analysis of the performance of iterative
- solvers for SPD systems
- </strong>
- <br>
- IBM TJ Watson Research Center, Tech. Rep. RC24737, 2009.
- </li>
-
- <li>
- P. Ghysels, G. Samaey, B. Tijskens, P. Van Liedekerke,
- H. Ramon, D. Roose
- <br>
- <strong>Multi-scale simulation of plant tissue deformation
- using a model for individual cell mechanics
- </strong>
- <br>
- Phys. Biol., vol. 6, pp. 016009/1-14, 2009
- </li>
-
- <li>
- S. Gladkov, M. Stiemer, B. Svendsen
- <br>
- <strong>Phase-field-based modeling and simulation of solidification
- and deformation behavior of technological alloys
- </strong>
- <br>
- PAMM, vol. 8, pp. 10547-10548, 2009
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, M. Lukacova-Medvidova, F. Prill
- <br>
- <strong>Efficient preconditioning for the discontinuous
- Galerkin finite element method by low-order elements</strong>
- <br>
- Appl. Numer. Math., vol. 59, no. 8, pp. 1737-1753, 2009
- </li>
-
- <li>H. K. Hesse,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Mesh Adaptive Multiple Shooting for Partial Differential
- Equations. Part I: Linear Quadratic Optimal Control Problems</strong>
- <br>
- Journal of Numerical Mathematics, vol. 17, pp. 195-217 2009
- </li>
-
- <li> D. Hyde, R. Schulz, D. Brooks, E. Miller, V. Ntziachristos
- <br>
- <strong>Performance dependence of hybrid x-ray computed
- tomography/fluorescence molecular tomography on the optical
- forward problem</strong>
- <br>
- J. Optical Soc. Amer., vol. 26, pp. 919-923, 2009
- </li>
-
- <li> T. Jetzfellner, D. Razansky, A. Rosenthal, R. Schulz,
- K.-H. Englmeier, V. Ntziachristos
- <br>
- <strong>Performance of iterative optoacoustic tomography with
- experimental data</strong>
- <br>
- Appl. Phys. Lett., vol. 95, pp. 013703/1-3, 2009
- </li>
-
- <li> J. Jung
- <br>
- <strong>Mehrgitterverfahren für FE-Modelle 4. Ordnung
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2009
- </li>
-
- <li>
- S. Kim
- <br>
- <strong>Analysis of a PML method applied to computation of
- resonances in open systems and acoustic scattering problems</strong>
- <br>
- Ph.D. thesis, Texas A&M University, 2009
- </li>
-
- <li>
- S. Kim, J. E. Pasciak
- <br>
- <strong>The computation of resonances in open systems using a
- perfectly matched layer</strong>
- <br>
- Math. Comp., vol. 78, pp. 1375-1398, 2009
- </li>
-
- <li> N. Klein
- <br>
- <strong>Modelladaptive FE-Techniken bei Elastizitätsproblemen
- mit großen Verformungen
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2009
- </li>
-
- <li> J. Lorentzon
- <br>
- <strong>Fluid-structure interaction (FSI) case study of a cantilever
- using OpenFOAM and DEAL.II with application to VIV
- </strong>
- <br>
- Master's thesis, Lunds Institute of Technology, Sweden, 2009
- </li>
-
- <li>
- G. Matthies, G. Lube, L. Röhe
- <br>
- <strong>Some remarks on streamline-diffusion methods for inf-sup
- stable discretisations of the generalised Oseen problem
- </strong>
- <br>
- Comp. Meths. Appl. Math. 9 (2009) 4, 1-23.
- </li>
-
- <li> A. M. McMahon
- <br>
- <strong>Modelling the Flow Behaviour of Gas Bubbles in a
- Bubble Column</strong>
- <br>
- M.Sc. thesis, University of Cape Town, South Africa, 2009.
- </li>
-
- <li>
- S. T. Miller, F. Costanzo
- <br>
- <strong>A numerical verification for an unconditionally
- stable FEM for elastodynamics</strong>
- <br>
- Comp. Mech., vol. 43, pp. 223-237, 2009
- </li>
-
- <li>
- M. Olshanskii, G. Lube, T. Heister, J. Löwe
- <br>
- <strong>Grad-div stabilization and subgrid pressure models for the
- incompressible Navier–Stokes equations</strong>
- <br>
- Comp. Meth. Appl. Mech. Eng. V. 198, pp. 3975-3988, 2009
- </li>
-
- <li>
- J. S. Pitt, F. Costanzo
- <br>
- <strong>An adaptive h-refinement algorithm for local damage
- models </strong>
- <br>
- Algorithms, vol. 2, pp. 1281-1300, 2009
- </li>
-
- <li>
- L. Plagne, F. Hülsemann, D. Barthou, J. Jaeger
- <br>
- <strong>Parallel expression template for large vectors
- </strong>
- <br>
- Proceedings of the 8th workshop on Parallel/High-Performance
- Object-Oriented Scientific Computing, European Conference on
- Object-Oriented Programming, 2009.
- </li>
-
- <li> F. Prill, M. Lukacova-Medvidova,
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Smoothed aggregation multigrid for the discontinuous
- Galerkin method
- </strong>
- <br>
- SIAM J. Sci. Comput., vol. 31, no. 5, pp. 3503-3528, 2009.
- </li>
-
- <li>
- F. Prill, M. Lukacova-Medvidova,
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong>A multilevel discontinuous Galerkin method for the
- compressible Navier-Stokes equations
- </strong>
- <br>
- In A. Handlovicova, P. Frolkovic, K. Mikula and D. Sevcovic, eds.,
- Proceedings of ALGORITMY 2009. 18th Conference on Scientific
- Computing Vysoke Tatry - Podbanske, Slovakia, March 15 - 20,
- 2009.
- </li>
-
- <li>
- A. Q. Raeini
- <br>
- <strong>Fractured reservoir simulation using finite element method
- with logarithmic shape functions (in Persian)
- </strong>
- <br>
- M. Sc. thesis, Sharif University of Technology, Iran, 2009.
- </li>
-
- <li>
- H. R. Ramay and M. Vendelin
- <br>
- <strong>Diffusion restrictions surrounding mitochondria: a
- mathematical model of heart muscle fibers
- </strong>
- <br>
- Biophys. J., vol. 97, pp. 443-452, 2009.
- </li>
-
- <li>
- R. Rannacher
- <br>
- <strong>Adaptive Finite Element Discretization of Flow
- Problems for Goal-Oriented Model Reduction </strong>
- <br>
- In: Computational Fluid Dynamics 2008 (H. Choi, H.
- G. Choi and J. Y. Yoo, eds.), pp. 31-45, Springer, 2009.
- </li>
-
- <li> B. Rüger, J. Joos, T. Carraro, A. Weber, E. Ivers-Tiffée
- <br>
- <strong>3D Electrode Microstructure Reconstruction and
- Modelling</strong>
- <br>
- ECS Trans. 25, pp. 1211-1220, 2009.
- </li>
-
- <li>
- D. Schötzau, L. Zhu
- <br>
- <strong>A robust a-posteriori error estimator for discontinuous
- Galerkin methods for convection-diffusion equations
- </strong>
- <br>
- Appl. Numer. Math., vol. 59, pp. 2236-2255, 2009
- </li>
-
- <li> N. Schröder
- <br>
- <strong>Simulation eines mikrofluidischen Kanals mit deal.II
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2009
- </li>
-
- <li> Y. Wang
- <br>
- <strong>Adaptive mesh refinement solution techniques for the
- multigrid S<sub>N</sub> transport equation using a
- higher-order discontinuous finite element method
- </strong>
- <br>
- Ph.D. thesis, Texas A&M University, 2009
- </li>
-
- <li> Y. Wang, W. Bangerth, J. Ragusa
- <br>
- <strong>Three-dimensional h-adaptivity for the multigroup neutron
- diffusion equations
- </strong>
- <br>
- Progress in Nuclear Energy, vol. 51, pp. 543-555, 2009
- </li>
-
- <li> S. Wanka
- <br>
- <strong>Grundkonzepte zur Modelladaptivität bei Hindernisproblemen
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2009
- </li>
-
- <li> J. White
- <br>
- <strong>Stabilized finite element methods for coupled flow
- and geomechanics</strong>
- <br>
- PhD thesis, Stanford University, 2009.
- </li>
-
- <li> J. Willems
- <br>
- <strong>Numerical Upscaling for Multiscale Flow Problems - Analysis
- and Algorithms </strong>
- <br>
- Südwestdeutscher Verlag für Hochschulschriften, 2009.
- </li>
-
- <li> J. Willems
- <br>
- <strong>Numerical upscaling for multiscale flow problems
- </strong>
- <br>
- Ph.D. thesis, University of Kaiserslautern, Germany, 2009
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>, E. Romero, and J. E. Roman
- <Br>
- <strong>Finite element solution of the stationary
- Schrödinger equation using standard computational tools
- </strong>
- <br>
- In Proceedings of the International Conference on
- Computational and Mathematical Methods in Science and
- Engineering 2009, Gijon Asturias, Spain, July
- 2009.
- </li>
-
- <li> <a href="http://www.ippt.gov.pl/~tyoung"
- target="_top">T. D. Young</a>
- <br>
- <strong>Exemplifying quantum systems in a finite element
- basis
- </strong>
- <br>
- AIP Conf. Proc., vol. 1148, pp. 285-289 2009.
- </li>
-
- <li> R. Ziegler, B. Brendel, A. Schipper, R. Harbers, M. van Beek,
- H. Rinneberg, T. Nielsen
- <br>
- <strong>Investigation of detection limits for diffuse optical
- tomography systems: I. Theory and experiment
- </strong>
- <br>
- Phys. Med. Biol., vol. 54, pp. 399-412, 2009
- </li>
-
- <li> R. Ziegler, B. Brendel,
- H. Rinneberg, T. Nielsen
- <br>
- <strong>Investigation of detection limits for diffuse optical
- tomography systems: II. Analysis of slab and cup geometry for
- breast imaging
- </strong>
- <br>
- Phys. Med. Biol., vol. 54, pp. 413-431, 2009
- </li>
-
- <li> R. Ziegler, T. Nielsen, T. Koehler, D. Grosnick,
- O. Steinkellner, A. Hagen, R. Macdonald, H. Rinneberg
- <br>
- <strong>Nonlinear reconstruction of absorption and
- fluorescence contrast from measured diffuse transmittance and
- reflectance of a compressed-breast-simulating phantom
- </strong>
- <br>
- Applied Optics, vol. 48, pp. 4651-4662, 2009
- </li>
- </ol>
-
-
-
- <a name="2008"> </a>
- <h2>Publications in 2008</h2>
-
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong>A framework for the adaptive finite element solution of
- large-scale inverse problems
- </strong>
- <br>
- SIAM J. Sci. Comput, vol. 30, pp. 2965-2989, 2008
- </li>
-
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. Joshi
- <br>
- <strong>Adaptive finite element methods for the solution of
- inverse problems in optical tomography
- </strong>
- <br>
- Inverse Problems, vol. 24, article 034011 (23 pages), 2008
- </li>
-
- <li> E. Bängtsson, B. Lund
- <br>
- <strong>A comparison between two solution techniques to solve
- the equations of glacially induced deformation of an elastic
- Earth
- </strong>
- <br>
- Int. J. Numer. Meth. Engrg., vol. 75, pp. 479-502, 2008
- </li>
-
- <li>
- M. Bartels, A. Joshi, J. C. Rasmussen, E. M. Sevick-Muraca,
- <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong>Post-image acquisition excitation light mitigation in NIR
- fluorescent tomography
- </strong>
- <br>
- Proceedings of the IEEE International
- Symposium on Biomedical Imaging, Arlington, VA, 2008
- </li>
-
- <li>
- B. Brendel, R. Ziegler, T. Nielsen
- <br>
- <strong>Algebraic reconstruction techniques for spectral
- reconstruction in diffuse optical tomography
- </strong>
- <br>
- Applied Optics, vol. 47, pp. 6392-6403, 2008
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/"
- target="_top">L. Heltai</a>,
- C. S. Peskin
- <br>
- <strong>On the hyper-elastic formulation of
- the immersed boundary method
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 197, pp. 2210-2231, 2008
- </li>
-
- <li> B. Carnes, G. F. Carey
- <br>
- <strong>Local boundary value problems for the error in FE
- approximation of non-linear diffusion systems
- </strong>
- <br>
- Int. J. for Numer. Methods Engrg., vol. 73,
- pp. 665-684, 2008
- </li>
-
- <li> N. Djilali, P. C. Sui
- <br>
- <strong>Transport phenomena in fuel cells: from microscale to
- macroscale
- </strong>
- <br>
- Int. J. of Comput. Fluid Dynam., vol. 22,
- pp. 115-133, 2008
- </li>
-
- <li> R. Fosdick, F. Freddi, G. Royer-Carfagni
- <br>
- <strong>Bifurcation instability in
- linear elasticity with the constraint of local injectivity
- </strong>
- <br>
- J. of Elasticity, vol. 90, pp. 99-126, 2008
- </li>
-
- <li>
- M. Geiger
- <br>
- <strong>Vergleich dreier Zeitschrittverahren zur numerischen
- Lösung der akustischen Wellengleichung</strong>
- <br>
- Diploma thesis, University of Heidelberg, Germany, 2008
- </li>
-
- <li>
- P. Ghysels, G. Samaey, B. Tijskens,
- H. Ramon, D. Roose
- <br>
- <strong>Multi-scale simulation of plant tissue deformation
- using a model for individual cell behavior
- </strong>
- <br>
- Report TW 522, Department of Computer Science, K.U. Leuven, Belgium,
- 2008
- <br>
-
- <li> C. Giavarini, M. L. Santarelli, R. Natalini, F. Freddi
- <br>
- <strong>A non linear model of
- sulphation of porous stones: numerical simulations and preliminary
- laboratory assessments
- </strong>
- <br>
- J. of Cultural Heritage, vol. 9, pp. 14-22, 2008
- </li>
-
- <li> <a href="http://www.math.unibas.ch/~grote/" target="_top">M. Grote</a>, <a
- href="http://www.math.unibas.ch/~schneeba/" target="_top">A.
- Schneebeli</a>, <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong>Interior penalty discontinuous Galerkin method for
- Maxwell's equations: optimal L<sup>2</sup>-norm estimates
- </strong>
- <br>
- IMA J. Numer. Anal., vol. 28, pp. 440-468, 2008
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Multitarget error estimation and adaptivity in aerodynamic flow simulations
- </strong>
- <br>
- SIAM J. Sci. Comput., vol. 31, no. 1, pp. 708-731, 2008
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Numerical Analysis of Higher Order Discontinuous Galerkin Finite Element Methods</strong>
- <br>
- In H. Deconinck, editor,
- VKI LS 2008-08: 35th CFD/ADIGMA course on very high order discretization methods, Oct. 13-17, 2008.
- <br>
- Von Karman Institute for Fluid Dynamics, Rhode Saint Genese, Belgium (2008).
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>An optimal order interior penalty discontinuous
- Galerkin discretization of the compressible Navier-Stokes
- equations
- </strong>
- <br>
- J. Comput. Phys., vol. 227, no. 22, pp. 9670-9685, 2008
- </li>
-
- <li>
- T. Heister
- <br>
- <strong>Vorkonditionierunsstrategien für das
- stabilisierte Oseen-Problem</strong>
- <br>
- Diploma thesis, University of Göttingen, Germany, 2008
- </li>
-
- <li><a
- href="http://www-dimat.unipv.it/heltai/"
- target="_top">L. Heltai</a>
- <br>
- <strong>On the stability of the finite element immersed
- boundary method</strong>
- <br>
- Computers and Structures, vol. 86, pp. 598-617, 2008
- </li>
-
- <li> A. Joshi, <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, E. Sevick
- <br>
- <strong>Non-Contact Fluorescence Optical Tomography with
- Adaptive Finite Element Methods
- </strong>
- <br>
- In: "Mathematical Methods in Biomedical Imaging and Intensity-Modulated
- Radiation Therapy (IMRT)", Y. Censor, M. Jiang and A.K. Louis (eds.),
- pp. 185-200,
- Birkhäuser, 2008
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Robust smoothers for high order discontinuous Galerkin
- discretizations of advection-diffusion problems</strong>
- <br>
- J. Comput. Appl. Math., vol. 218, pp. 53-60, 2008.
- <br>
- <a href="http://www.isc.tamu.edu/publications-reports/tr/0701.pdf">(Preprint)</a>
- </li>
-
- <li> <a
- href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>, <a
- href="http://www.math.ubc.ca/~schoetzau/"
- target="_top">D. Schötzau</a>
- <br>
- <strong>Energy norm a-posteriori error estimation for divergence-free
- discontinuous Galerkin approximations of the Navier-Stokes
- equations
- </strong>
- <br>
- Int. J. Numer. Methods Fluids, vol. 57, pp. 1093-1113, 2008.
- <a href="http://dx.doi.org/10.1002/fld.1795">DOI: 10.1002/fld.1795</a>
- </li>
-
- <li> D. K. Khalmanova, F. Costanzo
- <br>
- <strong>A space-time discontinuous Galerkin finite element method for
- fully coupled linear thermo-elasto-dynamic problems with strain and
- heat flux discontinuities
- </strong>
- <br>
- Comput. Meth. Appl. Mech. Engrg., vol. 197, pp. 1323-1342, 2008
- </li>
-
- <li> L. Khasina
- <br>
- <strong>Mathematische Behandlung von Mischungen
- elastoplastischer Substanzen
- </strong>
- <br>
- PhD thesis, University of Bonn, Germany, 2008
- </li>
-
- <li> M. Kronbichler, G. Kreiss
- <br>
- <strong>A hybrid level–set–Cahn–Hilliard model for
- two-phase flow
- </strong>
- <br>
- Proceedings of the 1st European Conference on Microfluidics, accepted
- for publication. Microfluidics 2008, Bologna, Italy, December
- 10–12, 2008.
- </li>
-
- <li>
- T. Leicht, <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Anisotropic mesh refinement for discontinuous Galerkin methods
- in two-dimensional aerodynamic flow simulations
- </strong>
- <br>
- Int. J. Numer. Meth. Fluids, vol. 56, no. 11, pp. 2111-2138, 2008
- </li>
-
- <li>
- J. Löwe
- <br>
- <strong>Stabilisierung durch lokale Projektion für
- inkompressible Strömungsprobleme</strong>
- <br>
- Diploma thesis, University of Göttingen, Germany, 2008
- </li>
-
- <li>
- M. Neytcheva and E. Bängtsson
- <br>
- <strong>Preconditioning of nonsymmetric saddle point systems as
- arising in modelling of viscoelastic problems
- </strong> <br>
- ETNA, vol. 29, pp. 193-211, 2008
- 2008
- </li>
-
- <li>
- J. S. Pitt, F. Costanzo
- <br>
- <strong>Theory and simulation of a brittle damage model in
- thermoelastodynamics
- </strong> <br>
- Proceedings of the 8th World Congress on Computational
- Mechanics (WCCM 8), Venice, Italy, 2008
- </li>
-
- <li>
- K. Schmid
- <br>
- <strong>Theory and numerics of a reconstruction algorithm for a
- problem from acoustic microscopy
- </strong> <br>
- Diploma thesis, Technical University of Munich, Germany,
- 2008
- </li>
-
- <li> M. Secanell, K. Karan, A. Suleman, N. Djilali
- <br>
- <strong>Optimal design of ultralow-platinum PEMFC anode electrodes
- </strong>
- <br>
- Journal of The Electrochemical Society, vol. 155, pp. B125-B134, 2008
- </li>
-
- <li> M. Secanell, R. Songprakorp, A. Suleman, N. Djilali
- <br>
- <strong>Multi-objective optimization of a polymer electrolyte
- fuel cell membrane electrode assembly
- </strong>
- <br>
- Energy & Environmental Science, vol. 1, pp. 378-388, 2008
- </li>
-
- <li> J. A. White, R. I. Borja
- <br>
- <strong>Stabilized low-order finite elements for coupled
- solid-deformation/fluid-diffusion and their application to
- fault zone transients
- </strong>
- <br>
- Comput. Meth. Appl. Mech. Engrg., vol. 197, pp. 4353-4366, 2008
- </li>
-
- <li> T. Wick
- <br>
- <strong>Untersuchung von Kopplungsmechanismen von
- Fluid-Struktur-Interaktion
- </strong>
- <br>
- Master's thesis, Universität Siegen, Germany, 2008
- </li>
-
- <li> R. Ziegler
- <br>
- <strong>Modeling photon transport and reconstruction of
- optical properties for performance assessment of laser and
- fluorescence mammographs and analysis of clinical data
- </strong>
- <br>
- PhD thesis, Freie Universität Berlin, 2008
- </li>
- </ol>
-
-
- <a name="2007"> </a>
- <h2>Publications in 2007</h2>
- <!-- Please enter alphabetically by name -->
- <ol>
- <li> N. Antonic, M. Vrdoljak
- <br>
- <strong>Gradient methods for multiple state optimal design problems
- </strong>
- <br>
- Ann. Univ. Ferrara, vol. 53, pp. 177-187, 2007
- </li>
-
- <li>
- P. F. Antonietti,
- <a href="http://www-dimat.unipv.it/heltai" >L. Heltai</a>
- <br>
- <strong>Numerical validation of a class of mixed
- discontinuous Galerkin methods for Darcy flow
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 196, pp. 4505-4520, 2007
- </li>
-
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>deal.II — a general-purpose object-oriented finite
- element library
- </strong>
- <br>
- ACM Transactions on Mathematical Software, vol. 33, no. 4, article
- 24, 2007
- </li>
-
- <li> <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. Joshi, E. Sevick
- <br>
- <strong>Inverse biomedical imaging using separately adapted meshes
- for parameters and forward model variables
- </strong>
- <br>
- Proceedings of the IEEE International Symposium on Biomedical Imaging,
- Arlington, VA, pp. 1368-1371, 2007
- </li>
-
- <li> E. Bängtsson, M. Neytcheva
- <br>
- <strong>Finite Element Block-Factorized Preconditioners
- </strong>
- <br>
- Technical Report 2007-008, Uppsala University, Sweden, 2007
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/" target="_top">L. Heltai</a>
- <br>
- <strong>On the CFL condition for the finite element immersed
- boundary method</strong>
- <br>
- Computers & Structures, vol. 85, pp. 775-783, 2007
- (<a href="http://dx.doi.org/10.1016/j.compstruc.2007.01.009" >DOI</a>)
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/"
- target="_top">L. Heltai</a>
- <br>
- <strong>Numerical stability of the finite element immersed boundary method</strong>
- <br>
- Mathematical Models and Methods in Applied Sciences, vol. 17,
- pp. 1479-1505, 2007
- </li>
-
- <li> M. Calhoun-Lopez, M. D. Gunzburger
- <br>
- <strong>The efficient implementation of a finite element,
- multi-resolution viscosity method for hyperbolic conservation
- laws
- </strong>
- <br>
- Journal of Computational Physics, vol. 225, pp. 1288-1313, 2007
- </li>
-
- <li> B. Carnes, G. F. Carey
- <br>
- <strong>Estimating spatial and parameter error in
- parameterized nonlinear reaction-diffusion equations
- </strong>
- <br>
- Communications in Numerical Methods in Engineering, vol. 23,
- pp. 835-854, 2007
- </li>
-
-
- <li> C. C. Douglas, M. J. Cole, P. Dostert, Y. Efendiev, R. E. Ewing,
- G. Haase, J. Hatcher, M. Iskandarani, C. R. Johnson, R. A. Lodder
- <br>
- <strong>Dynamically identifying and tracking contaminants in water
- bodies
- </strong>
- <br>
- International Conference on Computational Science ICCS 2007,
- vol. 4487 of Springer Lecture Notes in Computer Science,
- pp. 1002-1009, 2007
- </li>
-
- <li> F. Freddi, M. Frémond
- <br>
- <strong>Collision and Fractures: a predictive theory
- </strong>
- <br>
- Proceedings of the EuroSim Conference, Lubiana, Slovenia,
- 9-13 September, 2007
- </li>
-
- <li> P.K. Galenko, S. Reutzel, D. M. Herlach, D. Danilov, B. Nestler
- <br>
- <strong>Modelling of dendritic solidification in undercooled
- dilute Ni-Zr melts
- </strong>
- <br>
- Acta Materialia, vol. 55, pp. 6834-6842, 2007
- </li>
-
- <li> A. Garny, J. Cooper, P. J. Hunt
- <br>
- <strong>Toward a VPH/Physiome ToolKit
- </strong>
- <br>
- Wiley Interdisciplinary Reviews: Systems Biology and Medicine,
- vol. 2, pp. 134-147, 2010
- </li>
-
- <li> T. Ha, C. Shin
- <br>
- <strong>Magnetotelluric inversion via reverse time migration
- algorithm of seimic data
- </strong>
- <br>
- J. Comput. Phys., vol. 225, pp. 237-262, 2007
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Adjoint consistency analysis of Discontinuous Galerkin discretizations
- </strong>
- <br>
- SIAM J. Numer. Anal., vol. 45, no. 6, pp. 2671-2696, 2007
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Error estimation and adjoint based refinement for an adjoint
- consistent DG discretization of the compressible Euler equations
- </strong>
- <br>
- Int. J. Computing Science and Mathematics, vol. 1, pp. 207-220, 2007
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>DG discretizations for compressible flows: Adjoint
- consistency analysis, error estimation and adaptivity
- </strong>
- <br>
- In R. Rannacher, E. Süli, and R. Verführt, eds.,
- Adaptive Numerical Methods for PDEs, Mathematisches
- Forschungsinstitut Oberwolfach Report 29/2007, pp. 26-30, 2007
- </li>
-
- <li> P. Hepperger
- <br>
- <strong>Ein POD-basierter Ansatz zur numerischen Lösung eines
- Datenassimilationsproblems am Beispiel einer linearen
- Diffusions-Konvektions-Gleichung
- </strong> <br>
- Diploma thesis, Technical University of Munich, Germany,
- 2007</li>
-
- <li> Christian D. Kamm
- <br>
- <strong>A posteriori error estimation in numerical methods
- for solving self-adjoint eigenvalue problems
- </strong>
- <br>
- Diploma thesis, TU Berlin, Germany, 2007
- </li>
-
- <li> O. Kayser-Herold, H.G. Matthies
- <br>
- <strong>A unified least-squares formulation for fluid-structure interaction
- problems
- </strong>
- <br>
- Computers and Structures, vol. 85, pp. 998-1011, 2007
- </li>
-
- <li> <a
- href="http://numerik.uni-hd.de/~baer"
- target="_top">B. Janssen</a>,
- <br>
- <strong>Vergleich verschiedener Finite-Elemente-Approximationen
- zur numerischen Lösung der Plattengleichung</strong>
- <br>
- Diploma thesis, University of Heidelberg, Germany, 2007.
- </li>
-
- <li> A. Joshi, <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, R. Sharma, J. Rasmussen, W. Wang,
- E. Sevick
- <br>
- <strong>Molecular tomographic imaging of lymph nodes with
- NIR fluorescence
- </strong>
- <br>
- Proceedings of the IEEE International Symposium on Biomedical Imaging,
- Arlington, VA, pp. 564-567, 2007
- </li>
-
- <li> B. Nestler, D. Danilov, A. Bracchi,
- Y.-L. Huang, T. Niermann, M. Seibt and S. Schneider
- <br>
- <strong>A metallic glass composite: Phase-field simulations
- and experimental analysis of microstructure evolution
- </strong>
- <br>
- Materials Science and Engineering: A, vol. 452-453, pp. 8-14, 2007
- </li>
-
- <li>
- A. Nigro
- <br>
- <strong>Discontinuous Galerkin Methods for inviscid low Mach
- number flows
- </strong> <br>
- Ph.D. thesis, University of Calabria, 2007
- </li>
-
- <li> P. J. Phillips and M. F. Wheeler
- <br>
- <strong>A coupling of mixed and continuous Galerkin finite
- element methods for poroelasticity II: the discrete-in-time case
- </strong>
- <br>
- Computational Geosciences, vol. 11, pp. 145-158, 2007
- </li>
-
- <li> H.-J. Reinhardt, D. N. Hào, J. Frohne and F.-T. Suttmeier
- <br>
- <strong>Numerical solution of Inverse Heat Conduction
- Problems in two spatial dimensions
- </strong>
- <br>
- J. Inverse and Ill-Posed Problems, vol. 5, pp. 19-36, 2007
- </li>
-
- <li>
- L. Röhe
- <br>
- <strong>Residuale Stabilisierung für Finite Elemente Verfahren
- bei inkompressiblen Strömungen</strong>
- <br>
- Diploma thesis, University of Göttingen, Germany, 2007
- </li>
-
- <li> M. Schmidt
- <br>
- <strong>Systematic discretization of input/output maps and
- other contributions to the control of distributed parameter
- systems
- </strong>
- <br>
- Ph.D. thesis, TU Berlin, Germany, 2007
- </li>
-
- <li> M. Secanell, B. Carnes, A. Suleman, N. Djilali
- <br>
- <strong>Numerical optimization of proton exchange membrane fuel cell
- cathodes
- </strong>
- <br>
- Electrochimica Acta, vol. 52, pp. 2668-2682, 2007
- </li>
-
- <li> M. Secanell, K. Karan, A. Suleman, N. Djilali
- <br>
- <strong>Multi-variable optimization of PEMFC cathodes using
- an agglomerate model
- </strong>
- <br>
- Electrochimica Acta, vol. 52, pp. 6318-6337, 2007
- </li>
-
- <li>
- M. Steigemann, M. Fulland, M. Specovius-Neugebauer, H. A. Richard
- <br>
- <strong>Simulation of crack paths in functionally graded materials
- </strong>
- <br>
- PAMM, vol. 7, pp. 4030029-4030030, 2007
- </li>
-
- <li> M. Steigemann, M. Fulland
- <br>
- <strong>On the computation of the pure Neumann problem in
- 2-dimensional elasticity
- </strong>
- <br>
- International Journal of Fracture, vol. 146, pp. 265-277, 2007
- </li>
-
- <li> R. Ziegler, T. Nielsen, T. Koehler, D. Grosenick,
- O. Steinkellner, A. Hagen, R. Macdonald, H. Rinneberg
- <br>
- <strong>Reconstruction of absorption and fluorescence
- contrast for scanning time-domain fluorescence mammography
- </strong>
- <br>
- Optical Tomography and Spectroscopy of Tissue VII, Proc. SPIE
- vol. 6434, 64340H/1-11, 2007
- </li>
- </ol>
-
-
-
- <a name="2006"> </a>
- <h2>Publications in 2006</h2>
-
- <ol>
-
- <li> M. Allmaras
- <br>
- <strong>Optimal Design of Periodic Microstructures by the
- Inverse Homogenization Method
- </strong>
- <br>
- Diploma Thesis, Technical University Munich, Germany, 2006
- </li>
-
- <li> N. Antonic, M. Vrdoljak
- <br>
- <strong>Sequential laminates in multiple state optimal design problems
- </strong>
- <br>
- Mathematical Problems in Engineering, vol. 2006, pp. 1-14, 2006
- </li>
-
- <li>
- P. F. Antonietti
- <br>
- <strong>Domain decomposition, spectral correctness and
- numerical testing of discontinuous Galerkin methods
- </strong>
- <br>
- Ph.D. thesis, University of Pavia, Italy, 2007
- </li>
-
- <li> E. Bängtsson, B. Lund
- <br>
- <strong>A comparison between two approaches to solve the equations of
- isostasy
- </strong>
- <br>
- Institute for Parallel Processing (BIS 21++) Technical Report 2006-03,
- Bulgarian Academy of Sciences, 2006
- </li>
-
- <li> E. Bängtsson, B. Lund
- <br>
- <strong>A comparison between two approaches to solve the equations of
- isostasy
- </strong>
- <br>
- Technical Report 2006-051, Uppsala University, Sweden, 2006
- </li>
-
- <li> E. Bängtsson, M. Neytcheva
- <br>
- <strong>Numerical simulations of glacial rebound using
- preconditioned iterative solution methods
- </strong>
- <br>
- Applications of Mathematics, vol. 50, pp. 183-201, 2006
- </li>
-
- <li> E. Bängtsson, M. Neytcheva
- <br>
- <strong>An agglomerate multilevel preconditioner for linear
- isostasy saddle point problems
- </strong>
- <br>
- Proceedings of Large-Scale Scientific Computing: 5th
- International Conference (I. Lirkov, S. Margenov,
- J. Wasniewski, eds), pp. 113-120, 2006
- </li>
-
- <li> B. Carnes, N. Djilali
- <br>
- <strong>Analysis of coupled proton and water transport in a
- PEM fuel cell using the binary friction membrane model
- </strong>
- <br>
- Electrochimica Acta, vol. 52, pp. 1038-1052, 2007
- </li>
-
- <li> D. Danilov, B. Nestler
- <br>
- <strong>Phase-field simulations of eutectic solidification
- using an adaptive finite element method
- </strong>
- <br>
- International Journal of Modern Physics B, vol. 20,
- pp. 853-867, 2006
- </li>
-
- <li> J. Frohne
- <br>
- <strong>Numerische Lösung des inversen
- Wärmeleitproblems in zwei
- Ortsdimensionen zur Identifizierung von Randbedingungen
- </strong>
- <br>
- Diploma thesis, Universität Siegen, Germany, 2009
- </li>
-
- <li> <a href="http://www.math.unibas.ch/~grote/" target="_top">M. Grote</a>, <a
- href="http://www.math.unibas.ch/~schneeba/" target="_top">A.
- Schneebeli</a>, <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong> Discontinuous Galerkin Finite Element Method for the Wave Equation
- </strong>
- <br>
- SIAM J. Numer. Anal, vol. 44, pp. 2408-2431, 2006
- </li>
-
- <li> T. Ha, C. Shin
- <br>
- <strong>Two dimensional magnetotelluric inversion via reverse
- time migration algorithm
- </strong>
- <br>
- Abstracts of the SEG Annual Meeting in New Orleans,
- pp. 830-835, 2006
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Error estimation and adjoint-based adaptation in aerodynamics
- </strong>
- <br>
- In P. Wesseling, E. Onate, J. Periaux, eds.,
- Proceedings of the ECCOMAS CFD 2006, Sept. 5-8, Egmond aan Zee,
- The Netherlands, 2006
- </li>
-
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Derivation of an adjoint consistent discontinuous Galerkin
- discretization of the compressible Euler equations
- </strong>
- <br>
- In G. Lube and G. Rapin, eds.,
- Proceedings of the BAIL 2006 Conference, 2006
- </li>
-
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Adaptive discontinuous Galerkin methods with
- shock-capturing for the compressible Navier-Stokes equations
- </strong>
- <br>
- Int. J. Numer. Meth. Fluids, vol. 51, pp. 1131-1156, 2006
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Symmetric Interior Penalty DG Methods for the
- Compressible Navier-Stokes Equations I: Method Formulation
- </strong>
- <br>
- Int. J. Numer. Anal. Model., vol. 3, pp. 1-20, 2006.
- </li>
-
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Symmetric Interior Penalty DG Methods for the
- Compressible Navier-Stokes Equations II: Goal-Oriented A
- Posteriori Error Estimation
- </strong>
- <br>
- Int. J. Numer. Anal. Model., vol. 3, pp. 141-162, 2006
- </li>
-
- <li> <a href="http://www-dimat.unipv.it/heltai/">L. Heltai</a>
- <br>
- <strong>The Finite Element Immersed Boundary Method
- </strong> <br>
- Ph.D. thesis, Università di Pavia, Dipartimento di Matematica "F. Casorati",
- 2006
- </li>
-
- <li> K. Hwang, T. Pan, A. Joshi, J. C. Rasmussen, <a
- href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- E. Sevick-Muraca
- <br>
- <strong>Influence of excitation light rejection on forward model
- mismatch in optical tomography
- </strong>
- <br>
- Phys. Med. Biol., vol. 51, pp. 5889-5902, 2006
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, E. Sevick-Muraca
- <br>
- <strong>Non-contact fluorescence optical tomography with scanning
- patterned illumination
- </strong>
- <br>
- Optics Express, vol. 14,
- pp. 6516-6534, 2006
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, K. Hwang, J. C. Rasmussen,
- E. Sevick-Muraca
- <br>
- <strong>Fully adaptive FEM based fluorescence optical tomography from
- time-dependent measurements with area illumination and detection
- </strong>
- <br>
- Med. Phys., vol. 33,
- pp. 1299-1310, 2006
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, E. Sevick-Muraca
- <br>
- <strong>Non-contact fluorescence optical tomography with scanning
- illumination
- </strong>
- <br>
- Proceedings of the IEEE International Symposium on Biomedical Imaging,
- Arlington, VA, 2006, pp. 582-585, 2006
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, K. Hwang, J. C. Rasmussen,
- E. Sevick-Muraca
- <br>
- <strong>Plane wave fluorescence tomography with adaptive finite
- elements
- </strong>
- <br>
- Optics Letters, vol. 31,
- pp. 193-195, 2006
- </li>
-
- <li> O. Kayser-Herold
- <br>
- <strong>Least-Squares Methods for the Solution of Fluid-Structure
- Interaction Problems
- </strong>
- <br>
- Ph.D. thesis, TU-Braunschweig, Germany, 2006
- <br>
- Available online through <a
- href="http://www.digibib.tu-bs.de/?docid=00000035"
- target="_top">this link</a>
- </li>
-
- <li>
- T. Leicht
- <br>
- <strong> Anisotropic Mesh Refinement for Discontinuous Galerkin
- Methods in Aerodynamic Flow Simulations
- </strong>
- <br>
- Diploma thesis, TU Dresden, 2006
- <br>
- Available online through <a
- href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/publications/publications.html#supervised"
- target="_top">this link</a>
- </li>
-
- <li> D. Oeltz
- <br>
- <strong>Ein Raum-Zeit Dünngitterverfahren zur Diskretisierung
- parabolischer Differentialgleichungen
- </strong>
- <br>
- Ph.D. thesis, University of Bonn, Germany, 2006
- </li>
-
- <li> M. Schmidt
- <br>
- <strong>Low-dimensional I/O modeling of distributed parameter
- systems
- </strong>
- <br>
- Proc. Appl. Math. Mech., vol. 6, pp. 15-18, 2006
- </li>
-
- </ol>
-
-
- <a name="2005"> </a>
- <h2>Publications in 2005</h2>
-
- <ol>
-
- <li> M. Anderson, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, G. Carey
- <br>
- <strong>Analysis of parameter sensitivity and experimental
- design for a class of nonlinear partial differential
- equations
- </strong>
- <br>
- International Journal for Numerical Methods in Fluids, vol. 48,
- pp. 583-605, 2005
- </li>
-
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. Joshi, E. Sevick-Muraca
- <br>
- <strong>Adaptive finite element methods for increased
- resolution in fluorescence optical tomography
- </strong>
- <br>
- Progress in Biomedical Optics and Imaging, vol. 6,
- pp. 318-329, 2005
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/" target="_top">L. Heltai</a>
- <br>
- <strong>The finite element immersed boundary method: model, stability, and numerical
- results</strong>
- <br>
- In Schrefler Papadrakakis, Onate, eds., Computational Methods for
- Coupled Problems in Science and Engineering, 2005
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/" target="_top">L. Heltai</a>
- <br>
- <strong>Stability results and algorithmic strategies for the finite
- element approach to the immersed boundary method
- </strong>
- <br>
- Proceeding of the Sixth European Conference on Numerical Mathematics
- and Advanced Applications (ENUMATH 2005), pages 557-566, 2005
- </li>
-
- <li> M. Calhoun-Lopez, M. D. Gunzburger
- <br>
- <strong>A Finite Element, Multiresolution Viscosity Method
- for Hyperbolic Conservation Laws
- </strong>
- <br>
- SIAM J. Numer. Anal., vol. 43, pp. 1988-2011, 2005
- </li>
-
- <li> B. Carnes, N. Djilali
- <br>
- <strong>Systematic parameter estimation for PEM fuel cell models
- </strong>
- <br>
- Journal of Power Sources, vol. 144, pp. 83-93, 2005
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>,
- <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong>A locally conservative LDG method for the incompressible Navier- Stokes equations</strong>
- <br>
- Math. Comput., vol. 74, pp. 1067-1095, 2005
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>,
- <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong>The Local Discontinuous Galerkin Method for Linear
- Incomressible Fluid Flow: a Review</strong>
- <br>
- Comput. & Fluids, vol. 34, pp. 491-506, 2005
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong>Discontinuous Galerkin methods for compressible flows:
- higher order accuracy, error estimation and adaptivity
- </strong>
- <br>
- In H. Deconinck and M. Ricchiuto, editors,
- VKI LS 2006-01: CFD - Higher Order Discretization Methods,
- November 14-18, 2005, Rhode Saint Genese, Belgium.
- <br>
- von Karman Institute for Fluid Dynamics (2005)
- </li>
-
- <li> A. Joshi
- <br>
- <strong>Adaptive finite element methods for fluorescence enhanced
- optical tomography
- </strong>
- <br>
- Ph.D. thesis, Texas A&M University, 2005
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. B. Thompson, E. Sevick-Muraca
- <br>
- <strong>Experimental fluorescence optical tomography using
- adaptive finite elements and planar illumination with
- modulated excitation light
- </strong>
- <br>
- Progress in Biomedical Optics and Imaging, vol. 6,
- pp. 351-358, 2005
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Block Preconditioners for LDG Discretizations of
- Linear Incompressible Flow Problems</strong>
- <br>
- J. Sci. Comput., vol. 22, pp. 381-394, 2005
- </li>
-
- <li> O. Kayser-Herold, H. G. Matthies
- <br>
- <strong>Least squares finite element methods for fluid-structure
- interaction problems
- </strong>
- <br>
- Computers & Structures, vol. 83, pp. 191-207, 2005
- </li>
-
- <li> R. Li
- <br>
- <strong>On multi-mesh h-adaptive methods</strong>
- <br>
- J. Sci. Comput., vol. 24, pp. 321-341, 2005
- <br>
- (This paper uses <a
- href="http://dsec.pku.edu.cn/~rli/software_e.php"
- target="_top">AFEPack</a> which in turn uses deal.II's linear
- algebra library.)
- </li>
-
- <li> M. Mu
- <br>
- <strong>PDE.MART: A network-based problem-solving environment
- for PDEs
- </strong>
- <br>
- ACM Trans. Math. Software, vol. 31, pp. 508-531, 2005
- </li>
-
- <li> B. Nestler, D. Danilov, P. Galenko
- <br>
- <strong>Crystal growth of pure substances: Phase-field simulations in
- comparison with analytical and experimental results
- </strong>
- <br>
- Journal of Computational Physics, vol. 207, pp. 221-239, 2005
- </li>
-
- <li> T. Nielsen, T. Koehler, M. van der Mark, G. t'Hooft
- <br>
- <strong>Fully 3D reconstruction of attenuation for diffuse
- optical tomography using a finite element model
- </strong>
- <br>
- Nuclear Science Symposium Record, vol. 4, pp. 2283-2285, 2005
- </li>
-
- <li> Q. Ouyang, K. Xiu
- <br>
- <strong>Simulation Study of Reduced Self-Heating in Novel
- Thin-SOI Vertical Bipolar Transistors
- </strong>
- <br>
- Simulation of Semiconductor Processes and Devices, pp. 55-58, 2005
- </li>
-
- <li> M. Polner
- <br>
- <strong>Galerkin least-squares stabilization operators for the
- Navier-Stokes equations, A unified approach
- </strong>
- <br>
- Ph.D. thesis, University of Twente, The Netherlands, 2005
- </li>
-
- <li> R. B. Schulz, G. Echner, H. Ruehle,
- W. Stroh, J. Vierling, T. Vogt, J. Peter, W. Semmler
- <br>
- <strong>Development of a fully rotational non-contact fluorescence tomographer
- for small animals
- </strong>
- <br>
- IEEE Micro-imaging Conference, IEEE Nuclear Science Symposium
- Conference Record, pp. 2391-2393, 2005
- </li>
-
-
- <li> R. B. Schulz, J. Peter, W. Semmler, C. D'andrea, G. Valentini, R. Cubeddu
- <br>
- <strong>Quantifiability and Image Quality in Noncontact Fluorescence Tomography
- </strong>
- <br>
- in: Photon Migration and Diffuse-Light Imaging II, K. Licha
- and R. Cubeddu (eds.), SPIE press, 2005
- </li>
-
- </ol>
-
-
-
- <a name="2004"> </a>
- <h2>Publications in 2004</h2>
-
- <ol>
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>,
- <br>
- <strong>A framework for the adaptive finite element solution
- of large inverse problems. I. Basic techniques
- </strong>
- <br>
- ICES Report 2004-39, 2004.
- </li>
-
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, <a
- href="http://www.math.unibas.ch/~grote/"
- target="_top">M. Grote</a>, C. Hohenegger
- <br>
- <strong>Finite Element Method For Time Dependent Scattering:
- Nonreflecting Boundary Condition, Adaptivity, and Energy
- Decay
- </strong>
- <br>
- Computer Methods in Applied Mechanics and Engineering,
- vol. 193, pp. 2453-2482, 2004
- </li>
-
- <li> D. Boffi, L. Gastaldi, <a
- href="http://www-dimat.unipv.it/heltai/" target="_top">L. Heltai</a>
- <br>
- <strong> A finite element approach to the immersed boundary method
- </strong>
- <br>
- Progress in Engineering Computational Technology, vol. 12,
- pp. 271-298, 2004
- </li>
-
-
- <li> G. Carey, M. Anderson, B. Carnes, B. Kirk
- <br>
- <strong>Some aspects of adaptive grid technology related to
- boundary and interior layers
- </strong>
- <br>
- Journal of Computational and Applied Mathematics, vol. 166,
- pp. 55-86, 2004
- </li>
-
- <li> G. Carey, W. Barth, J. A. Woods, B. Kirk,
- M. Anderson, S. Chow, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong>Modeling error and constitutive relations in
- simulation of flow and transport
- </strong>
- <br>
- International Journal for Numerical Methods in Fluids,
- vol. 46, pp. 1211-1236, 2004
- </li>
-
- <li> S. Chow, G. F. Carey, M. L. Anderson
- <br>
- <strong>Finite element approximations of a glaciology problem.
- </strong>
- <br>
- ESAIM: Mathematical Modelling and Numerical Analysis (M2AN),
- vol. 38, pp. 741-756, 2004.
- </li>
-
- <li> C. Fröbel
- <br>
- <strong>Tikhonov-Regularisierung zur Parameteridentifikation bei elliptischen und parabolischen Modellgleichungen.
- </strong>
- <br>
- Diploma thesis, Universität Bremen, Germany, 2004
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong> Goal-Oriented A Posteriori Error Estimation
- for Multiple Target Functionals
- </strong>
- <br>
- in M. Feistauer, V. Doleji, P. Knobloch and K. Najzar,
- editors, Numerical Mathematics and Advanced Applications,
- ENUMATH 2003, pp. 410-419, Springer-Verlag, 2004
- </li>
-
- <li> U. Hasler, <a
- href="http://www.math.unibas.ch/~schneeba/" target="_top">A.
- Schneebeli</a>, <a
- href="http://www.math.ubc.ca/~schoetzau/" target="_top">D.
- Schötzau</a>
- <br>
- <strong>Mixed finite element approximation of incompressible
- MHD problems based on weighted regularization
- </strong>
- <br>
- Applied Numerical Mathematics, vol. 51, pp. 19-45, 2004
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, E. Sevick-Muraca
- <br>
- <strong>Adaptive finite element modeling of optical
- fluorescence-enhanced tomography
- </strong>
- <br>
- Optics Express, vol. 12, pp. 5402-5417, 2004
- </li>
-
- <li> A. Joshi, A. B. Thompson, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, E. Sevick-Muraca
- <br>
- <strong>Adaptive finite element methods for forward modeling
- in fluorescence enhanced frequency domain optical tomography
- </strong>
- <br>
- Proceedings of the 2004 OSA Biomedical Topical Meetings, 2004
- </li>
-
- <li> A. Joshi, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, A. B. Thompson, E. Sevick-Muraca
- <br>
- <strong>Adaptive finite element methods for fluorescence
- enhanced frequency domain optical tomography: Forward imaging
- problem
- </strong>
- <br>
- Proceedings of the 2004 IEEE International Symposium on
- Biomedical Imaging, 2004
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Multi-level methods for discontinuous Galerkin FEM on locally refined meshes</strong>
- <br>
- Comput. & Struct., vol. 82, pp. 2437-2445, 2004
- </li>
-
- <li> J. Ramirez, M. Laso
- <br>
- <strong>Micro-macro simulations of three-dimensional plane
- contraction flow
- </strong>
- <br>
- Modelling Simul. Mater. Sci. Eng., vol. 12, pp. 1293-1306, 2004
- </li>
-
- <li> R. B.
- Schulz, <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, J. Peter, W. Semmler
- <br>
- <strong>Independent modeling of
- fluorescence excitation and emission with the finite element method
- </strong>
- <br>
- Proceedings
- of the OSA BIOMED topical meeting, Miami, Florida, 14-18 April 2004
- </li>
-
- <li> E. Zander, J. R. Weimar, H. G. Mathies
- <br>
- <strong>Simulation of High-Frequency Atmospheric Gas Discharges
- </strong>
- <br>
- PAMM, vol. 4, pp. 428-429, 2004
- </li>
-
- </ol>
-
-
-
- <a name="2003"> </a>
- <h2>Publications in 2003</h2>
-
- <ol>
- <li>
- S. Achatz
- <br>
- <strong>Adaptive finite Dünngitter-Elemente höherer Ordnung
- für elliptische partielle Differentialgleichungen mit variablen
- Koeffizienten
- </strong>
- <br>
- Ph.D. thesis, TU Munich, 2003
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Starting threads in a C++ compatible fashion
- </strong>
- <br>
- C/C++ Users Journal, October 2003, pp. 21-24
- </li>
-
- <li> <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, R. Rannacher
- <br>
- <strong>Adaptive Finite Element Methods for Solving Differential Equations
- </strong>
- <br>
- Book, Birkhäuser, 2003
- </li>
-
- <li> M. Calhoun-Lopez
- <br>
- <strong>Numerical solutions of hyperbolic conservation laws:
- Incorporating multi-resolution viscosity methods into the
- finite element framework
- </strong>
- <br>
- Ph.D. thesis, Iowa State University, 2003
- </li>
-
- <li> B. Carnes
- <br>
- <strong>Adaptive finite elements for nonlinear transport equations
- </strong>
- <br>
- Ph.D. thesis, ICES, The University of Texas at Austin, 2003
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>,
- <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong>LDG methods for Stokes flow problems</strong>
- <br>
- in Brezzi, Buffa, Corsaro, Murli: Numerical Mathematics and Advanced Applications:
- ENUMATH 2001, Springer Italia, 2003
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>,
- <a href="http://www.math.ubc.ca/~schoetzau/" target="_top">D. Schötzau</a>
- <br>
- <strong>The Local Discontinuous Galerkin Method for the Oseen Equations</strong>
- <br>
- Math. Comput., vol. 73, pp. 569-593, 2003
- </li>
-
- <li>
- J. Gopalakrishnan,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Application of unified DG analysis to preconditioning DG methods
- </strong>
- <br>
- in Bathe: Computational Fluid and Solid Mechanics, pp. 1943-1945, 2003
- </li>
-
- <li>
- J. Gopalakrishnan,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong> A Multilevel Discontinuous Galerkin Method
- </strong>
- <br>
- Numer. Math., vol. 95, pp. 527-550, 2003
- </li>
-
- <li>
- Jay Gopalakrishnan, <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Multi-level Preconditioners for the interior penalty method</strong>
- <br>
- in Brezzi, Buffa, Corsaro, Murli: Numerical Mathematics and Advanced Applications:
- ENUMATH 2001, Springer Italia, 2003
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong> Goal-Oriented A Posteriori Error Estimation
- for Multiple Target Functionals
- </strong>
- <br>
- in T. Y. Hou and E. Tadmor, editors, Hyperbolic Problems:
- Theory, Numerics, Applications, pp. 579-588, Springer, 2003
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Goal-Oriented A Posteriori Error Estimation for Compressible Fluid Flows
- </strong>
- <br>
- In F. Brezzi, A. Buffa, S. Corsaro and A. Murli, editors,
- Numerical Mathematics and Advanced Applications, pp. 775-784, Springer, 2003
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Discontinuous Galerkin Finite Element Methods for Advection-Diffusion Problems</strong>
- <br>
- Habilitationsschrift, Universität Heidelberg, 2003
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Preconditioning discontinuous Galerkin saddle point systems</strong>
- <br>
- in Bathe: Computational Fluid and Solid Mechanics, pp. 2016-2018, 2003
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong>Preconditioning methods for local discontinuous {G}alerkin Discretizations</strong>
- <br>
- SIAM J. Sci. Comput., vol. 25, pp. 815-831, 2003
- </li>
-
-
- <li> <a
- href="http://www.math.unibas.ch/~schneeba/" target="_top">A.
- Schneebeli</a>, <a
- href="http://www.math.ubc.ca/~schoetzau/" target="_top">D.
- Schötzau</a>
- <br>
- <strong>Mixed finite elements for incompressible magneto-hydrodynamics
- </strong>
- <br>
- Comptes Rendus Mathematique, vol. 337, pp. 71-74, 2003
- </li>
-
- <li> M. Stadler, G. A. Holzapfel, J. Korelc
- <br>
- <strong>C<sup>n</sup> continuous modelling of smooth contact surfaces
- using NURBS and application to 2D problems
- </strong>
- <br>
- International Journal for Numerical Methods in Engineering,
- vol. 57, pp. 2177-2203, 2003
- </li>
-
- </ol>
-
-
- <a name="2002"> </a>
- <h2>Publications in 2002</h2>
-
- <ol>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Adaptive Finite Element Methods for the
- Identification of Distributed Parameters in
- Partial Differential Equations
- </strong>
- <br>
- Ph.D. thesis, University of Heidelberg, 2002
- </li>
-
- <li> S. Benkler
- <br>
- <strong>Numerical solution of the nonlinear Hartree equation.
- </strong>
- <br>
- Diploma thesis, ETH Zurich, Switzerland, 2002.
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>, <a
- href="http://www.math.ubc.ca/~schoetzau/">D.
- Schötzau</a>
- <br>
- <strong> The local discontinuous Galerkin method in
- incompressible fluid flow
- </strong>
- <br>
- in Mang, Rammerstorfer, Eberhardsteiner: Proceedings of the
- Fifth World Congress on Computational Mechanics (WCCM V),
- Vienna University of Technology, 2002
- </li>
-
- <li>
- B. Cockburn,
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>, <a
- href="http://www.math.ubc.ca/~schoetzau/">D.
- Schötzau</a>, C. Schwab
- <br>
- <strong> Local discontinuous Galerkin methods for the Stokes
- system
- </strong>
- <br>
- SIAM J. Numer. Anal., vol. 40, pp. 319-343, 2002
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>
- <br>
- <strong> Adaptive Finite Element Methods for the Compressible
- Euler Equations
- </strong>
- <br>
- Ph.D. thesis, University of Heidelberg, 2002
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann/"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Adaptive Discontinuous Galerkin Finite Element
- Methods for the Compressible Euler Equations
- </strong>
- <br>
- J. Comput. Phys., vol. 183, pp. 508-532, 2002.
- </li>
-
- <li>
- <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>, P. Houston
- <br>
- <strong>Adaptive Discontinuous Galerkin Finite Element
- Methods for Nonlinear Hyperbolic Conservation Laws
- </strong>
- <br>
- SIAM J. Sci. Comput., vol. 24, pp. 979-1004, 2002.
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>, Rolf Rannacher
- <br>
- <strong> Local error analysis of the interior penalty
- discontinuous Galerkin method for second order elliptic problems
- </strong>
- <br>
- J. Numer. Math., vol. 10, pp. 249-274, 2002
- </li>
-
- <li> F. Mohamed, M. Troyer, G. Blatter
- <br>
- <strong>Interaction of vortices in superconductors with
- kappa close to 1/sqrt(2),
- </strong>
- <br>
- Phys. Rev. B, vol. 65, article 224504, 2002.
- </li>
-
-
- <li> T. Shardlow
- <br>
- <strong>A coupled Cahn-Hilliard particle system
- </strong>
- <br>
- Electronic Journal of Differential Equations,
- vol. 2002, No. 73, pp. 1-21, 2002
- </li>
-
-
- <li> M. Stadler, G. A. Holzapfel
- <br>
- <strong>A novel approach for smooth contact surfaces using NURBS:
- application to the FE simulation of stenting
- </strong>
- <br>
- Proceedings of the 13th Conference of the European Society of
- Biomechanics, 1-4 September 2002, Wroclaw, Poland.
- </li>
-
- </ol>
-
-
-
- <a name="2001"> </a>
- <h2>Publications in 2001</h2>
-
- <ol>
- <li> A. Barinka, T. Barsch, P. Charton, A. Cohen, S. Dahlke,
- W. Dahmen, K. Urban
- <br>
- <strong>Adaptive wavelet schemes for elliptic
- problems—implementation and numerical experiments
- </strong>
- <br>
- SIAM J. Sci. Comput.,
- vol. 23, pp. 910-939, 2001
- </li>
-
- <li>
- B. Cockburn, <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>, Ilaria Perugia, <a
- href="http://www.math.ubc.ca/~schoetzau/">D.
- Schötzau</a>
- <br>
- <strong>Superconvergence of the Local Discontinuous Galerkin
- Method for Elliptic Problems on Cartesian Grids
- </strong>
- <br>
- SIAM J. Numer. Anal. 39 (1), pp. 264-285, 2001
- </li>
-
- <li>
- T. Richter
- <br>
- <strong>Funktionalorientierte Gitteroptimierung bei der Finite-Elemente
- Approximation elliptischer Differentialgleichungen
- </strong>
- <br>
- Diploma thesis, University of Heidelberg, 2001 (in German)
- </li>
- </ol>
-
-
- <a name="2000"> </a>
- <h2>Publications in 2000</h2>
-
- <ol>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Mesh Adaptivity and Error Control for a Finite Element
- Approximation of the Elastic Wave
- Equation
- </strong>
- <br>
- Proceedings of the Waves2000 conference,
- held in Santiago de Compostela, Spain, July 10-14, 2000
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Multi-threading support in deal.II
- </strong>
- <br>
- Preprint 2000-11 (SFB 359), IWR Heidelberg, October 1999.
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Using Modern Features of C++ for Adaptive Finite
- Element Methods:
- Dimension-Independent Programming in deal.II
- </strong>
- <br>
- Proceedings of the 16th IMACS World
- Congress, Lausanne, Switzerland, 2000
- </li>
-
- <li> <a href="http://ganymed.iwr.uni-heidelberg.de/~hartmann"
- target="_top">R. Hartmann</a>
- <br>
- <strong> Adaptive FE-Methods for Conservation Equations
- </strong>
- <br>
- In Heinrich Freistühler and Gerald Warnecke, eds.
- Hyperbolic problems: theory, numerics, applications:
- eighth international conference in Magdeburg, 2000.
- <br>
- International series of numerical mathematics 141: 495-503.
- Birkhäuser, Basel 2001.
- </li>
-
- <li> F. Mohamed
- <br>
- <strong>Interaction of vortices in superconductors with
- kappa close to 1/sqrt(2),
- </strong>
- <br>
- Diploma thesis, ETH Zurich, 2000.
- </li>
-
- </ol>
-
-
-
- <a name="1999"> </a>
- <h2>Publications in 1999</h2>
-
- <ol>
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a> and
- <a href="http://www.math.tamu.edu/~kanschat"
- target="_top">G. Kanschat</a>
- <br>
- <strong> Concepts for object-oriented finite element
- software - the <CODE>deal.II</CODE> library
- </strong>
- <br>
- Preprint 99-43 (SFB 359), IWR Heidelberg, October 1999.
- </li>
-
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, R. Rannacher
- <br>
- <strong> Adaptive finite element approximation of the acoustic wave
- equation: Error estimation and mesh adaptation
- </strong>
- <br>
- East-West Journal of Numerical Mathematics, vol. 7, no. 4 (1999),
- pp. 263-282
- </li>
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>, R. Rannacher
- <br>
- <strong> Adaptive finite element techniques for the acoustic
- wave equation
- </strong>
- <br>
- Journal of Computational Acoustics, vol. 9, no. 2
- (2001), pp. 575-591
- </li>
-
- <li>
- S. Nauber
- <br>
- <strong> Adaptive Finite Elemente Verfahren für
- selbstadjungierte Eigenwertprobleme
- </strong>
- <br>
- Diploma thesis, University of Heidelberg, 1999 (in German)
- </li>
-
- </ol>
-
-
-
-
-
-
-
- <a name="1998"> </a>
- <h2>Publications in 1998</h2>
-
- <ol>
- <li>
- <a href="http://www.math.tamu.edu/~bangerth"
- target="_top">W. Bangerth</a>
- <br>
- <strong> Adaptive Finite-Elemente-Methoden zur Lösung der
- Wellengleichung mit Anwendung in der Physik der Sonne
- </strong>
- <br>
- Diploma thesis, University of Heidelberg, 1998 (in German)
- </li>
- </ol>
-
- <hr />
- <address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
- </address>
- <div class="right">
- <a href="http://validator.w3.org/check?uri=referer" target="_top">
- <img style="border:0" src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"></a>
- <a href="http://jigsaw.w3.org/css-validator/check/referer" target="_top">
- <img style="border:0;width:88px;height:31px" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!"></a>
- </div>
+ <body>
+ This page is now part of the top-level project description. See
+ <a target="_top" href="http://dealii.org/publications.html">this page</a>.
</body>
</html>
<title>The deal.II Readme</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<link href="screen.css" rel="StyleSheet"/>
- <meta name="copyright" content="Copyright (C) 1998 - 2013 by the deal.II Authors"/>
+ <meta name="copyright" content="Copyright (C) 1998 - 2014 by the deal.II Authors"/>
<meta name="date" content="$Date$"/>
<meta name="svn_id" content="$Id$"/>
<meta name="keywords" content="deal.II"/>
<body>
- <h4 align="center" style="color: red">
- <strong class="red">Note: Since version 8.0, deal.II uses
- <a href="http://www.cmake.org" target="_top">CMake</a> to
- configure and build. For using the previous build
- system used until deal.II version 7.3, see
- <a href="http://www.dealii.org/7.3.0/readme.html"
- target="_top">the old ReadMe file</a>.
- </strong>
- <br />
- </h4>
-
<h1>Installation instructions and further information
on <acronym>deal.II</acronym> </h1>
</p>
</dd>
- <dt>
- <a name="functionparser"></a>
- <a href="http://warp.povusers.org/FunctionParser/">FunctionParser</a>
- </dt>
- <dd>
- <p>
- <a href="http://warp.povusers.org/FunctionParser/">FunctionParser</a>
- is a library that allows to enter functions in text form and have them
- interpreted at run time. This is particularly useful in input
- parameter files. <code>cmake</code> will usually find the version of
- this library that comes bundled with <acronym>deal.II</acronym>.
- The function parser library has its own license; if you want to use
- it with deal.II, please read it and make sure that you agree with it.
- You can find it
- <a href="http://warp.povusers.org/FunctionParser/">here</a>. We
- include FunctionParser in the deal.II distributions courtesy of its author,
- <a href="http://iki.fi/warp/">Juha Nieminen</a>.
- </p>
- </dd>
-
-
<dt><a name="HDF5"></a><a href="http://www.hdfgroup.org/HDF5/">HDF5</a></dt>
<dd>
<p>
</dd>
+ <dt>
+ <a name="muparser"></a>
+ <a href="http://muparser.beltoforion.de/">muparser</a>
+ </dt>
+ <dd>
+ <p>
+ <a href="http://muparser.beltoforion.de/">muparser</a>
+ is a library that allows to enter functions in text form and have them
+ interpreted at run time. This is particularly useful in input
+ parameter files. <code>cmake</code> will usually find the version of
+ this library that comes bundled with <acronym>deal.II</acronym>, but you
+ can specify <code>-DMUPARSER_DIR=/path/to/muparser</code> if desired.
+ </p>
+ </dd>
+
+
<dt><a name="netcdf"></a><a href="http://www.unidata.ucar.edu/software/netcdf/" target="_top">NetCDF</a></dt>
<dd>
<a href="http://www.unidata.ucar.edu/software/netcdf/"
in order to determine the directions of future work on the
library. We are also very much interested in incorporating any
work and bug fixes by third parties into the library. Of course,
- you will be credited for this on the <a href="authors.html">authors page</a>.
+ you will be credited for this on
+ the <a href="http://www.dealii.org/authors.html" target="_top">authors page</a>.
</p>
<p>
libraries we create. To this end, we collect
publications with results obtained using <acronym>deal.II</acronym>. Please
let us know if you have publications that we can add
- <a href="publications/index.html">to this page</a>.
+ <a href="http://www.dealii.org/publications.html">to this page</a>.
</p>
<a name="license"></a>
the license of the deal.II project granted to you.</b>
</li>
<li>
- We, <a href="authors.html">the deal.II Authors</a>, do not require
+ We, <a href="http://www.dealii.org/authors.html" target="_top">the deal.II Authors</a>, do not require
copyright assignments for contributions. This means that the
copyright for code contributions in the deal.II project is held by
its respective contributors who have each agreed to release their
later), we ask for the courtesy that scientific publications
presenting results obtained with this libraries acknowledge its
use. Please cite one of the papers referenced
- <a href="publications/index.html">here</a>.
+ <a href="http://www.dealii.org/publications.html">here</a>.
</li>
<li>
<acronym>deal.II</acronym> can interface with a number of <a
<a href="http://threadingbuildingblocks.org/"
target="_top">Threading Building Blocks</a>,
<a href="http://www.boost.org/" target="_top">BOOST</a> and
- <a href="http://warp.povusers.org/FunctionParser/"
- target="_top">FunctionParser</a>, courtesy of their authors.
+ <a href="http://muparser.beltoforion.de/"
+ target="_top">muparser</a>, courtesy of their authors.
These are also covered by their own licenses; please refer to
their webpages for more information.
</li>
<hr />
<address>
- <a href="authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
<link href="../screen.css" rel="StyleSheet" type="text/css">
<meta name="author" content="the deal.II authors">
- <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="2006/02/07 22:49:01">
<meta name="keywords" content="deal.II">
<meta name="svn_id" content="$Id$">
<p>
There are a number of papers that describe the overall design or
individual aspects of <acronym>deal.II</acronym>. Please refer to the
- papers listed at the top of the <a href="../publications/index.html"
+ papers listed at the top of the <a href="http://www.dealii.org/publications.html"
target="body">publications page</a> for full references. In addition,
there are the following reports:
<ul>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
# Set the name of the project and target:
SET(TARGET "step-1")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
- step-1.cc
- # You can specify additional files here!
+ ${TARGET}.cc
)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
# Set the name of the project and target:
SET(TARGET "step-1")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
- step-1.cc
- # You can specify additional files here!
+ ${TARGET}.cc
)
# Specify a list of files (file globs) that will be removed
<title>deal.II CMake documentation</title>
<link href="../screen.css" rel="StyleSheet">
<meta name="author" content="the deal.II authors <authors @ dealii.org>">
- <meta name="copyright" content="Copyright (C) 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta name="keywords" content="deal.II">
DEAL_II_WITH_LAPACK
DEAL_II_WITH_METIS
DEAL_II_WITH_MUMPS
+DEAL_II_WITH_MUPARSER
DEAL_II_WITH_MPI
DEAL_II_WITH_NETCDF
DEAL_II_WITH_P4EST
LAPACK_DIR (and BLAS_DIR),
METIS_DIR,
MUMPS_DIR (and SCALAPACK_DIR, BLACS_DIR),
+MUPARSER_DIR,
P4EST_DIR (and SC_DIR),
PETSC_DIR and PETSC_ARCH (forming ${PETSC_DIR}/${PETSC_ARCH}),
SLEPC_DIR (forming ${SLEPC_DIR}/${PETSC_ARCH}),
a way to provide a link interface that is suitable for static
linkage of executables. Enabling this option forces
<code>BUILD_SHARED_LIBS=OFF</code> and
- <code>DEAL_II_PERFER_STATIC_LIBS</code>.
+ <code>DEAL_II_PREFER_STATIC_LIBS=ON</code>.
<li>
<code>CMAKE_INSTALL_RPATH_USE_LINK_PATH</code>: If set
</p>
<p>
- deal.II will configure sensible default <code>CXXFLAGS</code>
- depending on platform, compiler and build target. There are two
- options to override this behaviour:
+ deal.II will configure sensible default <code>CXXFLAGS</code> and
+ <code>LDFLAGS</code> depending on platform, compiler and build
+ target. There are two options to override this behaviour:
<ol>
<li>
DEAL_II_CXX_FLAGS - used during all builds
DEAL_II_CXX_FLAGS_DEBUG - additional flags for the debug library
DEAL_II_CXX_FLAGS_RELEASE - additional flags for the release library
+
+DEAL_II_LINKER_FLAGS - used during all builds
+DEAL_II_LINKER_FLAGS_DEBUG - additional flags for the debug library
+DEAL_II_LINKER_FLAGS_RELEASE - additional flags for the release library
</pre>
The content of the cached variables will be preserved
configuration.
</p>
- <p>
- The build system automatically exports a <code>config.camke</code>
- into the binary directory that can be used to conveniently clone a
- build directories cache entries, e.g. assuming that there is a
- configured build directory <code>build</code> next to an empty
- directory <code>build2</code>:
-<pre class="cmake">
-$ cd build2
-$ cmake -C ../build/config.cmake ../deal.II
-</pre>
- </p>
-
<a name="compiling"></a>
<h2> Compiling only certain parts </h2>
<p>
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
DEAL_II_WITH_METIS
DEAL_II_WITH_MPI
DEAL_II_WITH_MUMPS
+DEAL_II_WITH_MUPARSER
DEAL_II_WITH_NETCDF
DEAL_II_WITH_P4EST
DEAL_II_WITH_PETSC
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2013 by the deal.II Authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE at
-## the top level of the deal.II distribution.
-##
-## ---------------------------------------------------------------------
-
-#
-# Example configuration file
-#
-# This file can be used as a script to preseed the initial cache of a build
-# directory. To do so, invoke cmake with
-#
-# $ cmake -C configuration.cmake [...]
-#
-#
-# Please note that this file is actually intrepeted as a full featured
-# CMake script file, so in order to set variables in the cache a statement
-# of the form
-#
-# SET(<variable> <value> CACHE <type> "<string>")
-#
-# has to be used. See doc/readme.html and doc/users/cmake.html for further
-# details on how to use the cmake build system of deal.II.
-#
+## ##
+# Example configuration file #
+# #
+# See doc/readme.html and doc/users/cmake.html for further #
+# details on how to use the cmake build system of deal.II. #
+## ##
###########################################################################
# "Fortran Compiler."
# )
#
-# SET(DEAL_II_CXX_FLAGS "" CACHE STRING
-# "The user supplied cache variable will be appended _at the end_ of the auto generated DEAL_II_CXX_FLAGS variable"
+# SET(CMAKE_CXX_FLAGS "" CACHE STRING
+# "The user supplied cache variable will be appended _at the end_ of the auto generated CMAKE_CXX_FLAGS variable"
# )
#
# SET(DEAL_II_CXX_FLAGS_DEBUG "" CACHE STRING
# "The user supplied cache variable will be appended _at the end_ of the auto generated DEAL_II_LINKER_FLAGS_RELEASE variable"
# )
#
-# SET(DEAL_II_DEFINITIONS "" CACHE STRING
-# "Additional, user supplied compile definitions"
-# )
-#
-# SET(DEAL_II_DEFINITIONS_DEBUG "" CACHE STRING
-# "Additional, user supplied compile definitions"
-# )
-#
-# SET(DEAL_II_DEFINITIONS_RELEASE "" CACHE STRING
-# "Additional, user supplied compile definitions"
-# )
-#
# SET(BUILD_SHARED_LIBS "ON" CACHE BOOL
# "Build a shared library"
# )
# "If set to ON, then use 64-bit data types to represent global degree of freedom indices. The default is to OFF. You only want to set this to ON if you will solve problems with more than 2^31 (approximately 2 billion) unknowns. If set to ON, you also need to ensure that both Trilinos and/or PETSc support 64-bit indices."
# )
#
+#
###########################################################################
#
+#
+# muPaser:
+#
+# SET(DEAL_II_WITH_MUPARSER ON CACHE BOOL
+# "Build deal.II with support for muparser"
+#
+# Automatic detection:
+#
+# Specify a hint with CMAKE_PREFIX_PATH or by setting
+# SET(MUPARSER_DIR "/.../..." CACHE PATH "")
+#
+# Manual setup:
+#
+# SET(MUPARSER_FOUND TRUE CACHE BOOL "")
+# SET(MUPARSER_LIBRARIES "library;and;semicolon;separated;list;of;link;interface" CACHE STRING "")
+# SET(MUPARSER_INCLUDE_DIRS "semicolon;separated;list;of;include;dirs" CACHE STRING "")
+#
+
+
#
# Netcdf:
#
# C++11 support is autodetected. You can explicitly disable C+11 support by
# specifying
#
-# SET(DEAL_II_WITH_CXX11 FALSE CACHE BOOL "")
+# SET(DEAL_II_HAVE_CXX11_FLAG FALSE CACHE BOOL "")
#
# A custom C++11 flag can be set by setting
#
-# SET(DEAL_II_CXX11_FLAG "-std=c++11" CACHE STRING "")
+# SET(DEAL_II_HAVE_CXX11_FLAG TRUE CACHE BOOL "")
+# SET(DEAL_II_CXX11_FLAG "-std=c++0x" CACHE STRING "")
#
# "Library suffix for the debug library"
# )
#
-# SET(DEAL_II_RELEASE_SUFFIX "" CACHE STRING
+# SET_IF_EMPTY(DEAL_II_RELEASE_SUFFIX "" CACHE STRING
# "Library suffix for the release library"
# )
#
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
<title>deal.II Development Navigation Bar</title>
<link href="../screen.css" rel="StyleSheet">
<meta name="author" content="the deal.II authors <authors@dealii.org>">
- <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013 by the deal.II authors">
+ <meta name="copyright" content="Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013, 2014 by the deal.II authors">
<meta name="date" content="$Date$">
<meta name="svn_id" content="$Id$">
<meta http-equiv="content-language" content="en">
<b><small>Online Resources</small></b>
<p>
<a href="https://code.google.com/p/dealii/wiki/FrequentlyAskedQuestions" target="_top">FAQ</a><br />
- <a href="../news/news.html" target="body">News</a><br />
+ <a href="http://www.dealii.org/news.html" target="_top">News</a><br />
<a href="http://www.dealii.org/download/" target="body">Download</a><br />
<a href="http://www.dealii.org/mail.html" target="body">Mailing list</a><br />
<a href="https://code.google.com/p/dealii/w/list" target="_top">Wiki</a><br />
<hr />
<address>
- <a href="../authors.html" target="body">The deal.II Authors</a>
+ <a href="http://www.dealii.org/authors.html" target="_top">The deal.II Authors</a>
$Date$
</address>
<div class="right">
#
PATTERN "CMakeFiles*" EXCLUDE
PATTERN "doc*" EXCLUDE
- PATTERN "doxygen*" EXCLUDE
PATTERN ".svn*" EXCLUDE
#
# Glob Includes:
PATTERN "*.prm"
PATTERN "*.inp"
PATTERN "step*/CMakeLists.txt"
+ PATTERN "doxygen/CMakeLists.txt"
#
# Special files:
#
--- /dev/null
+##
+# CMake script for compiling the doxygen examples
+##
+
+# Usually, you will not need to modify anything beyond this point...
+
+FILE(GLOB sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
+
+FIND_PACKAGE(deal.II 8.2 QUIET
+ HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
+ )
+IF(NOT ${deal.II_FOUND})
+ MESSAGE(FATAL_ERROR "\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
+ "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
+ "or set an environment variable \"DEAL_II_DIR\" that contains this path."
+ )
+ENDIF()
+
+DEAL_II_INITIALIZE_CACHED_VARIABLES()
+PROJECT(doxygen_examples)
+
+FOREACH(ccfile ${sources})
+ GET_FILENAME_COMPONENT(file ${ccfile} NAME_WE)
+ ADD_EXECUTABLE(${file} ${ccfile})
+ DEAL_II_SETUP_TARGET(${file})
+ENDFOREACH()
using namespace Algorithms;
-class Explicit
- : public Operator<Vector<double> >
+class Explicit : public Operator<Vector<double> >
{
public:
Explicit(const FullMatrix<double> &matrix);
- void operator() (NamedData<Vector<double>*> &out,
- const NamedData<Vector<double>*> &in);
+ void operator() (AnyData &out, const AnyData &in);
- void initialize_timestep_data(const TimestepData &);
private:
- const TimestepData *timestep_data;
SmartPointer<const FullMatrix<double>, Explicit> matrix;
FullMatrix<double> m;
};
-class Implicit
- : public Operator<Vector<double> >
+class Implicit : public Operator<Vector<double> >
{
public:
Implicit(const FullMatrix<double> &matrix);
- void operator() (NamedData<Vector<double>*> &out,
- const NamedData<Vector<double>*> &in);
-
- void initialize_timestep_data(const TimestepData &);
-private:
- const TimestepData *timestep_data;
+ void operator() (AnyData &out, const AnyData &in);
+
+ private:
SmartPointer<const FullMatrix<double>, Implicit> matrix;
FullMatrix<double> m;
};
int main()
{
FullMatrix<double> matrix(2);
- matrix(0,0) = 1.;
- matrix(1,1) = 1.;
- matrix(0,1) = 31.4;
- matrix(1,0) = -31.4;
+ matrix(0,0) = 0.;
+ matrix(1,1) = 0.;
+ matrix(0,1) = 3.14;
+ matrix(1,0) = -3.14;
OutputOperator<Vector<double> > out;
out.initialize_stream(std::cout);
Explicit op_explicit(matrix);
Implicit op_implicit(matrix);
ThetaTimestepping<Vector<double> > solver(op_explicit, op_implicit);
- op_explicit.initialize_timestep_data(solver.explicit_data());
- op_implicit.initialize_timestep_data(solver.implicit_data());
solver.set_output(out);
Vector<double> value(2);
value(0) = 1.;
- NamedData<Vector<double>*> indata;
- NamedData<Vector<double>*> outdata;
- Vector<double> *p = &value;
- outdata.add(p, "value");
+ AnyData indata;
+ AnyData outdata;
+ outdata.add(&value, "value");
solver.notify(Events::initial);
solver(outdata, indata);
void
-Explicit::initialize_timestep_data(const TimestepData &t)
-{
- timestep_data = &t;
-}
-
-
-void
-Explicit::operator() (NamedData<Vector<double>*> &out, const NamedData<Vector<double>*> &in)
+Explicit::operator() (AnyData &out, const AnyData &in)
{
+ const double timestep = *in.read_ptr<double>("Timestep");
if (this->notifications.test(Events::initial) || this->notifications.test(Events::new_timestep_size))
{
- m.equ(-timestep_data->step, *matrix);
+ m.equ(-timestep, *matrix);
for (unsigned int i=0; i<m.m(); ++i)
m(i,i) += 1.;
}
this->notifications.clear();
- unsigned int i = in.find("Previous iterate");
- m.vmult(*out(0), *in(i));
+ m.vmult(*out.entry<Vector<double>*>(0),
+ *in.read_ptr<Vector<double> >("Previous iterate"));
}
void
-Implicit::initialize_timestep_data(const TimestepData &t)
-{
- timestep_data = &t;
-}
-
-
-void
-Implicit::operator() (NamedData<Vector<double>*> &out, const NamedData<Vector<double>*> &in)
+Implicit::operator() (AnyData &out, const AnyData &in)
{
+ const double timestep = *in.read_ptr<double>("Timestep");
if (this->notifications.test(Events::initial) || this->notifications.test(Events::new_timestep_size))
{
- m.equ(timestep_data->step, *matrix);
+ m.equ(timestep, *matrix);
for (unsigned int i=0; i<m.m(); ++i)
m(i,i) += 1.;
m.gauss_jordan();
}
this->notifications.clear();
-
- unsigned int i = in.find("Previous time");
- m.vmult(*out(0), *in(i));
+ m.vmult(*out.entry<Vector<double>*>(0),
+ *in.read_ptr<Vector<double> >("Previous time"));
}
# Set the name of the project and target:
SET(TARGET "step-1")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
Bangerth's video lectures</a> on deal.II and computational science. In
particular, you can see the steps he executes to run this and other
programs, and you will get a much better idea of the tools that can be
-used to work with deal.II.
+used to work with deal.II. In particular, lectures 2 and 4 give an overview of
+deal.II and of the building blocks of any finite element code.
<h3> What this program does </h3>
about them).
The program is otherwise small enough that it doesn't need a whole lot
-of introduction. Let us just continue with its commented source.
+of introduction.
+
+@dealiiVideoLecture{5,6}
<h3> About scientific computing in general </h3>
As a general recommendation: If you expect to spend more than a few days
writing software in the future, do yourself the favor of learning tools that
can make your life more productive, in particular debuggers and integrated
-development environments. You will find that you will get the time spent
+development environments. (@dealiiVideoLectureSeeAlso{7,8,25})
+You will find that you will get the time spent
learning these tools back severalfold soon by being more productive!
Several of the video lectures referenced above show how to use tools
such as integrated development environments or debuggers.
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 1999 - 2013 by the deal.II authors
+ * Copyright (C) 1999 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
// to write programs in an essentially dimension independent way.
// Next, we want to fill the triangulation with a single cell for a square
- // domain. The triangulation is the refined four times, to yield 4^4=256
+ // domain. The triangulation is the refined four times, to yield $4^4=256$
// cells in total:
GridGenerator::hyper_cube (triangulation);
triangulation.refine_global (4);
# Set the name of the project and target:
SET(TARGET "step-10")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-11")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-12")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-13")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-14")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-15")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
space. In this example, we choose $\Omega$ as the unit disk.
As described above, we solve this equation using Newton's method in which we
-compute the $n$th approximate solution from the $n-1$st one, and use
+compute the $n$th approximate solution from the $n$th$-1$ one, and use
a damping parameter $\alpha^n$ to get better global convergence behavior:
@f{align*}
F'(u^{n},\delta u^{n})&=- F(u^{n})
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 2012 - 2013 by the deal.II authors
+ * Copyright (C) 2012 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
// compute again. To ensure there are no hanging nodes of the old mesh in
// the object, it's first cleared. To be on the safe side, we then also
// make sure that the current solution's vector entries satisfy the
- // hanging node constraints:
-
+ // hanging node constraints (see the discussion in the documentation of
+ // the SolutionTransfer class for why this is necessary):
hanging_node_constraints.clear();
DoFTools::make_hanging_node_constraints(dof_handler,
# Set the name of the project and target:
SET(TARGET "step-16")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 2003 - 2013 by the deal.II authors
+ * Copyright (C) 2003 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
-// These, now, are the include necessary for the multilevel methods. The
-// first two declare classes that allow us to enumerate degrees of freedom not
-// only on the finest mesh level, but also on intermediate levels (that's what
-// the MGDoFHandler class does) as well as allow to access this information
-// (iterators and accessors over these cells).
+// These, now, are the include necessary for the multilevel methods. The first
+// one declares how to handle Dirichlet boundary conditions on each of the
+// levels of the multigrid method. For the actual description of the degrees
+// of freedom, we do not need any new include file because DoFHandler already
+// has all necessary methods implemented. We will only need to distribute the
+// DoFs for the levels further down.
//
// The rest of the include files deals with the mechanics of multigrid as a
// linear operator (solver or preconditioner).
-#include <deal.II/multigrid/mg_dof_handler.h>
#include <deal.II/multigrid/mg_constrained_dofs.h>
#include <deal.II/multigrid/multigrid.h>
#include <deal.II/multigrid/mg_transfer.h>
Triangulation<dim> triangulation;
FE_Q<dim> fe;
- MGDoFHandler<dim> mg_dof_handler;
+ DoFHandler<dim> dof_handler;
SparsityPattern sparsity_pattern;
SparseMatrix<double> system_matrix;
triangulation (Triangulation<dim>::
limit_level_difference_at_vertices),
fe (degree),
- mg_dof_handler (triangulation),
+ dof_handler (triangulation),
degree(degree)
{}
// @sect4{LaplaceProblem::setup_system}
// The following function extends what the corresponding one in step-6
- // did. The top part, apart from the additional output, does the same:
+ // did, with the exception of also distributing the degrees of freedom on
+ // each level of the mesh which is needed for the multigrid hierarchy.
+ // We then output the number of degrees (globally and on each level) and
+ // reset the solution and right hand side vectors to the correct size.
+ // As in other programs where we use a sequence of meshes that become
+ // finer and finer (starting with step-5), the code as is here sets
+ // the solution vector to zero, rather than trying to interpolate the
+ // solution obtained on the previous mesh to the current one. This
+ // follows from the empirical observation that interpolating the solution
+ // and using it as a starting guess does not significant decrease the number
+ // of linear CG iterations one has to perform to solve a linear system.
+ // (The situation is very different for nonlinear problems, where using
+ // a previous time step's solution, or a solution from a coarser grid,
+ // typically drastically makes the solution of a nonlinear system cheaper.)
template <int dim>
void LaplaceProblem<dim>::setup_system ()
{
- mg_dof_handler.distribute_dofs (fe);
+ dof_handler.distribute_dofs (fe);
+ dof_handler.distribute_mg_dofs (fe);
- // Here we output not only the degrees of freedom on the finest level, but
- // also in the multilevel structure
- deallog << "Number of degrees of freedom: "
- << mg_dof_handler.n_dofs();
-
- for (unsigned int l=0; l<triangulation.n_levels(); ++l)
- deallog << " " << 'L' << l << ": "
- << mg_dof_handler.n_dofs(l);
- deallog << std::endl;
+ std::cout << " Number of degrees of freedom: "
+ << dof_handler.n_dofs()
+ << " (by level: ";
+ for (unsigned int level=0; level<triangulation.n_levels(); ++level)
+ std::cout << dof_handler.n_dofs(level)
+ << (level == triangulation.n_levels()-1
+ ? ")" : ", ");
+ std::cout << std::endl;
- sparsity_pattern.reinit (mg_dof_handler.n_dofs(),
- mg_dof_handler.n_dofs(),
- mg_dof_handler.max_couplings_between_dofs());
- DoFTools::make_sparsity_pattern (mg_dof_handler, sparsity_pattern);
+ sparsity_pattern.reinit (dof_handler.n_dofs(),
+ dof_handler.n_dofs(),
+ dof_handler.max_couplings_between_dofs());
+ DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern);
- solution.reinit (mg_dof_handler.n_dofs());
- system_rhs.reinit (mg_dof_handler.n_dofs());
+ solution.reinit (dof_handler.n_dofs());
+ system_rhs.reinit (dof_handler.n_dofs());
// But it starts to be a wee bit different here, although this still
// doesn't have anything to do with multigrid methods. step-6 took care of
// the global matrix from local contributions. This works, but the same
// can be done in a slightly simpler way if we already take care of these
// constraints at the time of copying local contributions into the global
- // matrix. To this end, we here do not just compute the constraints do to
+ // matrix. To this end, we here do not just compute the constraints due to
// hanging nodes, but also due to zero boundary conditions. We will use
// this set of constraints later on to help us copy local contributions
// correctly into the global linear system right away, without the need
// for a later clean-up stage:
constraints.clear ();
hanging_node_constraints.clear ();
- DoFTools::make_hanging_node_constraints (mg_dof_handler, hanging_node_constraints);
- DoFTools::make_hanging_node_constraints (mg_dof_handler, constraints);
+ DoFTools::make_hanging_node_constraints (dof_handler, hanging_node_constraints);
+ DoFTools::make_hanging_node_constraints (dof_handler, constraints);
- typename FunctionMap<dim>::type dirichlet_boundary;
+ typename FunctionMap<dim>::type dirichlet_boundary_functions;
ZeroFunction<dim> homogeneous_dirichlet_bc (1);
- dirichlet_boundary[0] = &homogeneous_dirichlet_bc;
- VectorTools::interpolate_boundary_values (static_cast<const DoFHandler<dim>&>(mg_dof_handler),
- dirichlet_boundary,
+ dirichlet_boundary_functions[0] = &homogeneous_dirichlet_bc;
+ VectorTools::interpolate_boundary_values (static_cast<const DoFHandler<dim>&>(dof_handler),
+ dirichlet_boundary_functions,
constraints);
constraints.close ();
hanging_node_constraints.close ();
// about the boundary values as well, so we pass the
// <code>dirichlet_boundary</code> here as well.
mg_constrained_dofs.clear();
- mg_constrained_dofs.initialize(mg_dof_handler, dirichlet_boundary);
+ mg_constrained_dofs.initialize(dof_handler, dirichlet_boundary_functions);
// Now for the things that concern the multigrid data structures. First,
for (unsigned int level=0; level<n_levels; ++level)
{
CompressedSparsityPattern csp;
- csp.reinit(mg_dof_handler.n_dofs(level),
- mg_dof_handler.n_dofs(level));
- MGTools::make_sparsity_pattern(mg_dof_handler, csp, level);
+ csp.reinit(dof_handler.n_dofs(level),
+ dof_handler.n_dofs(level));
+ MGTools::make_sparsity_pattern(dof_handler, csp, level);
mg_sparsity_patterns[level].copy_from (csp);
// @sect4{LaplaceProblem::assemble_system}
// The following function assembles the linear system on the finest level of
- // the mesh. It is almost exactly the same as in step-6, with the exception
- // that we don't eliminate hanging nodes and boundary values after
- // assembling, but while copying local contributions into the global
- // matrix. This is not only simpler but also more efficient for large
- // problems.
+ // the mesh. It is almost exactly the same as in step-6.
//
// This latter trick is something that only found its way into deal.II over
// time and wasn't used in the initial version of this tutorial
const Coefficient<dim> coefficient;
std::vector<double> coefficient_values (n_q_points);
- typename MGDoFHandler<dim>::active_cell_iterator
- cell = mg_dof_handler.begin_active(),
- endc = mg_dof_handler.end();
+ typename DoFHandler<dim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
cell_matrix = 0;
// obscure if you're not familiar with the algorithm actually implemented
// in deal.II to support multilevel algorithms on adaptive meshes; if some
// of the things below seem strange, take a look at the @ref mg_paper.
- //
- // Our first job is to identify those degrees of freedom on each level
- // that are located on interfaces between adaptively refined levels, and
- // those that lie on the interface but also on the exterior boundary of
- // the domain. As in many other parts of the library, we do this by using
- // Boolean masks, i.e. vectors of Booleans each element of which indicates
- // whether the corresponding degree of freedom index is an interface DoF
- // or not. The <code>MGConstraints</code> already computed the information
- // for us when we called initialize in <code>setup_system()</code>.
- std::vector<std::vector<bool> > interface_dofs
- = mg_constrained_dofs.get_refinement_edge_indices ();
- std::vector<std::vector<bool> > boundary_interface_dofs
- = mg_constrained_dofs.get_refinement_edge_boundary_indices ();
-
- // The indices just identified will later be used to decide where the
- // assembled value has to be added into on each level. On the other hand,
- // we also have to impose zero boundary conditions on the external
- // boundary of each level. But this the <code>MGConstraints</code> knows.
- // So we simply ask for them by calling <code>get_boundary_indices()</code>.
- // The third step is to construct constraints on all those
- // degrees of freedom: their value should be zero after each application
- // of the level operators. To this end, we construct ConstraintMatrix
- // objects for each level, and add to each of these constraints for each
- // degree of freedom. Due to the way the ConstraintMatrix stores its data,
- // the function to add a constraint on a single degree of freedom and
- // force it to be zero is called Constraintmatrix::add_line(); doing so
- // for several degrees of freedom at once can be done using
+
+ // Our first job is to identify the boundary conditions for the levels. On
+ // each level, we impose Dirichlet boundary conditions on the exterior
+ // boundary of the domain as well as on interfaces between adaptively
+ // refined levels. As in many other parts of the library, we do this by
+ // using a mask described by an IndexSet. The <code>MGConstraints</code>
+ // already computed the information for us when we called initialize in
+ // <code>setup_system()</code>. So we simply ask for them by calling
+ // <code>get_boundary_indices()</code> and
+ // <code>get_refinement_edge_indices(level)</code>. Moreover, we have to
+ // identify the subset of the refinement edge indices which are also
+ // located on the boundary as they require special treatment in the
+ // algorithm further down.
+
+ // These three masks are used to fill a ConstraintMatrix objects for each
+ // level that we use during the assembly of the matrix: the value of the
+ // associated degrees of freedom should be zero after each application of
+ // the level operators. Due to the way the ConstraintMatrix stores its
+ // data, the function to add a constraint on a single degree of freedom
+ // and force it to be zero is called Constraintmatrix::add_line(); doing
+ // so for several degrees of freedom at once can be done using
// Constraintmatrix::add_lines():
std::vector<ConstraintMatrix> boundary_constraints (triangulation.n_levels());
std::vector<ConstraintMatrix> boundary_interface_constraints (triangulation.n_levels());
for (unsigned int level=0; level<triangulation.n_levels(); ++level)
{
- boundary_constraints[level].add_lines (interface_dofs[level]);
boundary_constraints[level].add_lines (mg_constrained_dofs.get_boundary_indices()[level]);
+ boundary_constraints[level].
+ add_lines (mg_constrained_dofs.get_refinement_edge_indices(level));
boundary_constraints[level].close ();
boundary_interface_constraints[level]
- .add_lines (boundary_interface_dofs[level]);
+ .add_lines (mg_constrained_dofs.get_refinement_edge_boundary_indices(level));
boundary_interface_constraints[level].close ();
}
// <code>assemble_system</code>, with two exceptions: (i) we don't need a
// right hand side, and more significantly (ii) we don't just loop over
// all active cells, but in fact all cells, active or not. Consequently,
- // the correct iterator to use is MGDoFHandler::cell_iterator rather than
- // MGDoFHandler::active_cell_iterator. Let's go about it:
- typename MGDoFHandler<dim>::cell_iterator cell = mg_dof_handler.begin(),
- endc = mg_dof_handler.end();
+ // the correct iterator to use is DoFHandler::cell_iterator rather than
+ // DoFHandler::active_cell_iterator. Let's go about it:
+ typename DoFHandler<dim>::cell_iterator cell = dof_handler.begin(),
+ endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
// with a gotcha that is easily forgotten: The indices of global
// degrees of freedom we want here are the ones for current level, not
// for the global matrix. We therefore need the function
- // MGDoFAccessor::get_mg_dof_indices, not
- // MGDoFAccessor::get_dof_indices as used in the assembly of the
+ // DoFAccessor::get_mg_dof_indices, not
+ // DoFAccessor::get_dof_indices as used in the assembly of the
// global system:
cell->get_mg_dof_indices (local_dof_indices);
// we have a symmetric operator, one of these matrices is the
// transpose of the other.
//
- // The way we assemble these matrices is as follows: since the are
+ // The way we assemble these matrices is as follows: since they are
// formed from parts of the local contributions, we first delete all
// those parts of the local contributions that we are not interested
// in, namely all those elements of the local matrix for which not $i$
// necessary.
for (unsigned int i=0; i<dofs_per_cell; ++i)
for (unsigned int j=0; j<dofs_per_cell; ++j)
- if ( !(interface_dofs[cell->level()][local_dof_indices[i]]==true &&
- interface_dofs[cell->level()][local_dof_indices[j]]==false))
+ if ( !(mg_constrained_dofs.get_refinement_edge_indices(cell->level()).
+ is_element(local_dof_indices[i])==true &&
+ mg_constrained_dofs.get_refinement_edge_indices(cell->level()).
+ is_element(local_dof_indices[j])==false))
cell_matrix(i,j) = 0;
boundary_interface_constraints[cell->level()]
// the finite element function spaces involved and can often be computed in
// a generic way independent of the problem under consideration. In that
// case, we can use the MGTransferPrebuilt class that, given the constraints
- // on the global level and an MGDoFHandler object computes the matrices
- // corresponding to these transfer operators.
+ // of the final linear system and the MGConstrainedDoFs object that knows
+ // about the boundary conditions on the each level and the degrees of
+ // freedom on interfaces between different refinement level can build the
+ // matrices for those transfer operations from a DoFHandler object with
+ // level degrees of freedom.
//
// The second part of the following lines deals with the coarse grid
// solver. Since our coarse grid is very coarse indeed, we decide for a
template <int dim>
void LaplaceProblem<dim>::solve ()
{
-
- // Create the object that deals with the transfer between different
- // refinement levels. We need to pass it the hanging node constraints.
MGTransferPrebuilt<Vector<double> > mg_transfer(hanging_node_constraints, mg_constrained_dofs);
- // Now the prolongation matrix has to be built. This matrix needs to take
- // the boundary values on each level into account and needs to know about
- // the indices at the refinement edges. The <code>MGConstraints</code>
- // knows about that so pass it as an argument.
- mg_transfer.build_matrices(mg_dof_handler);
+ mg_transfer.build_matrices(dof_handler);
FullMatrix<double> coarse_matrix;
coarse_matrix.copy_from (mg_matrices[0]);
// the transpose operator for the latter operation, allowing us to
// initialize both up and down versions of the operator with the matrices
// we already built:
- MGMatrix<> mg_matrix(&mg_matrices);
- MGMatrix<> mg_interface_up(&mg_interface_matrices);
- MGMatrix<> mg_interface_down(&mg_interface_matrices);
+ mg::Matrix<Vector<double> > mg_matrix(mg_matrices);
+ mg::Matrix<Vector<double> > mg_interface_up(mg_interface_matrices);
+ mg::Matrix<Vector<double> > mg_interface_down(mg_interface_matrices);
// Now, we are ready to set up the V-cycle operator and the multilevel
// preconditioner.
- Multigrid<Vector<double> > mg(mg_dof_handler,
+ Multigrid<Vector<double> > mg(dof_handler,
mg_matrix,
coarse_grid_solver,
mg_transfer,
mg.set_edge_matrices(mg_interface_down, mg_interface_up);
PreconditionMG<dim, Vector<double>, MGTransferPrebuilt<Vector<double> > >
- preconditioner(mg_dof_handler, mg, mg_transfer);
+ preconditioner(dof_handler, mg, mg_transfer);
// With all this together, we can finally get about solving the linear
// system in the usual way:
// computed. In particular, the first one refines the mesh at the beginning
// of each cycle while the second one outputs results at the end of each
// such cycle. The functions are almost unchanged from those in step-6, with
- // the exception of two minor differences: The KellyErrorEstimator::estimate
- // function wants an argument of type DoFHandler, not MGDoFHandler, and so
- // we have to cast from derived to base class; and we generate output in VTK
+ // the exception of one minor difference: we generate output in VTK
// format, to use the more modern visualization programs available today
// compared to those that were available when step-6 was written.
template <int dim>
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- KellyErrorEstimator<dim>::estimate (static_cast<DoFHandler<dim>&>(mg_dof_handler),
+ KellyErrorEstimator<dim>::estimate (dof_handler,
QGauss<dim-1>(3),
typename FunctionMap<dim>::type(),
solution,
{
DataOut<dim> data_out;
- data_out.attach_dof_handler (mg_dof_handler);
+ data_out.attach_dof_handler (dof_handler);
data_out.add_data_vector (solution, "solution");
data_out.build_patches ();
setup_system ();
- std::cout << " Number of degrees of freedom: "
- << mg_dof_handler.n_dofs()
- << " (by level: ";
- for (unsigned int level=0; level<triangulation.n_levels(); ++level)
- std::cout << mg_dof_handler.n_dofs(level)
- << (level == triangulation.n_levels()-1
- ? ")" : ", ");
- std::cout << std::endl;
-
assemble_system ();
assemble_multigrid ();
# Set the name of the project and target:
SET(TARGET "step-17")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS
${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
href="../../readme.html" target="body">README</a> file.
-There is an additional caveat: PETSc appears not to co-operate well when using
-threads and the program crashes when deal.II is compiled in its usual mode
-supporting multithreading. The program can therefore only be compiled and run
-if multithreading is disabled upon configuration of deal.II using the
-<code>--disable-threads</code> switch to <code>./configure</code>.
-
Now, for the details: as mentioned, the program does not compute anything new,
so the use of finite element classes etc. is exactly the same as before. The
As can be seen, we can easily get to almost four million unknowns. In fact, the
code's runtime with 8 processes was less than 7 minutes up to (and including)
-cycle 14, and 14 minutes including the second to last step. I lost the timing
-information for the last step, though, but you get the idea. All this is if
-the debug flag in the Makefile was changed to "off", i.e. "optimized", and
+cycle 14, and 14 minutes including the second to last step. (These are numbers
+relevant to when the code was initially written, in 2004.) I lost the timing
+information for the last step, though, but you get the idea. All this is after
+release mode has been enabled by running <code>make release</code>, and
with the generation of graphical output switched off for the reasons stated in
-the program comments above. The biggest 2d computations we did had roughly 7.1
+the program comments above.
+(@dealiiVideoLectureSeeAlso{18})
+The biggest 2d computations we did had roughly 7.1
million unknowns, and were done on 32 processes. It took about 40 minutes.
Not surprisingly, the limiting factor for how far one can go is how much memory
one has, since every process has to hold the entire mesh and DoFHandler objects,
# Set the name of the project and target:
SET(TARGET "step-18")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS
${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
simulation.
-@note PETSc appears not to co-operate well when using
-threads and the program crashes when deal.II is compiled in its usual mode
-supporting multithreading. The program can therefore only be compiled and run
-if multithreading is disabled upon configuration of deal.II using the
-<code>--disable-threads</code> switch to <code>./configure</code>.
# Set the name of the project and target:
SET(TARGET "step-19")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# No sensible run target can be defined for this example step
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-2")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{9}
+
After we have created a grid in the previous example, we now show how
to define degrees of freedom on this mesh. For this example, we
will use the lowest order ($Q_1$) finite elements, for which the degrees
# Set the name of the project and target:
SET(TARGET "step-20")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{19,20,21}
+
This program is devoted to two aspects: the use of mixed finite elements -- in
particular Raviart-Thomas elements -- and using block matrices to define
solvers, preconditioners, and nested versions of those that use the
# Set the name of the project and target:
SET(TARGET "step-21")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-22")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<h3>%Boundary conditions</h3>
+@dealiiVideoLecture{21.5}
+
The weak form just derived immediately presents us with different
possibilities for imposing boundary conditions:
<ol>
<h4>2D calculations</h4>
Running the program with the space dimension set to 2 in <code>main()</code>
-yields the following output (when the flag is set to optimized in the
-Makefile):
+yields the following output (in "release mode", @dealiiVideoLectureSeeAlso{18}):
@code
examples/\step-22> make run
-============================ Remaking Makefile.dep
-==============optimized===== \step-22.cc
-============================ Linking \step-22
-============================ Running \step-22
Refinement cycle 0
Number of active cells: 64
Number of degrees of freedom: 679 (594+85)
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 2008 - 2013 by the deal.II authors
+ * Copyright (C) 2008 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
}
+ // For the right-hand side we use the fact that the shape
+ // functions are only non-zero in one component (because our
+ // elements are primitive). Instead of multiplying the tensor
+ // representing the dim+1 values of shape function i with the
+ // whole right-hand side vector, we only look at the only
+ // non-zero component. The Function
+ // FiniteElement::system_to_component_index(i) will return
+ // which component this shape function lives in (0=x velocity,
+ // 1=y velocity, 2=pressure in 2d), which we use to pick out
+ // the correct component of the right-hand side vector to
+ // multiply with.
+
const unsigned int component_i =
fe.system_to_component_index(i).first;
local_rhs(i) += fe_values.shape_value(i,q) *
// simultaneously use the ConstraintMatrix object to apply Dirichlet
// boundary conditions and eliminate hanging node constraints, as we
// discussed in the introduction), we have to be careful about one
- // thing, though. We have only build up half of the local matrix
+ // thing, though. We have only built half of the local matrix
// because of symmetry, but we're going to save the full system matrix
// in order to use the standard functions for solution. This is done
// by flipping the indices in case we are pointing into the empty part
# Set the name of the project and target:
SET(TARGET "step-23")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{28}
+
This is the first of a number of tutorial programs that will finally
cover "real" time-dependent problems, not the slightly odd form of time
dependence found in step-18 or the DAE model of step-21. In particular, this program introduces
# Set the name of the project and target:
SET(TARGET "step-24")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-25")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-26")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{29,30}
+
+
This program implements the heat equation
@f{align*}
\frac{\partial u(\mathbf x, t)}{\partial t}
the explicit Euler ($\theta=0$), implicit Euler ($\theta=1$) and
Crank-Nicolson ($\theta=\frac 12$) time discretizations. Since the latter has
the highest convergence order, we will choose $\theta=\frac 12$ in the program
-below, but make it so that playing with this parameter remains simple.
+below, but make it so that playing with this parameter remains simple. (If you
+are interested in playing with higher order methods, take a look at step-52.)
Given this time discretization, space discretization happens as it always
does, by multiplying with test functions, integrating by parts, and then
Ralf Hartmann, published by the University of Heidelberg, Germany, in 2002.
+<h4>Better time stepping methods</h4>
+
+We here use one of the simpler time stepping methods, namely the second order
+in time Crank-Nicolson method. However, more accurate methods such as
+Runge-Kutta methods are available and should be used as they do not represent
+much additional effort. It is not difficult to implement this for the current
+program, but a more systematic treatment is also given in step-52.
+
+
<h4>Better refinement criteria</h4>
If you look at the meshes in the movie above, it is clear that they are not
# Set the name of the project and target:
SET(TARGET "step-27")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
hanging node is constrained not only against the two adjacent degrees
of freedom, but is constrained against many more degrees of freedom.
-In previous programs, for example in step-6, we have dealt with eliminating
-these constrained degrees of freedom by first building an object of type
-ConstraintMatrix that stores the constraints, and then "condensing" away these
-degrees of freedom first from the sparsity pattern. The same scheme is used
-for the matrix and right hand side, which are also both first built then
-condensed.
-
-Dealing with sparsity patterns and matrices in this way turns out to be
-inefficient because the effort necessary is at least ${\cal O}(N \log N)$ in
-the number of unknowns, whereas an ideal finite element program would of
-course only have algorithms that are linear in the number of unknowns. The
-solution to this problem is to use the ConstraintMatrix object already at the
-time of creating the sparsity pattern, or while copying local contributions
-into the global matrix object (or global vector).
-
-So, instead of the code snippet (taken from step-6)
-@code
- DoFTools::make_hanging_node_constraints (dof_handler,
- hanging_node_constraints);
- hanging_node_constraints.close ();
-
- DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern);
- hanging_node_constraints.condense (sparsity_pattern);
-@endcode
-we now use the following:
-@code
- DoFTools::make_hanging_node_constraints (dof_handler,
- hanging_node_constraints);
- hanging_node_constraints.close ();
-
- DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern,
- hanging_node_constraints, false);
-@endcode
-
-Note the last <tt>false</tt> argument we pass when creating the sparsity
-pattern. It tells the sparsity pattern that constrained entries should not
-be inserted into the sparsity pattern. This makes sense for the way we're
-going to do assembly, which does the elimination of constraints already
-locally. Hence, we will never write the constrained entries. This is the
-second key to increase this program's performance, since the system matrix
-will have less entries — this saves both memory and computing time
-when doing matrix-vector multiplications or applying a preconditioner.
-
-In a similar vein, we have to slightly modify the way we copy local
-contributions into global matrices and vectors. In previous tutorial programs,
-we have always used a process like this:
-@code
- typename hp::DoFHandler<dim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- {
- ... // assemble local contributions them into global object
-
- cell->get_dof_indices (local_dof_indices);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- system_matrix.add (local_dof_indices[i],
- local_dof_indices[j],
- cell_matrix(i,j));
- system_rhs(local_dof_indices[i]) += cell_rhs(i);
- }
- }
-
- hanging_node_constraints.condense (system_matrix);
- hanging_node_constraints.condense (system_rhs);
-@endcode
-We now replace copying and later condensing into one step, as already shown in
-step-17, step-18, and step-22:
-@code
- typename hp::DoFHandler<dim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- {
- ... // assemble local contributions them into global object
-
- cell->get_dof_indices (local_dof_indices);
-
- hanging_node_constraints
- .distribute_local_to_global (cell_matrix, cell_rhs,
- local_dof_indices,
- system_matrix, system_rhs);
- }
-@endcode
-Essentially, what the
-<code>hanging_node_constraints.distribute_local_to_global</code> call does is
-to implement the same loops as before, but whenever we hit a constrained degree
-of freedom, the function does the right thing and already condenses it away.
-
-Using this technique of eliminating constrained nodes already when
-transferring local contributions into the global objects, we avoid the problem
-of having to go back later and change these objects. Timing these operations
-shows that this makes the overall algorithms faster.
+It turns out that the strategy presented first in step-6 to eliminate the
+constraints while computing the element matrices and vectors with
+ConstraintMatrix::distribute_local_to_global is the most efficient approach
+also for this case. The alternative strategy to first build the matrix without
+constraints and then "condensing" away constrained degrees of freedom is
+considerably more expensive. It turns out that building the sparsity pattern
+by this inefficient algorithm requires at least ${\cal O}(N \log N)$ in the
+number of unknowns, whereas an ideal finite element program would of course
+only have algorithms that are linear in the number of unknowns. Timing the
+sparsity pattern creation as well as the matrix assembly shows that the
+algorithm presented in step-6 (and used in the code below) is indeed faster.
In our program, we will also treat the boundary conditions as (possibly
inhomogeneous) constraints and eliminate the matrix rows and columns to
interpolates the Dirichlet boundary conditions already in the setup phase in
order to tell the ConstraintMatrix object about them, and then do the
transfer from local to global data on matrix and vector simultaneously. This
-is exactly what we've shown in the step-22 tutorial program.
+is exactly what we've shown in step-6.
<h3>The test case</h3>
// @sect4{LaplaceProblem::setup_system}
//
- // This function is again an almost verbatim copy of what we already did in
- // step-6. The first change is that we append the Dirichlet boundary
- // conditions to the ConstraintMatrix object, which we consequently call
- // just <code>constraints</code> instead of
- // <code>hanging_node_constraints</code>. The second difference is that we
- // don't directly build the sparsity pattern, but first create an
- // intermediate object that we later copy into the usual SparsityPattern
- // data structure, since this is more efficient for the problem with many
- // entries per row (and different number of entries in different rows). In
- // another slight deviation, we do not first build the sparsity pattern and
- // then condense away constrained degrees of freedom, but pass the
- // constraint matrix object directly to the function that builds the
- // sparsity pattern. We disable the insertion of constrained entries with
- // <tt>false</tt> as fourth argument in the DoFTools::make_sparsity_pattern
- // function. All of these changes are explained in the introduction of this
- // program.
- //
- // The last change, maybe hidden in plain sight, is that the dof_handler
- // variable here is an hp object -- nevertheless all the function calls we
- // had before still work in exactly the same way as they always did.
+ // This function is again a verbatim copy of what we already did in
+ // step-6. Despite function calls with exactly the same names and arguments,
+ // the algorithms used internally are different in some aspect since the
+ // dof_handler variable here is an hp object.
template <int dim>
void LaplaceProblem<dim>::setup_system ()
{
local_dof_indices,
system_matrix, system_rhs);
}
-
- // Now with the loop over all cells finished, we are done for this
- // function. The steps we still had to do at this point in earlier
- // tutorial programs, namely condensing hanging node constraints and
- // applying Dirichlet boundary conditions, have been taken care of by the
- // ConstraintMatrix object <code>constraints</code> on the fly.
}
# Set the name of the project and target:
SET(TARGET "step-28")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-29")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
(Of course, execution times will differ if you run the program
locally.) The fact that most of the time is spent on assembling
the system matrix and generating output is due to the many assertion
-that need to be checked in debug mode. In optimized mode these parts
+that need to be checked in debug mode. In release mode these parts
of the program run much faster whereas solving the linear system is
hardly sped up at all:
# Set the name of the project and target:
SET(TARGET "step-3")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{10}
<h3>The basic functioning of finite elements</h3>
The output of the program looks as follows:
@code
Number of active cells: 1024
-Total number of cells: 1365
Number of degrees of freedom: 1089
DEAL:cg::Starting value 0.121094
DEAL:cg::Convergence step 48 value 5.33692e-13
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 1999 - 2013 by the deal.II authors
+ * Copyright (C) 1999 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
// Now, the first thing we've got to do is to generate the triangulation on
// which we would like to do our computation and number each vertex with a
-// degree of freedom. We have seen this in the previous examples before.
+// degree of freedom. We have seen these two steps in step-1 and step-2
+// before, respectively.
+//
+// This function does the first part, creating the mesh. We create the grid
+// and refine all cells five times. Since the initial grid (which is the
+// square $[-1,1] \times [-1,1]$) consists of only one cell, the final grid
+// has 32 times 32 cells, for a total of 1024.
+//
+// Unsure that 1024 is the correct number? We can check that by outputting the
+// number of cells using the <code>n_active_cells()</code> function on the
+// triangulation.
void Step3::make_grid ()
{
- // First create the grid and refine all cells five times. Since the initial
- // grid (which is the square [-1,1]x[-1,1]) consists of only one cell, the
- // final grid has 32 times 32 cells, for a total of 1024.
GridGenerator::hyper_cube (triangulation, -1, 1);
triangulation.refine_global (5);
- // Unsure that 1024 is the correct number? Let's see: n_active_cells
- // returns the number of active cells:
+
std::cout << "Number of active cells: "
<< triangulation.n_active_cells()
<< std::endl;
- // Here, by active we mean the cells that aren't refined any further. We
- // stress the adjective `active', since there are more cells, namely the
- // parent cells of the finest cells, their parents, etc, up to the one cell
- // which made up the initial grid. Of course, on the next coarser level, the
- // number of cells is one quarter that of the cells on the finest level,
- // i.e. 256, then 64, 16, 4, and 1. We can get the total number of cells
- // like this:
- std::cout << "Total number of cells: "
- << triangulation.n_cells()
- << std::endl;
- // Note the distinction between n_active_cells() and n_cells().
}
+// @note We call the Triangulation::n_active_cells() function, rather than
+// Triangulation::n_cells(). Here, <i>active</i> means the cells that aren't
+// refined any further. We stress the adjective "active" since there are more
+// cells, namely the parent cells of the finest cells, their parents, etc, up
+// to the one cell which made up the initial grid. Of course, on the next
+// coarser level, the number of cells is one quarter that of the cells on the
+// finest level, i.e. 256, then 64, 16, 4, and 1. If you called
+// <code>triangulation.n_cells()</code> instead in the code above, you would
+// consequently get a value of 1365 instead. On the other hand, the number of
+// cells (as opposed to the number of active cells) is not typically of much
+// interest, so there is no good reason to print it.
+
+
// @sect4{Step3::setup_system}
// Next we enumerate all the degrees of freedom and set up matrix and vector
// global right hand side to zero, before we fill them:
cell_matrix = 0;
cell_rhs = 0;
-
- // Then finally assemble the matrix: For the Laplace problem, the matrix
- // on each cell is the integral over the gradients of shape function i
- // and j. Since we do not integrate, but rather use quadrature, this is
- // the sum over all quadrature points of the integrands times the
- // determinant of the Jacobian matrix at the quadrature point times the
- // weight of this quadrature point. You can get the gradient of shape
- // function $i$ at quadrature point q_point by using
- // <code>fe_values.shape_grad(i,q_point)</code>; this gradient is a
- // 2-dimensional vector (in fact it is of type Tensor@<1,dim@>, with
- // here dim=2) and the product of two such vectors is the scalar
- // product, i.e. the product of the two shape_grad function calls is the
- // dot product. This is in turn multiplied by the Jacobian determinant
- // and the quadrature point weight (that one gets together by the call
- // to FEValues::JxW() ). Finally, this is repeated for all shape
- // functions $i$ and $j$:
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- cell_matrix(i,j) += (fe_values.shape_grad (i, q_point) *
- fe_values.shape_grad (j, q_point) *
- fe_values.JxW (q_point));
-
- // We then do the same thing for the right hand side. Here, the integral
- // is over the shape function i times the right hand side function,
- // which we choose to be the function with constant value one (more
- // interesting examples will be considered in the following
- // programs). Again, we compute the integral by quadrature, which
- // transforms the integral to a sum over all quadrature points of the
- // value of the shape function at that point times the right hand side
- // function, here the constant function equal to one, times the Jacobian
- // determinant times the weight of that quadrature point:
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
- cell_rhs(i) += (fe_values.shape_value (i, q_point) *
- 1 *
- fe_values.JxW (q_point));
-
+
+ // Now it is time to start integration over the cell, which we
+ // do by looping over all quadrature points, which we will
+ // number by q_index.
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
+ {
+ // First assemble the matrix: For the Laplace problem, the
+ // matrix on each cell is the integral over the gradients of
+ // shape function i and j. Since we do not integrate, but
+ // rather use quadrature, this is the sum over all
+ // quadrature points of the integrands times the determinant
+ // of the Jacobian matrix at the quadrature point times the
+ // weight of this quadrature point. You can get the gradient
+ // of shape function $i$ at quadrature point with number q_index by
+ // using <code>fe_values.shape_grad(i,q_index)</code>; this
+ // gradient is a 2-dimensional vector (in fact it is of type
+ // Tensor@<1,dim@>, with here dim=2) and the product of two
+ // such vectors is the scalar product, i.e. the product of
+ // the two shape_grad function calls is the dot
+ // product. This is in turn multiplied by the Jacobian
+ // determinant and the quadrature point weight (that one
+ // gets together by the call to FEValues::JxW() ). Finally,
+ // this is repeated for all shape functions $i$ and $j$:
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_matrix(i,j) += (fe_values.shape_grad (i, q_index) *
+ fe_values.shape_grad (j, q_index) *
+ fe_values.JxW (q_index));
+
+ // We then do the same thing for the right hand side. Here,
+ // the integral is over the shape function i times the right
+ // hand side function, which we choose to be the function
+ // with constant value one (more interesting examples will
+ // be considered in the following programs).
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_rhs(i) += (fe_values.shape_value (i, q_index) *
+ 1 *
+ fe_values.JxW (q_index));
+ }
// Now that we have the contribution of this cell, we have to transfer
// it to the global matrix and right hand side. To this end, we first
// have to find out which global numbers the degrees of freedom on this
void Step3::run ()
{
make_grid ();
- setup_system();
+ setup_system ();
assemble_system ();
solve ();
output_results ();
# Set the name of the project and target:
SET(TARGET "step-30")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-31")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
\nabla \cdot \kappa \nabla (T^\alpha)
+
\kappa(\alpha-1)
- T^{\alpha-2} |\nabla T|^\alpha
+ T^{\alpha-2} |\nabla T|^2
-
\gamma
T^{\alpha-1}
# Set the name of the project and target:
SET(TARGET "step-32")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Define the output that should be cleaned:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
threads. For example, if your cluster nodes have 8 cores as they often have at
the time of writing this, and if your batch scheduler puts 8 MPI processes on
each node, then using threads doesn't make the program any
-faster. Consequently, you probably want to use the
-<code>--disable-threads</code> flag when configuring your deal.II installation
-for this machine. On the other hand, if you want to run this program on a
-single multicore machine, then it may make sense to use threads. That said, at
+faster. Consequently, you probably want to either configure your deal.II without threads, or set the number of threads in MPI_InitFinalize to 1 (third argument), or "export DEAL_II_NUM_THREADS=1" before running.
+That said, at
the time of writing this, we only use the WorkStream class for assembling
(parts of) linear systems, while 75% or more of the run time of the program is
spent in the linear solvers that are not parallelized — in other words,
};
double global_temperature[2];
- for (unsigned int i=0; i<distributed_temperature_solution.local_size(); ++i)
+ for (unsigned int i=distributed_temperature_solution.local_range().first;
+ i < distributed_temperature_solution.local_range().second; ++i)
{
temperature[0] = std::min<double> (temperature[0],
- distributed_temperature_solution.trilinos_vector()[0][i]);
+ distributed_temperature_solution(i));
temperature[1] = std::max<double> (temperature[1],
- distributed_temperature_solution.trilinos_vector()[0][i]);
+ distributed_temperature_solution(i));
}
temperature[0] *= -1.0;
# Set the name of the project and target:
SET(TARGET "step-33")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# A custom command line to run the program
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-34")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-35")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-36")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-37")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
// twice. Rather, we would keep this object in the main class and simply
// store a reference.
//
- // @note Observe how we store the values for the coefficient: We use a
- // vector type <code>AlignedVector<VectorizedArray<number> ></code>
- // structure. One would think that one can use
- // <code>std::vector<VectorizedArray<number> ></code> as well, but there are
- // some technicalities with vectorization: A certain alignment of the data
- // with the memory address boundaries is required (essentially, a
- // VectorizedArray of 16 bytes length as in SSE needs to start at a memory
- // address that is divisible by 16). The chosen class makes sure that this
- // alignment is respected, whereas std::vector can in general not, which may
- // lead to segmentation faults at strange places for some systems or
- // suboptimal performance for other systems.
+ // @note Note that storing values of type
+ // <code>VectorizedArray<number></code> requires care: Here, we use the
+ // deal.II table class which is prepared to hold the data with correct
+ // alignment. However, storing it in e.g.
+ // <code>std::vector<VectorizedArray<number> ></code> is not possible with
+ // vectorization: A certain alignment of the data with the memory address
+ // boundaries is required (essentially, a VectorizedArray of 16 bytes length
+ // as in SSE needs to start at a memory address that is divisible by
+ // 16). The table class (as well as the AlignedVector class it is based on)
+ // makes sure that this alignment is respected, whereas std::vector can in
+ // general not, which may lead to segmentation faults at strange places for
+ // some systems or suboptimal performance for other systems.
template <int dim, int fe_degree, typename number>
class LaplaceOperator : public Subscriptor
{
void evaluate_coefficient(const Coefficient<dim> &function);
MatrixFree<dim,number> data;
- AlignedVector<VectorizedArray<number> > coefficient;
+ Table<2, VectorizedArray<number> > coefficient;
Vector<number> diagonal_values;
bool diagonal_is_available;
{
const unsigned int n_cells = data.n_macro_cells();
FEEvaluation<dim,fe_degree,fe_degree+1,1,number> phi (data);
- coefficient.resize (n_cells * phi.n_q_points);
+ coefficient.reinit (n_cells, phi.n_q_points);
for (unsigned int cell=0; cell<n_cells; ++cell)
{
phi.reinit (cell);
for (unsigned int q=0; q<phi.n_q_points; ++q)
- coefficient[cell*phi.n_q_points+q] =
+ coefficient(cell,q) =
coefficient_function.value(phi.quadrature_point(q));
}
}
const std::pair<unsigned int,unsigned int> &cell_range) const
{
FEEvaluation<dim,fe_degree,fe_degree+1,1,number> phi (data);
- AssertDimension (coefficient.size(), data.n_macro_cells() * phi.n_q_points);
for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
{
phi.read_dof_values(src);
phi.evaluate (false,true,false);
for (unsigned int q=0; q<phi.n_q_points; ++q)
- phi.submit_gradient (coefficient[cell*phi.n_q_points+q] *
+ phi.submit_gradient (coefficient(cell,q) *
phi.get_gradient(q), q);
phi.integrate (false,true);
phi.distribute_local_to_global (dst);
# Set the name of the project and target:
SET(TARGET "step-38")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-39")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
#include <deal.II/fe/fe_dgp.h>
#include <deal.II/fe/fe_dgq.h>
#include <deal.II/dofs/dof_tools.h>
-#include <deal.II/multigrid/mg_dof_handler.h>
// The include files for using the MeshWorker framework
#include <deal.II/meshworker/dof_info.h>
Triangulation<dim> triangulation;
const MappingQ1<dim> mapping;
const FiniteElement<dim> &fe;
- MGDoFHandler<dim> mg_dof_handler;
- DoFHandler<dim> &dof_handler;
+ DoFHandler<dim> dof_handler;
// Then, we have the matrices and vectors related to the global discrete
// system.
:
mapping(),
fe(fe),
- mg_dof_handler(triangulation),
- dof_handler(mg_dof_handler),
+ dof_handler(triangulation),
estimates(1)
{
GridGenerator::hyper_cube_slit(triangulation, -1, 1);
// First, we use the finite element to distribute degrees of freedom over
// the mesh and number them.
dof_handler.distribute_dofs(fe);
+ dof_handler.distribute_mg_dofs(fe);
unsigned int n_dofs = dof_handler.n_dofs();
// Then, we already know the size of the vectors representing finite
// element functions.
{
// These are roughly the same lines as above for the global matrix,
// now for each level.
- CompressedSparsityPattern c_sparsity(mg_dof_handler.n_dofs(level));
- MGTools::make_flux_sparsity_pattern(mg_dof_handler, c_sparsity, level);
+ CompressedSparsityPattern c_sparsity(dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern(dof_handler, c_sparsity, level);
mg_sparsity[level].copy_from(c_sparsity);
mg_matrix[level].reinit(mg_sparsity[level]);
if (level>0)
{
CompressedSparsityPattern ci_sparsity;
- ci_sparsity.reinit(mg_dof_handler.n_dofs(level-1), mg_dof_handler.n_dofs(level));
- MGTools::make_flux_sparsity_pattern_edge(mg_dof_handler, ci_sparsity, level);
+ ci_sparsity.reinit(dof_handler.n_dofs(level-1), dof_handler.n_dofs(level));
+ MGTools::make_flux_sparsity_pattern_edge(dof_handler, ci_sparsity, level);
mg_sparsity_dg_interface[level].copy_from(ci_sparsity);
mg_matrix_dg_up[level].reinit(mg_sparsity_dg_interface[level]);
mg_matrix_dg_down[level].reinit(mg_sparsity_dg_interface[level]);
info_box.add_update_flags_all(update_flags);
info_box.initialize(fe, mapping);
- MeshWorker::DoFInfo<dim> dof_info(mg_dof_handler);
+ MeshWorker::DoFInfo<dim> dof_info(dof_handler);
// Obviously, the assembler needs to be replaced by one filling level
// matrices. Note that it automatically fills the edge matrices as well.
assembler.initialize_fluxes(mg_matrix_dg_up, mg_matrix_dg_down);
MatrixIntegrator<dim> integrator;
- // Here is the other difference to the previous function: we run over all
- // cells, not only the active ones. And we use <tt>mg_dof_handler</tt>,
- // since we need the degrees of freedom on each level, not the global
- // numbering.
+ // Here is the other difference to the previous function: we run
+ // over all cells, not only the active ones. And we use functions
+ // ending on <code>_mg</code> since we need the degrees of freedom
+ // on each level, not the global numbering.
MeshWorker::integration_loop<dim, dim> (
- mg_dof_handler.begin(), mg_dof_handler.end(),
+ dof_handler.begin_mg(), dof_handler.end_mg(),
dof_info, info_box,
integrator, assembler);
}
// preconditioner. First, we need transfer between grid levels. The object
// we are using here generates sparse matrices for these transfers.
MGTransferPrebuilt<Vector<double> > mg_transfer;
- mg_transfer.build_matrices(mg_dof_handler);
+ mg_transfer.build_matrices(dof_handler);
// Then, we need an exact solver for the matrix on the coarsest level.
FullMatrix<double> coarse_matrix;
// Now, we are ready to set up the V-cycle operator and the multilevel
// preconditioner.
- Multigrid<Vector<double> > mg(mg_dof_handler, mgmatrix,
+ Multigrid<Vector<double> > mg(dof_handler, mgmatrix,
mg_coarse, mg_transfer,
mg_smoother, mg_smoother);
// Let us not forget the edge matrices needed because of the adaptive
// which can be used as a regular preconditioner,
PreconditionMG<dim, Vector<double>,
MGTransferPrebuilt<Vector<double> > >
- preconditioner(mg_dof_handler, mg, mg_transfer);
+ preconditioner(dof_handler, mg, mg_transfer);
// and use it to solve the system.
solver.solve(matrix, solution, right_hand_side, preconditioner);
}
setup_system();
deallog << "DoFHandler " << dof_handler.n_dofs() << " dofs, level dofs";
for (unsigned int l=0; l<triangulation.n_levels(); ++l)
- deallog << ' ' << mg_dof_handler.n_dofs(l);
+ deallog << ' ' << dof_handler.n_dofs(l);
deallog << std::endl;
deallog << "Assemble matrix" << std::endl;
# Set the name of the project and target:
SET(TARGET "step-4")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{12,13}
deal.II has a unique feature which we call
``dimension independent programming''. You may have noticed in the
<img src="http://www.dealii.org/images/steps/developer/step-4.solution-2d.png" alt="">
</p>
+(@dealiiVideoLectureSeeAlso{11,32})
The picture shows the solution of the problem under consideration as
a 3D plot. As can be seen, the solution is almost flat in the interior
of the domain and has a higher curvature near the boundary. This, of
// difference to how we did things in step-3: Instead of using a
// constant right hand side with value 1, we use the object representing
// the right hand side and evaluate it at the quadrature points:
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (fe_values.shape_grad (i, q_point) *
- fe_values.shape_grad (j, q_point) *
- fe_values.JxW (q_point));
+ cell_matrix(i,j) += (fe_values.shape_grad (i, q_index) *
+ fe_values.shape_grad (j, q_index) *
+ fe_values.JxW (q_index));
- cell_rhs(i) += (fe_values.shape_value (i, q_point) *
- right_hand_side.value (fe_values.quadrature_point (q_point)) *
- fe_values.JxW (q_point));
+ cell_rhs(i) += (fe_values.shape_value (i, q_index) *
+ right_hand_side.value (fe_values.quadrature_point (q_index)) *
+ fe_values.JxW (q_index));
}
// As a final remark to these loops: when we assemble the local
// contributions into <code>cell_matrix(i,j)</code>, we have to multiply
- // the gradients of shape functions $i$ and $j$ at point q_point and
+ // the gradients of shape functions $i$ and $j$ at point number
+ // q_index and
// multiply it with the scalar weights JxW. This is what actually
- // happens: <code>fe_values.shape_grad(i,q_point)</code> returns a
+ // happens: <code>fe_values.shape_grad(i,q_index)</code> returns a
// <code>dim</code> dimensional vector, represented by a
// <code>Tensor@<1,dim@></code> object, and the operator* that
// multiplies it with the result of
- // <code>fe_values.shape_grad(j,q_point)</code> makes sure that the
+ // <code>fe_values.shape_grad(j,q_index)</code> makes sure that the
// <code>dim</code> components of the two vectors are properly
// contracted, and the result is a scalar floating point number that
// then is multiplied with the weights. Internally, this operator* makes
# Set the name of the project and target:
SET(TARGET "step-40")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
preconditioner package implementing algebraic multigrid; it can be
installed as part of PETSc but has to be explicitly enabled during
PETSc configuration; see the page linked to from the installation
-instructions for PETSc. Finally, note that
-PETSc appears not to co-operate well when using
-threads and the program crashes when deal.II is compiled in its usual mode
-supporting multithreading. The program can therefore only be compiled and run
-if multithreading is disabled upon configuration of deal.II using the
-<code>--disable-threads</code> switch to <code>./configure</code>.
+instructions for PETSc.
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{41.5}
+
Given today's computers, most finite element computations can be done on
a single machine. The majority of previous tutorial programs therefore
shows only this, possibly splitting up work among a number of
Number of degrees of freedom: 4225
Solved in 10 iterations.
+
++---------------------------------------------+------------+------------+
+| Total wallclock time elapsed since start | 0.176s | |
+| | | |
+| Section | no. calls | wall time | % of total |
++---------------------------------+-----------+------------+------------+
+| assembly | 1 | 0.0209s | 12% |
+| output | 1 | 0.0189s | 11% |
+| setup | 1 | 0.0299s | 17% |
+| solve | 1 | 0.0419s | 24% |
++---------------------------------+-----------+------------+------------+
+
+
Cycle 1:
Number of active cells: 1954
Number of degrees of freedom: 8399
- Solved in 11 iterations.
+ Solved in 10 iterations.
-Cycle 2:
- Number of active cells: 3640
- Number of degrees of freedom: 16091
- Solved in 11 iterations.
-Cycle 3:
- Number of active cells: 7018
- Number of degrees of freedom: 31387
++---------------------------------------------+------------+------------+
+| Total wallclock time elapsed since start | 0.327s | |
+| | | |
+| Section | no. calls | wall time | % of total |
++---------------------------------+-----------+------------+------------+
+| assembly | 1 | 0.0368s | 11% |
+| output | 1 | 0.0208s | 6.4% |
+| refine | 1 | 0.157s | 48% |
+| setup | 1 | 0.0452s | 14% |
+| solve | 1 | 0.0668s | 20% |
++---------------------------------+-----------+------------+------------+
+
+
+Cycle 2:
+ Number of active cells: 3664
+ Number of degrees of freedom: 16183
Solved in 11 iterations.
-Cycle 4:
- Number of active cells: 13594
- Number of degrees of freedom: 61531
- Solved in 13 iterations.
-
-Cycle 5:
- Number of active cells: 26950
- Number of degrees of freedom: 122693
- Solved in 13 iterations.
-
-Cycle 6:
- Number of active cells: 54373
- Number of degrees of freedom: 248265
- Solved in 14 iterations.
-
-Cycle 7:
- Number of active cells: 111754
- Number of degrees of freedom: 513153
- Solved in 14 iterations.
+...
@endcode
The exact numbers differ, depending on how many processors we use;
/* ---------------------------------------------------------------------
* $Id$
*
- * Copyright (C) 2009 - 2013 by the deal.II authors
+ * Copyright (C) 2009 - 2014 by the deal.II authors
*
* This file is part of the deal.II library.
*
#ifdef USE_PETSC_LA
data.symmetric_operator = true;
#else
- //trilinos defaults are good
+ /* Trilinos defaults are good */
#endif
preconditioner.initialize(system_matrix, data);
output_results (cycle);
}
- pcout << std::endl;
computing_timer.print_summary ();
computing_timer.reset ();
- }
+ pcout << std::endl;
+ }
}
}
# Set the name of the project and target:
SET(TARGET "step-41")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-42")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Define the output that should be cleaned:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
if (transfer_solution)
{
TrilinosWrappers::MPI::Vector distributed_solution(locally_owned_dofs, mpi_communicator);
- distributed_solution = solution;
solution_transfer.interpolate(distributed_solution);
solution = distributed_solution;
compute_nonlinear_residual(solution);
# Set the name of the project and target:
SET(TARGET "step-43")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-44")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
// We've chosen by default a SSOR preconditioner as it appears to
// provide the fastest solver convergence characteristics for this
- // problem on a single-thread machine. However, for multicore
- // computing, the Jacobi preconditioner which is multithreaded may
- // converge quicker for larger linear systems.
+ // problem on a single-thread machine. However, this might not be
+ // true for different problem sizes.
PreconditionSelector<SparseMatrix<double>, Vector<double> >
preconditioner (parameters.preconditioner_type,
parameters.preconditioner_relaxation);
# Set the name of the project and target:
SET(TARGET "step-45")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-46")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-47")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-48")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
each cell, the local indices of DoFs that are constrained as well as
the identifier of the type of constraint. Actually, you will not see
these data structures in the example program since the class
-<code>FEEvaluationGL</code> takes care of the constraints without user
+<code>FEEvaluation</code> takes care of the constraints without user
interaction.
data.initialize_dof_vector (inv_mass_matrix);
- FEEvaluationGL<dim,fe_degree> fe_eval(data);
+ FEEvaluation<dim,fe_degree> fe_eval(data);
const unsigned int n_q_points = fe_eval.n_q_points;
for (unsigned int cell=0; cell<data.n_macro_cells(); ++cell)
// This operator implements the core operation of the program, the
// integration over a range of cells for the nonlinear operator of the
- // Sine-Gordon problem. The implementation is based on the FEEvaluationGL
- // class since we are using the cell-based implementation for Gauss-Lobatto
- // elements.
+ // Sine-Gordon problem. The implementation is based on the FEEvaluation
+ // class as in step-37. Due to the special structure in Gauss-Lobatto
+ // elements, certain operations become simpler, in particular the evaluation
+ // of shape function values on quadrature points which is simply the
+ // injection of the values of cell degrees of freedom. The MatrixFree class
+ // detects possible structure of the finite element at quadrature points
+ // when initializing, which is then used by FEEvaluation for selecting the
+ // most appropriate numerical kernel.
// The nonlinear function that we have to evaluate for the time stepping
// routine includes the value of the function at the present time @p current
const std::pair<unsigned int,unsigned int> &cell_range) const
{
AssertDimension (src.size(), 2);
- FEEvaluationGL<dim,fe_degree> current (data), old (data);
+ FEEvaluation<dim,fe_degree> current (data), old (data);
for (unsigned int cell=cell_range.first; cell<cell_range.second; ++cell)
{
current.reinit (cell);
ConditionalOStream pcout;
void make_grid_and_dofs ();
- void oldstyle_operation ();
- void assemble_system ();
void output_results (const unsigned int timestep_number);
#ifdef DEAL_II_WITH_P4EST
# Set the name of the project and target:
SET(TARGET "step-49")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-5")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{14}
This example does not show revolutionary new things, but it shows many
small improvements over the previous examples, and also many small
complex, so debugging is an important aspect. We support safe
programming by using assertions that check the validity of
parameters and %internal states in a debug mode, but are removed
- in optimized mode.
+ in optimized mode. (@dealiiVideoLectureSeeAlso{18})
<li> Regarding the mathematical side, we show how to support a
variable coefficient in the elliptic operator and how to use
preconditioned iterative solvers for the linear systems of
coefficient.value_list (fe_values.get_quadrature_points(),
coefficient_values);
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (coefficient_values[q_point] *
- fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) *
- fe_values.JxW(q_point));
+ cell_matrix(i,j) += (coefficient_values[q_index] *
+ fe_values.shape_grad(i,q_index) *
+ fe_values.shape_grad(j,q_index) *
+ fe_values.JxW(q_index));
- cell_rhs(i) += (fe_values.shape_value(i,q_point) *
+ cell_rhs(i) += (fe_values.shape_value(i,q_index) *
1.0 *
- fe_values.JxW(q_point));
+ fe_values.JxW(q_index));
}
# Set the name of the project and target:
SET(TARGET "step-50")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Define the output that should be cleaned:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
# Set the name of the project and target:
SET(TARGET "step-51")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
\\
- (\nabla w, \mathbf{c} u_h)_{\mathcal{T}}
+ (w, \nabla \cdot \mathbf{q}_h)_{\mathcal{T}}
- + (w, (\mathbf{c}\cdot\mathbf{n}) \hat{u}_H)_{\mathcal{T}}
+ + (w, (\mathbf{c}\cdot\mathbf{n}) \hat{u}_H)_{\partial \mathcal{T}}
+ \left<w, \tau (u_h - \hat{u}_h)\right>_{\partial \mathcal{T}}
&=&
(w, f)_{\mathcal{T}},
--- /dev/null
+##
+# CMake script for the step-52 tutorial program:
+##
+
+# Set the name of the project and target:
+SET(TARGET "step-52")
+
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
+SET(TARGET_SRC
+ ${TARGET}.cc
+ )
+
+# Usually, you will not need to modify anything beyond this point...
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
+
+FIND_PACKAGE(deal.II 8.2 QUIET
+ HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
+ )
+IF(NOT ${deal.II_FOUND})
+ MESSAGE(FATAL_ERROR "\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
+ "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
+ "or set an environment variable \"DEAL_II_DIR\" that contains this path."
+ )
+ENDIF()
+
+DEAL_II_INITIALIZE_CACHED_VARIABLES()
+PROJECT(${TARGET})
+DEAL_II_INVOKE_AUTOPILOT()
--- /dev/null
+<br>
+
+<i>This program was contributed by Bruno Turcksin and Damien Lebrun-Grandie.</i>
+
+<a name="Intro"></a>
+<h1>Introducion</h1>
+
+This program shows how to use Runge-Kutta methods to solve a time-dependent
+problem. It solves a small variation of the heat equation discussed first in
+step-26 but, since the purpose of this program is only to demonstrate using
+more advanced ways to interface with deal.II's time stepping algorithms, only
+solves a simple problem on a uniformly refined mesh.
+
+
+<h3>Problem statement</h3>
+
+In this example, we solve the one-group time-dependent diffusion
+approximation of the neutron transport equation (see step-28 for the
+time-independent multigroup diffusion). This is a model for how neutrons move
+around highly scattering media, and consequently it is a variant of the
+time-dependent diffusion equation -- which is just a different name for the
+heat equation discussed in step-26, plus some extra terms.
+We assume that the medium is not
+fissible and therefore, the neutron flux satisfies the following equation:
+@f{eqnarray*}
+\frac{1}{v}\frac{\partial \phi(x,t)}{\partial t} = \nabla \cdot D(x) \nabla \phi(x,t)
+- \Sigma_a(x) \phi(x,t) + S(x,t)
+@f}
+augmented by appropriate boundary conditions. Here, $v$ is the velocity of
+neutrons (for simplicity we assume it is equal to 1 which can be achieved by
+simply scaling the time variable), $D$ is the diffusion coefficient,
+$\Sigma_a$ is the absorption cross section, and $S$ is a source. Because we are
+only interested in the time dependence, we assume that $D$ and $\Sigma_a$ are
+constant.
+
+Since this program only intends to demonstrate how to use advanced time
+stepping algorithms, we will only look for the solutions of relatively simple
+problems. Specifically, we are looking for a solution on a square domain
+$[0,b]\times[0,b]$ of the form
+@f{eqnarray*}
+\phi(x,t) = A\sin(\omega t)(bx-x^2).
+@f}
+By using quadratic finite elements, we can represent this function exactly at
+any particular time, and all the error will be due to the time discretization. We
+impose the following boundary conditions: homogeneous Dirichlet for $x=0$ and
+$x=b$ and homogeneous Neumann conditions for $y=0$ and $y=b$. We choose the
+source term so that the corresponding solution is
+in fact of the form stated above:
+@f{eqnarray*}
+S=A\left(\frac{1}{v}\omega \cos(\omega t)(bx -x^2) + \sin(\omega t)
+\left(\Sigma_a (bx-x^2)+2D\right) \right).
+@f}
+Because the solution is a sine, we know that $\phi\left(x,\pi\right) = 0$.
+Therefore, the error at time $t=\pi$ is simply the norm of the numerical
+solution and is particularly easily evaluated.
+
+
+<h3>Runge-Kutta methods</h3>
+
+The Runge-Kutta methods implemented in deal.II assume that the equation to be
+solved can be written as:
+@f{eqnarray*}
+\frac{dy}{dt} = g(t,y).
+@f}
+On the other hand, when using finite elements, discretized time derivatives always result in the
+presence of a mass matrix on the left hand side. This can easily be seen by
+considering that if the solution vector $y(t)$ in the equation above is in fact the vector
+of nodal coefficients $U(t)$ for a variable of the form
+@f{eqnarray*}
+ u_h(x,t) = \sum_j U_j(t) \varphi_j(x)
+@f}
+with spatial shape functions $\varphi_j(x)$, then multiplying an equation of
+the form
+@f{eqnarray*}
+ \frac{\partial u(x,t)}{\partial t} = q(t,u(x,t))
+@f}
+by test functions, integrating over $\Omega$, substituting $u\rightarrow u_h$
+and restricting the test functions to the $\varphi_i(x)$ from above, then this
+spatially discretized equation has the form
+@f{eqnarray*}
+M\frac{dU}{dt} = f(t,U),
+@f}
+where $M$ is the mass matrix and $f(t,U)$ is the spatially discretized version
+of the $q(t,u(x,t))$ (where $q$ is typically the place where spatial
+derivatives appear, but this is not of much concern for the moment given that
+we only consider time derivatives). In other words, this form fits the general
+scheme above if we write
+@f{eqnarray*}
+\frac{dy}{dt} = g(t,y) = M^{-1}f(t,y).
+@f}
+
+Runke-Kutta methods are time stepping schemes that approximate $y(t_n)\approx
+y_{n}$ through a particular one-step approach. They are typically written in the form
+@f{eqnarray*}
+y_{n+1} = y_n + \sum_{i=1}^s b_i k_i
+@f}
+where for the form of the right hand side above
+@f{eqnarray*}
+k_i = h M^{-1} f\left(t_n+c_ih,y_n+\sum_{j=1}^sa_{ij}k_j\right).
+@f}
+Here $a_{ij}$, $b_i$, and $c_i$ are known coefficients that identify which
+particular Runge-Kutta scheme you want to use, and $h=t_{n+1}-t_n$ is the time step
+used. Different time stepping methods of the Runge-Kutta class differ in the
+number of stages $s$ and the values they use for the coefficients $a_{ij}$,
+$b_i$, and $c_i$ but are otherwise easy to implement since one can look up
+tabulated values for these coefficients. (These tables are often called
+Butcher tableaus.)
+
+At the time of the writing of this tutorial, the methods implemented in
+deal.II can be divided in three categories:
+<ol>
+<li> explicit Runge-Kutta
+<li> embedded (or adaptive) Runge-Kutta
+<li> implicit Runge-Kutta
+</ol>
+Many well known time stepping schemes that one does not typically associated
+with the names Runge or Kutta can in fact be written in a way so that they,
+too, can be expressed in these categories. They oftentimes represent the
+lowest-order members of these families.
+
+
+<h4>Explicit Runge-Kutta methods</h4>
+
+These methods, only require a function to evaluate $M^{-1}f(t,y)$ but not
+(as implicit methods) to solve an equation that involves
+$f(t,y)$ for $y$. As all explicit time stepping methods, they become unstable
+when the time step chosen is too large.
+
+Well known methods in this class include forward Euler, third order
+Runge-Kutta, and fourth order Runge-Kutta (often abbreviated as RK4).
+
+
+<h4>Embedded Runge-Kutta methods</h4>
+
+These methods use both a lower and a higher order method to
+estimate the error and decide if the time step needs to be shortened or can be
+increased. The term "embedded" refers to the fact that the lower-order method
+does not require additional evaluates of the function $M^{-1}f(\cdot,\cdot)$
+but reuses data that has to be computed for the high order method anyway. It
+is, in other words, essentially free, and we get the error estimate as a side
+product of using the higher order method.
+
+This class of methods include Heun-Euler, Bogacki-Shampine, Dormand-Prince (ode45 in
+Matlab and often abbreviated as RK45 to indicate that the lower and higher order methods
+used here are 4th and 5th order Runge-Kutta methods, respectively), Fehlberg,
+and Cash-Karp.
+
+At the time of the writing, only embedded explicit methods have been implemented.
+
+
+<h4>Implicit Runge-Kutta methods</h4>
+
+Implicit methods require the solution of (possibly nonlinear) systems of the
+form $\alpha y = f(t,y)$
+for $y$ in each (sub-)timestep. Internally, this is
+done using a Newton-type method and, consequently, they require that the user
+provide functions that can evaluate $M^{-1}f(t,y)$ and
+$\left(I-\Delta t M^{-1} \frac{\partial f}{\partial y}\right)^{-1}$ or equivalently
+$\left(M - \Delta t \frac{\partial f}{\partial y}\right)^{-1} M$.
+
+The particular form of this operator results from the fact that each Newton
+step requires the solution of an equation of the form
+@f{align*}
+ \left(M - \Delta t \frac{\partial f}{\partial y}\right) \Delta y
+ = -M h(t,y)
+@f}
+for some (given) $h(t,y)$. Implicit methods are
+always stable, regardless of the time step size, but too large time steps of
+course affect the <i>accuracy</i> of the solution, even if the numerical
+solution remains stable and bounded.
+
+Methods in this class include backward Euler, implicit midpoint,
+Crank-Nicolson, and a two stage SDIRK.
+
+
+<h3>Spatially discrete formulation</h3>
+
+By expanding the solution as always using shape functions $\psi_j$ and writing
+@f{eqnarray*}
+\phi_h(x,t) = \sum_j U_j(t) \psi_j(x),
+@f}
+we immediately get the spatially discretized version of the diffusion equation as
+@f{eqnarray*}
+ M \frac{dU(t)}{dt}
+ = -{\cal D} U(t) - {\cal A} U(t) + {\cal S}(t)
+@f}
+where
+@f{eqnarray*}
+ M_{ij} &=& (\psi_i,\psi_j), \\
+ {\cal D}_{ij} &=& (D\nabla\psi_i,\nabla\psi_j)_\Omega, \\
+ {\cal A}_{ij} &=& (\Sigma_a\psi_i,\psi_j)_\Omega, \\
+ {\cal S}_{i}(t) &=& (\psi_i,S(x,t))_\Omega.
+@f}
+See also step-24 and step-26 to understand how we arrive here.
+%Boundary terms are not necessary due to the chosen boundary conditions for
+the current problem. To use the Runge-Kutta methods, we can then recast this
+as follows:
+@f{eqnarray*}
+f(y) = -{\cal D}y - {\cal A}y + {\cal S}
+@f}
+In the code, we will need to be able to evaluate this function $f(U)$ along
+with its derivative.
+
+
+<h3>Notes on the testcase</h3>
+
+To simplify the problem, the domain is two dimensional and the mesh is
+uniformly refined (there is no need to adapt the mesh since we use quadratic
+finite elements and the exact solution is quadratic). Going from a two
+dimensional domain to a three dimensional domain is not very
+challenging. However if you intend to solve more complex problems where the
+mesh must be adapted (as is done, for example, in step-26), then it is
+important to remember the following issues:
+
+<ol>
+<li> You will need to project the solution to the new mesh when the mesh is changed. Of course,
+ the mesh
+ used should be the same at the beginning and at the end of the time step,
+ a question that arises because Runge-Kutta methods use multiple
+ evaluations of the equations within each time step.
+<li> You will need to update the mass matrix and its inverse every time the
+ mesh is changed.
+</ol>
+The techniques for these steps are readily available by looking at step-26.
--- /dev/null
+time dependent
--- /dev/null
+<h1>Results</h1>
+
+The point of this program is less to show partcular results, but instead to
+show how it is done and that we have already demonstrated using the code
+above. Consequently, the output the program yields is relatively sparse and
+consists only of the console output and the solutions given in
+VTU format for visualization.
+
+The console output contains both errors and, for some of the methods, the
+number of steps they performed:
+@code
+Explicit methods:
+Forward Euler: error=1.00883
+Third order Runge-Kutta: error=0.000227982
+Fourth order Runge-Kutta: error=1.90541e-06
+
+Implicit methods:
+Backward Euler: error=1.03428
+Implicit Midpoint: error=0.00862702
+Crank-Nicolson: error=0.00862675
+SDIRK: error=0.0042349
+
+Embedded explicit methods:
+Heun-Euler: error=0.0073012
+ steps performed=284
+Bogacki-Shampine: error=0.000207511
+ steps performed=200
+Dopri: error=4.01774e-09
+ steps performed=200
+Fehlberg: error=9.89504e-09
+ steps performed=200
+Cash-Karp: error=2.55791e-10
+ steps performed=200
+@endcode
+
+As expected the higher order methods give (much) more accurate solutions. We
+also see that the (rather inaccurate) Heun-Euler method adapted the number of
+time steps in order to satisfy the tolerance. On the other hand, the other
+embedded methods did not need to change the number of time steps as they are
+easily able to reach the desired tolerance with the given time step size.
--- /dev/null
+Time-dependent diffusion equation. Neutron transport
--- /dev/null
+/* ---------------------------------------------------------------------
+ * $Id: step-52.cc 30526 2013-08-29 20:06:27Z felix.gruber $
+ *
+ * Copyright (C) 2014 by the deal.II authors
+ *
+ * This file is part of the deal.II library.
+ *
+ * The deal.II library is free software; you can use it, redistribute
+ * it, and/or modify it under the terms of the GNU Lesser General
+ * Public License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * The full text of the license can be found in the file LICENSE at
+ * the top level of the deal.II distribution.
+ *
+ * ---------------------------------------------------------------------
+
+ *
+ * Authors: Damien Lebrun-Grandie, Bruno Turcksin, 2014
+ */
+
+// @sect3{Include files}
+
+// The first task as usual is to include the functionality of these well-known
+// deal.II library files and some C++ header files.
+#include <deal.II/base/function.h>
+#include <deal.II/base/quadrature_lib.h>
+
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/tria_accessor.h>
+#include <deal.II/grid/tria_iterator.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/grid_out.h>
+
+#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/dofs/dof_accessor.h>
+#include <deal.II/dofs/dof_tools.h>
+
+#include <deal.II/fe/fe_q.h>
+#include <deal.II/fe/fe_values.h>
+
+#include <deal.II/lac/constraint_matrix.h>
+#include <deal.II/lac/sparse_direct.h>
+
+#include <deal.II/numerics/vector_tools.h>
+#include <deal.II/numerics/data_out.h>
+
+#include <fstream>
+#include <iostream>
+#include <cmath>
+#include <map>
+
+// This is the only include file that is new: It includes all the Runge-Kutta
+// methods.
+#include <deal.II/base/time_stepping.h>
+
+
+// The next step is like in all previous tutorial programs: We put everything
+// into a namespace of its own and then import the deal.II classes and functions
+// into it.
+namespace Step52
+{
+ using namespace dealii;
+
+ // @sect3{Diffusion}
+
+ // Now, here comes the declaration of the main class. Most of the functions in
+ // this class are not new and have been explained in previous tutorials.
+ class Diffusion
+ {
+ public:
+ Diffusion();
+
+ void run();
+
+ private:
+ void setup_system();
+
+ void assemble_system();
+
+ double get_source(double time,const Point<2> &point) const;
+
+ // This function evaluates the diffusion equation $M^{-1}(f(t,y))$ at a given time and
+ // for a given y.
+ Vector<double> evaluate_diffusion(const double time, const Vector<double> &y) const;
+
+ // Evaluate $\left(I-\tau M^{-1} \frac{\partial f(t,y)}{\partial y}\right)^{-1}$ or
+ // equivalently $\left(M-\tau \frac{\partial f}{\partial y}\right)^{-1} M$ at a given
+ // time, for a given $\tau$ and y.
+ Vector<double> id_minus_tau_J_inverse(const double time,
+ const double tau,
+ const Vector<double> &y);
+
+ void output_results(unsigned int time_step,TimeStepping::runge_kutta_method method) const;
+
+ // The next three functions are the driver for the explicit methods, the
+ // implicit methods, and the embedded explicit methods respectively. The
+ // driver function for embedded explicit methods returns the number of
+ // steps executed since this number is adapted.
+ void explicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time);
+
+ void implicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time);
+
+ unsigned int embedded_explicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time);
+
+
+ unsigned int fe_degree;
+
+ double diffusion_coefficient;
+ double absorption_xs;
+
+ Triangulation<2> triangulation;
+
+ FE_Q<2> fe;
+
+ DoFHandler<2> dof_handler;
+
+ ConstraintMatrix constraint_matrix;
+
+ SparsityPattern sparsity_pattern;
+
+ SparseMatrix<double> system_matrix;
+ SparseMatrix<double> mass_matrix;
+ SparseMatrix<double> mass_minus_tau_Jacobian;
+
+ SparseDirectUMFPACK inverse_mass_matrix;
+
+ Vector<double> solution;
+ };
+
+
+
+ // We choose quadratic finite elements and we initialize the parameters.
+ Diffusion::Diffusion()
+ :
+ fe_degree(2),
+ diffusion_coefficient(1./30.),
+ absorption_xs(1.),
+ fe(fe_degree),
+ dof_handler(triangulation)
+ {}
+
+
+
+ // @sect5{<code>Diffusion::setup_system</code>}
+ // Now, we create the constraint matrix and the sparsity pattern. Then, we
+ // initialize the matrices that we will use and the solution vector.
+ void Diffusion::setup_system()
+ {
+ dof_handler.distribute_dofs(fe);
+
+ VectorTools::interpolate_boundary_values(dof_handler,1,ZeroFunction<2>(),constraint_matrix);
+ constraint_matrix.close();
+
+ CompressedSparsityPattern c_sparsity(dof_handler.n_dofs());
+ DoFTools::make_sparsity_pattern(dof_handler,c_sparsity,constraint_matrix);
+ sparsity_pattern.copy_from(c_sparsity);
+
+ system_matrix.reinit(sparsity_pattern);
+ mass_matrix.reinit(sparsity_pattern);
+ mass_minus_tau_Jacobian.reinit(sparsity_pattern);
+ solution.reinit(dof_handler.n_dofs());
+ }
+
+
+
+ // @sect5{<code>Diffusion::assemble_system</code>}
+ // In this function, we compute
+ // $-\int D \nabla b_i \cdot \nabla b_j d\boldsymbol{r} - \int \Sigma_a b_i b_j d\boldsymbol{r}$
+ // and the mass matrix $\int b_i b_j d\boldsymbol{r}$. The mass matrix is then
+ // inverted using a direct solver.
+ void Diffusion::assemble_system()
+ {
+ system_matrix = 0.;
+ mass_matrix = 0.;
+
+ const QGauss<2> quadrature_formula(fe_degree+1);
+
+ FEValues<2> fe_values(fe, quadrature_formula,
+ update_values | update_gradients | update_JxW_values);
+
+
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell);
+ FullMatrix<double> cell_mass_matrix (dofs_per_cell, dofs_per_cell);
+
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<2>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+
+ for (; cell!=endc; ++cell)
+ {
+ cell_matrix = 0.;
+ cell_mass_matrix = 0.;
+
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ cell_matrix(i,j) += ((-diffusion_coefficient * fe_values.shape_grad(i,q_point) *
+ fe_values.shape_grad(j,q_point) - absorption_xs *
+ fe_values.shape_value(i,q_point) * fe_values.shape_value(j,q_point)) *
+ fe_values.JxW(q_point));
+ cell_mass_matrix(i,j) += fe_values.shape_value(i,q_point) *
+ fe_values.shape_value(j,q_point) *
+ fe_values.JxW(q_point);
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+
+ constraint_matrix.distribute_local_to_global(cell_matrix,local_dof_indices,system_matrix);
+ constraint_matrix.distribute_local_to_global(cell_mass_matrix,local_dof_indices,mass_matrix);
+ }
+
+ inverse_mass_matrix.initialize(mass_matrix);
+ }
+
+
+
+ // @sect5{<code>Diffusion::get_source</code>}
+ //
+ // In this function, the source for a given time and a given point is
+ // computed.
+ double Diffusion::get_source(double time,const Point<2> &point) const
+ {
+ const double pi = 3.14159265358979323846;
+ const double intensity = 10.;
+ const double frequency = pi/10.;
+ const double b = 5.;
+ const double x = point(0);
+ double source = 0.;
+
+ source = intensity*(frequency*std::cos(frequency*time)*(b*x-x*x) + std::sin(frequency*time) *
+ (absorption_xs*(b*x-x*x)+2.*diffusion_coefficient));
+
+ return source;
+ }
+
+
+
+ // @sect5{<code>Diffusion:evaluate_diffusion</code>}
+ //
+ // Now, the weak form of the diffusion equation is evaluated at a given time t and for a given vector y.
+ Vector<double> Diffusion::evaluate_diffusion(const double time, const Vector<double> &y) const
+ {
+ Vector<double> tmp(dof_handler.n_dofs());
+ tmp = 0.;
+ system_matrix.vmult(tmp,y);
+
+ const QGauss<2> quadrature_formula(fe_degree+1);
+
+ FEValues<2> fe_values(fe, quadrature_formula,
+ update_values | update_quadrature_points | update_JxW_values);
+
+
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int n_q_points = quadrature_formula.size();
+
+ Vector<double> cell_source(dofs_per_cell);
+
+ std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
+
+ typename DoFHandler<2>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+
+ for (; cell!=endc; ++cell)
+ {
+ cell_source = 0.;
+
+ fe_values.reinit (cell);
+
+ for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ {
+ double source = get_source(time,fe_values.quadrature_point(q_point)) ;
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_source(i) += source * fe_values.shape_value(i,q_point) *
+ fe_values.JxW(q_point);
+ }
+
+ cell->get_dof_indices(local_dof_indices);
+
+ constraint_matrix.distribute_local_to_global(cell_source,local_dof_indices,tmp);
+ }
+
+
+ Vector<double> value(dof_handler.n_dofs());
+ inverse_mass_matrix.vmult(value,tmp);
+
+ return value;
+ }
+
+
+ // @sect5{<code>Diffusion::id_minus_tau_J_inverse</code>}
+ //
+ // We compute $\left(M-\tau \frac{\partial f}{\partial y}\right)^{-1} M$. This
+ // is done in several steps:
+ // - compute $M-\tau \frac{\partial f}{\partial y}$
+ // - inverse the matrix to get $\left(M-\tau \frac{\partial f}{\partial y}\right)^{-1}$
+ // - compute $tmp=My$
+ // - compute $\left(M-\tau \frac{\partial f}{\partial y}\right)^{-1} tmp = \left(M-\tau \frac{\partial f}{\partial y}\right)^{-1} My$.
+ Vector<double> Diffusion::id_minus_tau_J_inverse(const double time, const double tau,
+ const Vector<double> &y)
+ {
+ Vector<double> tmp(dof_handler.n_dofs());
+ Vector<double> result(y);
+ SparseDirectUMFPACK inverse_mass_minus_tau_Jacobian;
+
+ mass_minus_tau_Jacobian.copy_from(mass_matrix);
+ mass_minus_tau_Jacobian.add(-tau,system_matrix);
+
+ inverse_mass_minus_tau_Jacobian.initialize(mass_minus_tau_Jacobian);
+
+ mass_matrix.vmult(tmp,y);
+
+ inverse_mass_minus_tau_Jacobian.vmult(result,tmp);
+
+ return result;
+ }
+
+
+
+ // @sect5{<code>Diffusion::output_results}
+ //
+ // We output the solution in vtu files.
+ void Diffusion::output_results(unsigned int time_step,TimeStepping::runge_kutta_method method) const
+ {
+ std::string method_name;
+
+ switch (method)
+ {
+ case TimeStepping::FORWARD_EULER :
+ {
+ method_name = "forward_euler";
+ break;
+ }
+ case TimeStepping::RK_THIRD_ORDER :
+ {
+ method_name = "rk3";
+ break;
+ }
+ case TimeStepping::RK_CLASSIC_FOURTH_ORDER :
+ {
+ method_name = "rk4";
+ break;
+ }
+ case TimeStepping::BACKWARD_EULER :
+ {
+ method_name = "backward_euler";
+ break;
+ }
+ case TimeStepping::IMPLICIT_MIDPOINT :
+ {
+ method_name = "implicit_midpoint";
+ break;
+ }
+ case TimeStepping::SDIRK_TWO_STAGES :
+ {
+ method_name = "sdirk";
+ break;
+ }
+ case TimeStepping::HEUN_EULER :
+ {
+ method_name = "heun_euler";
+ break;
+ }
+ case TimeStepping::BOGACKI_SHAMPINE :
+ {
+ method_name = "bocacki_shampine";
+ break;
+ }
+ case TimeStepping::DOPRI :
+ {
+ method_name = "dopri";
+ break;
+ }
+ case TimeStepping::FEHLBERG :
+ {
+ method_name = "fehlberg";
+ break;
+ }
+ case TimeStepping::CASH_KARP :
+ {
+ method_name = "cash_karp";
+ break;
+ }
+ default :
+ {
+ break;
+ }
+ }
+
+ DataOut<2> data_out;
+
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(solution, "solution");
+
+ data_out.build_patches();
+
+ const std::string filename = "solution-" + method_name + "-" +
+ Utilities::int_to_string (time_step, 3) +
+ ".vtu";
+ std::ofstream output(filename.c_str());
+ data_out.write_vtu(output);
+ }
+
+
+ // @sect5{<code>Diffusion::explicit_method</code>}
+ // This function is the driver for all the explicit method. It call
+ // evolve_one_time_step which performs one time step. evolve_one_time_step
+ // needs to evaluate $M^{-1}(f(t,y))$, i.e it needs evaluate_diffusion.
+ // Because evaluate_diffusion is a member function, it needs to be bind to
+ // $this$. Finally, the solution is output every 10 time steps.
+ void Diffusion::explicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time)
+ {
+ const double time_step = (final_time-initial_time)/static_cast<double> (n_time_steps);
+ double time = initial_time;
+ solution = 0.;
+
+ TimeStepping::ExplicitRungeKutta<Vector<double> > explicit_runge_kutta(method);
+ output_results(0,method);
+ for (unsigned int i=0; i<n_time_steps; ++i)
+ {
+ time = explicit_runge_kutta.evolve_one_time_step(
+ std_cxx1x::bind(&Diffusion::evaluate_diffusion,this,std_cxx1x::_1,std_cxx1x::_2),
+ time,time_step,solution);
+
+ if ((i+1)%10==0)
+ output_results(i+1,method);
+ }
+ }
+
+
+
+ // @sect5{<code>Diffusion::implicit_method</code>}
+ // This function is equivalent to explicit_method but for implicit methods.
+ // When using implicit methods, we need to evaluate $M^{-1}(f(t,y))$ and
+ // $\left(I-\tau M^{-1} \frac{\partial f(t,y)}{\partial y}\right)^{-1}$.
+ void Diffusion::implicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time)
+ {
+ const double time_step = (final_time-initial_time)/static_cast<double> (n_time_steps);
+ double time = initial_time;
+ solution = 0.;
+
+ TimeStepping::ImplicitRungeKutta<Vector<double> > implicit_runge_kutta(method);
+ output_results(0,method);
+ for (unsigned int i=0; i<n_time_steps; ++i)
+ {
+ time = implicit_runge_kutta.evolve_one_time_step(
+ std_cxx1x::bind(&Diffusion::evaluate_diffusion,this,std_cxx1x::_1,std_cxx1x::_2),
+ std_cxx1x::bind(&Diffusion::id_minus_tau_J_inverse,this,std_cxx1x::_1,std_cxx1x::_2,
+ std_cxx1x::_3),
+ time,time_step,solution);
+
+ if ((i+1)%10==0)
+ output_results(i+1,method);
+ }
+ }
+
+
+
+ // @sect5{<code>Diffusion::embedded_explicit_method</code>}
+ // This function is the driver for the embedded explict methods. It requires
+ // more parameters:
+ // - coarsen_param: factor multiplying the current time step when the error
+ // is below the threshold.
+ // - refine_param: factor multiplying the current time step when the error
+ // is above the threshold.
+ // - min_delta: smallest time step acceptable.
+ // - max_delta: largest time step acceptable.
+ // - refine_tol: threshold above which the time step is refined.
+ // - coarsen_tol: threshold below which the time step is coarsen.
+ // Embedded methods use a guessed time step. If the error using this time step
+ // is too large, the time step will be reduced. If the error is below the
+ // threshold, a larger time step will be tried for the next time step.
+ // delta_t_guess is the guessed time step produced by the embedded method.
+ unsigned int Diffusion::embedded_explicit_method(TimeStepping::runge_kutta_method method,
+ const unsigned int n_time_steps,
+ const double initial_time,
+ const double final_time)
+ {
+ double time_step = (final_time-initial_time)/static_cast<double> (n_time_steps);
+ double time = initial_time;
+ const double coarsen_param = 1.2;
+ const double refine_param = 0.8;
+ const double min_delta = 1e-8;
+ const double max_delta = 10*time_step;
+ const double refine_tol = 1e-1;
+ const double coarsen_tol = 1e-5;
+ solution = 0.;
+
+ TimeStepping::EmbeddedExplicitRungeKutta<Vector<double> > embedded_explicit_runge_kutta(method,
+ coarsen_param,refine_param,min_delta,max_delta,refine_tol,coarsen_tol);
+ output_results(0,method);
+ unsigned int n_steps=0;
+ while (time<final_time)
+ {
+ // We choose the last time step such that the final time is exactly
+ // reached.
+ if (time+time_step>final_time)
+ time_step = final_time-time;
+
+ time = embedded_explicit_runge_kutta.evolve_one_time_step(
+ std_cxx1x::bind(&Diffusion::evaluate_diffusion,this,std_cxx1x::_1,std_cxx1x::_2),
+ time,time_step,solution);
+
+ if ((n_steps+1)%10==0)
+ output_results(n_steps+1,method);
+
+ time_step = embedded_explicit_runge_kutta.get_status().delta_t_guess;
+ ++n_steps;
+ }
+
+ return n_steps;
+ }
+
+
+
+ // @sect5{<code>Diffusion::run</code>}
+ void Diffusion::run()
+ {
+ // We create the grid (a [0,5]x[0,5] square) and refine the mesh four times.
+ // The final grid has 16 by 16 cells, for a total of 256.
+ GridGenerator::hyper_cube(triangulation, 0., 5.);
+ triangulation.refine_global(4);
+
+ // Set the boundary indicator for x=0 and x=5 to 1.
+ typename Triangulation<2>::active_cell_iterator
+ cell = triangulation.begin_active(),
+ endc = triangulation.end();
+
+ for (; cell!=endc; ++cell)
+ for (unsigned int f=0; f<GeometryInfo<2>::faces_per_cell; ++f)
+ if (cell->face(f)->at_boundary())
+ {
+ if ((cell->face(f)->center()[0]==0.) || (cell->face(f)->center()[0]==5.))
+ cell->face(f)->set_boundary_indicator(1);
+ else
+ cell->face(f)->set_boundary_indicator(0);
+ }
+
+ setup_system();
+
+ assemble_system();
+
+ unsigned int n_steps = 0;
+ const unsigned int n_time_steps = 200;
+ const double initial_time = 0.;
+ const double final_time = 10.;
+
+ // Next, we solve the diffusion problem using different Runge-Kutta methods.
+ std::cout << "Explicit methods:" << std::endl;
+ explicit_method (TimeStepping::FORWARD_EULER,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Forward Euler: error=" << solution.l2_norm() << std::endl;
+
+ explicit_method (TimeStepping::RK_THIRD_ORDER,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Third order Runge-Kutta: error=" << solution.l2_norm() << std::endl;
+
+ explicit_method (TimeStepping::RK_CLASSIC_FOURTH_ORDER,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Fourth order Runge-Kutta: error=" << solution.l2_norm() << std::endl;
+ std::cout << std::endl;
+
+
+ std::cout << "Implicit methods:" << std::endl;
+ implicit_method (TimeStepping::BACKWARD_EULER,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Backward Euler: error=" << solution.l2_norm() << std::endl;
+
+ implicit_method (TimeStepping::IMPLICIT_MIDPOINT,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Implicit Midpoint: error=" << solution.l2_norm() << std::endl;
+
+ implicit_method (TimeStepping::CRANK_NICOLSON,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Crank-Nicolson: error=" << solution.l2_norm() << std::endl;
+
+ implicit_method (TimeStepping::SDIRK_TWO_STAGES,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "SDIRK: error=" << solution.l2_norm() << std::endl;
+ std::cout << std::endl;
+
+
+ std::cout << "Embedded explicit methods:" << std::endl;
+ n_steps = embedded_explicit_method (TimeStepping::HEUN_EULER,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Heun-Euler: error=" << solution.l2_norm() << std::endl;
+ std::cout << " steps performed=" << n_steps << std::endl;
+
+ n_steps = embedded_explicit_method (TimeStepping::BOGACKI_SHAMPINE,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Bogacki-Shampine: error=" << solution.l2_norm() << std::endl;
+ std::cout << " steps performed=" << n_steps << std::endl;
+
+ n_steps = embedded_explicit_method (TimeStepping::DOPRI,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Dopri: error=" << solution.l2_norm() << std::endl;
+ std::cout << " steps performed=" << n_steps << std::endl;
+
+ n_steps = embedded_explicit_method (TimeStepping::FEHLBERG,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Fehlberg: error=" << solution.l2_norm() << std::endl;
+ std::cout << " steps performed=" << n_steps << std::endl;
+
+ n_steps = embedded_explicit_method (TimeStepping::CASH_KARP,
+ n_time_steps,
+ initial_time,
+ final_time);
+ std::cout << "Cash-Karp: error=" << solution.l2_norm() << std::endl;
+ std::cout << " steps performed=" << n_steps << std::endl;
+ }
+}
+
+
+
+// @sect3{The <code>main()</code> function}
+//
+// The following <code>main</code> function is similar to previous examples as
+// well, and need not be commented on.
+int main ()
+{
+ try
+ {
+ Step52::Diffusion diffusion;
+ diffusion.run();
+ }
+ catch (std::exception &exc)
+ {
+ std::cerr << std::endl << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Exception on processing: " << std::endl
+ << exc.what() << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ return 1;
+ }
+ catch (...)
+ {
+ std::cerr << std::endl << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ std::cerr << "Unknown exception!" << std::endl
+ << "Aborting!" << std::endl
+ << "----------------------------------------------------"
+ << std::endl;
+ return 1;
+ };
+
+ return 0;
+}
--- /dev/null
+##
+# CMake script for the step-1 tutorial program:
+##
+
+# Set the name of the project and target:
+SET(TARGET "step-53")
+
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
+SET(TARGET_SRC
+ ${TARGET}.cc
+ )
+
+# Usually, you will not need to modify anything beyond this point...
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
+
+FIND_PACKAGE(deal.II 8.2 QUIET
+ HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
+ )
+IF(NOT ${deal.II_FOUND})
+ MESSAGE(FATAL_ERROR "\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
+ "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
+ "or set an environment variable \"DEAL_II_DIR\" that contains this path."
+ )
+ENDIF()
+
+DEAL_II_INITIALIZE_CACHED_VARIABLES()
+PROJECT(${TARGET})
+DEAL_II_INVOKE_AUTOPILOT()
--- /dev/null
+<a name="Intro"></a>
+<h1>Introduction</h1>
+
--- /dev/null
+techniques
--- /dev/null
+<h1>Results</h1>
+
--- /dev/null
+Geometry: Dealing with curved boundaries.
--- /dev/null
+/* ---------------------------------------------------------------------
+ * $Id$
+ *
+ * Copyright (C) 2014 by the deal.II authors
+ *
+ * This file is part of the deal.II library.
+ *
+ * The deal.II library is free software; you can use it, redistribute
+ * it, and/or modify it under the terms of the GNU Lesser General
+ * Public License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * The full text of the license can be found in the file LICENSE at
+ * the top level of the deal.II distribution.
+ *
+ * ---------------------------------------------------------------------
+
+ *
+ * Author: Wolfgang Bangerth, Texas A&M University, 2014
+ */
+
+#include <deal.II/grid/tria.h>
+#include <deal.II/grid/tria_boundary.h>
+#include <deal.II/grid/tria_boundary_lib.h>
+#include <deal.II/grid/grid_generator.h>
+#include <deal.II/grid/grid_out.h>
+
+#include <deal.II/base/std_cxx1x/array.h>
+
+#include <fstream>
+
+
+using namespace dealii;
+
+
+template <int dim>
+class SphereGeometry : public Boundary<dim>
+{
+public:
+ SphereGeometry (const Point<dim> ¢er);
+ virtual
+ Point<dim>
+ get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const;
+
+ virtual
+ Point<dim>
+ get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const;
+private:
+
+ std_cxx1x::array<double,dim> pull_back (const Point<dim> &p) const;
+ Point<dim> push_forward (const std_cxx1x::array<double,dim> &preimage) const;
+
+ template <int N>
+ static std_cxx1x::array<double,dim> average (const std_cxx1x::array<double,dim> (&array)[N]);
+
+ const Point<dim> center;
+};
+
+
+template <int dim>
+SphereGeometry<dim>::SphereGeometry (const Point<dim> ¢er)
+:
+center (center)
+{}
+
+
+template <>
+std_cxx1x::array<double,2>
+SphereGeometry<2>::pull_back (const Point<2> &p) const
+{
+ const Point<2> relative_point = p - center;
+
+ const double r = relative_point.norm();
+ const double phi = std::atan2 (relative_point[1], relative_point[0]);
+
+ std_cxx1x::array<double,2> result;
+ result[0] = r;
+ result[1] = phi;
+
+ return result;
+}
+
+
+template <>
+Point<2>
+SphereGeometry<2>::push_forward (const std_cxx1x::array<double,2> &preimage) const
+{
+ const Point<2> relative_point = preimage[0] * Point<2>(std::cos(preimage[1]), std::sin(preimage[1]));
+
+ return relative_point + center;
+}
+
+
+
+template <>
+std_cxx1x::array<double,3>
+SphereGeometry<3>::pull_back (const Point<3> &p) const
+{
+ const Point<3> relative_point = p - center;
+
+ const double r = relative_point.norm();
+ const double phi = std::atan2 (relative_point[1], relative_point[0]);
+ const double theta = std::atan2 (relative_point[2], std::sqrt (relative_point[0]*relative_point[0] +
+ relative_point[1]*relative_point[1]));
+
+ std_cxx1x::array<double,3> result;
+ result[0] = r;
+ result[1] = phi;
+ result[2] = theta;
+
+ return result;
+}
+
+
+template <>
+Point<3>
+SphereGeometry<3>::push_forward (const std_cxx1x::array<double,3> &preimage) const
+{
+ const Point<3> relative_point = (preimage[0] *
+ Point<3>(std::cos(preimage[1]),
+ std::sin(preimage[1]),
+ std::cos(preimage[2])));
+
+ return relative_point + center;
+}
+
+
+
+template <>
+template <int N>
+std_cxx1x::array<double,2>
+SphereGeometry<2>::average (const std_cxx1x::array<double,2> (&array)[N])
+{
+ std_cxx1x::array<double,2> result;
+
+ // average the radii first. this is uncritical
+ {
+ result[0] = 0;
+ for (unsigned int i=0; i<N; ++i)
+ result[0] += array[i][0];
+ result[0] /= N;
+ }
+
+ // now do the angle. there, we need to
+ // be more careful because the average of 0.9*pi and -0.9*pi should not
+ // be zero but pi. to this end, bring everything that is farther than
+ // pi away from the first angle we want to average with, back to within pi
+ // by adding/subtracting 2*pi
+ //
+ // we also want to make sure that we exclude from averaging all points
+ // that lie at the origin since they have no angle at all
+ {
+ bool origin_is_one_point = false;
+
+ result[1] = 0;
+ for (unsigned int i=0; i<N; ++i)
+ if (array[i][0] > 1e-10)
+ {
+ const double angle = array[i][1];
+ if (angle - array[0][1] > numbers::PI)
+ result[1] += angle-2*numbers::PI;
+ else if (angle - array[0][1] < -numbers::PI)
+ result[1] += angle+2*numbers::PI;
+ else
+ result[1] += angle;
+ }
+ else
+ origin_is_one_point = true;
+
+ if (origin_is_one_point == false)
+ result[1] /= N;
+ else
+ result[1] /= (N-1);
+ }
+
+ return result;
+}
+
+
+
+template <>
+template <int N>
+std_cxx1x::array<double,3>
+SphereGeometry<3>::average (const std_cxx1x::array<double,3> (&array)[N])
+{
+ std_cxx1x::array<double,3> result;
+
+ // average the radii first. this is uncritical
+ {
+ result[0] = 0;
+ for (unsigned int i=0; i<N; ++i)
+ result[0] += array[i][0];
+ result[0] /= N;
+ }
+
+ // now do the angle along the equatorial direction. do the same as we did
+ // in the 2d case
+ {
+ bool origin_is_one_point = false;
+
+ result[1] = 0;
+ for (unsigned int i=0; i<N; ++i)
+ if (array[i][0] > 1e-10)
+ {
+ const double angle = array[i][1];
+ if (angle - array[0][1] > numbers::PI)
+ result[1] += angle-2*numbers::PI;
+ else if (angle - array[0][1] < -numbers::PI)
+ result[1] += angle+2*numbers::PI;
+ else
+ result[1] += angle;
+ }
+ else
+ origin_is_one_point = true;
+
+ if (origin_is_one_point == false)
+ result[1] /= N;
+ else
+ result[1] /= (N-1);
+ }
+
+ // finally for the polar angle. the difficulty here is that we have, for
+ // example, two points at (r,phi,theta) and (r,phi+pi,\pm pi/2), then we want
+ // to average these to (r,*,pi) where the equatorial angle does not matter
+ {
+ //??? not sure how exactly to do this
+ }
+
+
+ return result;
+}
+
+
+
+
+template <int dim>
+Point<dim>
+SphereGeometry<dim>::
+get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const
+{
+ std_cxx1x::array<double,dim> preimages[2] = { pull_back (line->vertex(0)),
+ pull_back (line->vertex(1)) };
+
+ return push_forward(average (preimages));
+}
+
+
+template <int dim>
+Point<dim>
+SphereGeometry<dim>::
+get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
+{
+ std_cxx1x::array<double,dim> preimages[4] = { pull_back (quad->vertex(0)),
+ pull_back (quad->vertex(1)),
+ pull_back (quad->vertex(2)),
+ pull_back (quad->vertex(3)) };
+
+ return push_forward(average(preimages));
+}
+
+
+
+
+template <int dim>
+void make_grid ()
+{
+ Point<dim> center;
+ for (unsigned int i=0; i<dim; ++i)
+ center[i] = .25;
+ const double radius=center.norm();
+
+ SphereGeometry<dim> geometry(center);
+ Triangulation<dim> triangulation;
+ GridGenerator::hyper_cube (triangulation);
+
+ triangulation.refine_global(1);
+
+ for (typename Triangulation<dim>::active_cell_iterator cell=triangulation.begin_active();
+ cell!=triangulation.end(); ++cell)
+ {
+ if (cell->center().distance(center)< radius)
+ cell->set_manifold_id(1);
+
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ if (cell->face(f)->center().distance(center)< radius)
+ cell->face(f)->set_all_manifold_ids(1);
+ }
+
+ triangulation.set_manifold(1,geometry);
+ triangulation.refine_global(1);
+
+ const std::string filename = "mesh-" + Utilities::int_to_string(dim) + "d.vtk";
+ std::ofstream out (filename.c_str());
+ GridOut grid_out;
+ grid_out.write_vtk (triangulation, out);
+}
+
+
+
+
+// @sect3{The main function}
+
+// Finally, the main function. There isn't much to do here, only to call the
+// subfunctions.
+int main ()
+{
+ make_grid<2> ();
+// make_grid<3> ();
+}
# Set the name of the project and target:
SET(TARGET "step-6")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
<a name="Intro"></a>
<h1>Introduction</h1>
+@dealiiVideoLecture{15,16,17}
The main emphasis in this example is the handling of locally refined
grids. The approach to adaptivity chosen in deal.II is to use grids in which
incorporate the them as constraints in the same ConstraintMatrix object.
This way, we don't need to apply the boundary conditions after assembly
(like we did in the earlier steps).
-
\ No newline at end of file
+
<code>DoFHandler</code> and <code>FE_Q</code>. The mangling works as
follows: the first number indicates the number of characters of the
template class, i.e. 10 for <code>DoFHandler</code> and 4
-for<code>FE_Q</code>; the rest of the text is then template
+for <code>FE_Q</code>; the rest of the text is then template
arguments. From this we can already glean a little bit who's the
culprit here, and who the victim:
The one object that still uses the finite element is the
coefficient.value_list (fe_values.get_quadrature_points(),
coefficient_values);
- for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
+ for (unsigned int q_index=0; q_index<n_q_points; ++q_index)
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_matrix(i,j) += (coefficient_values[q_point] *
- fe_values.shape_grad(i,q_point) *
- fe_values.shape_grad(j,q_point) *
- fe_values.JxW(q_point));
+ cell_matrix(i,j) += (coefficient_values[q_index] *
+ fe_values.shape_grad(i,q_index) *
+ fe_values.shape_grad(j,q_index) *
+ fe_values.JxW(q_index));
- cell_rhs(i) += (fe_values.shape_value(i,q_point) *
+ cell_rhs(i) += (fe_values.shape_value(i,q_index) *
1.0 *
- fe_values.JxW(q_point));
+ fe_values.JxW(q_index));
}
// Finally, transfer the contributions from @p cell_matrix and
system_matrix,
system_rhs);
}
- // Now we are done assembling the linear system. The constrained nodes are
- // still in the linear system (there is a one on the diagonal of the matrix
- // and all other entries for this line are set to zero) but the computed
- // values are invalid. We compute the correct values for these nodes at the
- // end of the <code>solve</code> function.
+ // Now we are done assembling the linear system. The constraint matrix took
+ // care of applying the boundary conditions and also eliminated hanging node
+ // constraints. The constrained nodes are still in the linear system (there
+ // is a one on the diagonal of the matrix and all other entries for this
+ // line are set to zero) but the computed values are invalid. We compute the
+ // correct values for these nodes at the end of the <code>solve</code>
+ // function.
}
// quartic function, for which a 3 point Gauss formula is sufficient since it
// integrates polynomials up to order 5 exactly.)
//
-// Secondly, the function wants a list of boundaries where we have imposed
-// Neumann value, and the corresponding Neumann values. This information is
+// Secondly, the function wants a list of boundary indicators for those
+// boundaries where we have imposed Neumann values of the kind
+// $\partial_n u(\mathbf x) = h(\mathbf x)$, along with a function $h(\mathbf x)$
+// for each such boundary. This information is
// represented by an object of type <code>FunctionMap::type</code> that is
-// essentially a map from boundary indicators to function objects describing
-// Neumann boundary values (in the present example program, we do not use
+// a typedef to a map from boundary indicators to function objects describing
+// the Neumann boundary values. In the present example program, we do not use
// Neumann boundary values, so this map is empty, and in fact constructed
// using the default constructor of the map in the place where the function
-// call expects the respective function argument).
+// call expects the respective function argument.
//
// The output, as mentioned is a vector of values for all cells. While it may
-// make sense to compute the *value* of a degree of freedom very accurately,
-// it is usually not helpful to compute the *error indicator* corresponding to
-// a cell particularly accurately. We therefore typically use a vector of
-// floats instead of a vector of doubles to represent error indicators.
+// make sense to compute the <b>value</b> of a solution degree of freedom
+// very accurately, it is usually not necessary to compute the <b>error indicator</b>
+// corresponding to the solution on a cell particularly accurately. We therefore
+// typically use a vector of floats instead of a vector of doubles to represent
+// error indicators.
template <int dim>
void Step6<dim>::refine_grid ()
{
# Set the name of the project and target:
SET(TARGET "step-7")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
$x_1=(-\frac 12,\frac 12)$,
$x_2=(-\frac 12,-\frac 12)$, and
$x_3=(\frac 12,-\frac 12)$.
-The half width is set to $\sigma=\frac 13$.
+The half width is set to $\sigma=\frac {1}{8}$.
We further choose $\Gamma_1=\Gamma \cap\{\{x=1\} \cup \{y=1\}\}$, and there
set $g_1$ such that it resembles the exact values of $u$. Likewise, we choose
The program generates two kinds of output. The first are the output
-files <code>solution-adaptive-q1.gmv</code>,
-<code>solution-global-q1.gmv</code>, and
-<code>solution-global-q2.gmv</code>. We show the latter in a 3d view
+files <code>solution-adaptive-q1.vtk</code>,
+<code>solution-global-q1.vtk</code>, and
+<code>solution-global-q2.vtk</code>. We show the latter in a 3d view
here:
@code
examples/\step-7> make run
-============================ Running \step-7
Solving with Q1 elements, adaptive refinement
=============================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 9
+ Number of active cells: 64
+ Number of degrees of freedom: 81
Cycle 1:
- Number of active cells: 13
- Number of degrees of freedom: 22
+ Number of active cells: 124
+ Number of degrees of freedom: 157
Cycle 2:
- Number of active cells: 31
- Number of degrees of freedom: 46
+ Number of active cells: 280
+ Number of degrees of freedom: 341
Cycle 3:
- Number of active cells: 64
- Number of degrees of freedom: 87
+ Number of active cells: 577
+ Number of degrees of freedom: 690
Cycle 4:
- Number of active cells: 127
- Number of degrees of freedom: 160
+ Number of active cells: 1099
+ Number of degrees of freedom: 1264
Cycle 5:
- Number of active cells: 244
- Number of degrees of freedom: 297
+ Number of active cells: 2191
+ Number of degrees of freedom: 2452
Cycle 6:
- Number of active cells: 466
- Number of degrees of freedom: 543
-
-cycle cells dofs L2 H1 Linfty
- 0 4 9 1.198e+00 2.732e+00 1.383e+00
- 1 13 22 8.795e-02 1.193e+00 1.816e-01
- 2 31 46 8.147e-02 1.167e+00 1.654e-01
- 3 64 87 7.702e-02 1.077e+00 1.310e-01
- 4 127 160 4.643e-02 7.988e-01 6.745e-02
- 5 244 297 2.470e-02 5.568e-01 3.668e-02
- 6 466 543 1.622e-02 4.107e-01 2.966e-02
+ Number of active cells: 4165
+ Number of degrees of freedom: 4510
+Cycle 7:
+ Number of active cells: 7915
+ Number of degrees of freedom: 8440
+Cycle 8:
+ Number of active cells: 15196
+ Number of degrees of freedom: 15912
+
+cycle cells dofs L2 H1 Linfty
+ 0 64 81 1.576e-01 1.418e+00 2.707e-01
+ 1 124 157 4.285e-02 1.285e+00 1.469e-01
+ 2 280 341 1.593e-02 7.909e-01 8.034e-02
+ 3 577 690 9.359e-03 5.096e-01 2.784e-02
+ 4 1099 1264 2.865e-03 3.038e-01 9.822e-03
+ 5 2191 2452 1.480e-03 2.106e-01 5.679e-03
+ 6 4165 4510 6.907e-04 1.462e-01 2.338e-03
+ 7 7915 8440 4.743e-04 1.055e-01 1.442e-03
+ 8 15196 15912 1.920e-04 7.468e-02 7.259e-04
Solving with Q1 elements, global refinement
===========================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 9
-Cycle 1:
- Number of active cells: 16
- Number of degrees of freedom: 25
-Cycle 2:
Number of active cells: 64
Number of degrees of freedom: 81
-Cycle 3:
+Cycle 1:
Number of active cells: 256
Number of degrees of freedom: 289
-Cycle 4:
+Cycle 2:
Number of active cells: 1024
Number of degrees of freedom: 1089
-Cycle 5:
+Cycle 3:
Number of active cells: 4096
Number of degrees of freedom: 4225
-Cycle 6:
+Cycle 4:
Number of active cells: 16384
Number of degrees of freedom: 16641
-cycle cells dofs L2 H1 Linfty
- 0 4 9 1.198e+00 2.732e+00 1.383e+00
- 1 16 25 8.281e-02 1.190e+00 1.808e-01
- 2 64 81 8.142e-02 1.129e+00 1.294e-01
- 3 256 289 2.113e-02 5.828e-01 4.917e-02
- 4 1024 1089 5.319e-03 2.934e-01 1.359e-02
- 5 4096 4225 1.332e-03 1.469e-01 3.482e-03
- 6 16384 16641 3.332e-04 7.350e-02 8.758e-04
-
-n cells H1 L2
- 0 4 2.732e+00 - 1.198e+00 - -
- 1 16 1.190e+00 1.20 8.281e-02 14.47 3.86
- 2 64 1.129e+00 0.08 8.142e-02 1.02 0.02
- 3 256 5.828e-01 0.95 2.113e-02 3.85 1.95
- 4 1024 2.934e-01 0.99 5.319e-03 3.97 1.99
- 5 4096 1.469e-01 1.00 1.332e-03 3.99 2.00
- 6 16384 7.350e-02 1.00 3.332e-04 4.00 2.00
+cycle cells dofs L2 H1 Linfty
+ 0 64 81 1.576e-01 1.418e+00 2.707e-01
+ 1 256 289 4.280e-02 1.285e+00 1.444e-01
+ 2 1024 1089 1.352e-02 7.556e-01 7.772e-02
+ 3 4096 4225 3.423e-03 3.822e-01 2.332e-02
+ 4 16384 16641 8.586e-04 1.917e-01 6.097e-03
+
+n cells H1 L2
+0 64 1.418e+00 - - 1.576e-01 - -
+1 256 1.285e+00 1.10 0.14 4.280e-02 3.68 1.88
+2 1024 7.556e-01 1.70 0.77 1.352e-02 3.17 1.66
+3 4096 3.822e-01 1.98 0.98 3.423e-03 3.95 1.98
+4 16384 1.917e-01 1.99 1.00 8.586e-04 3.99 2.00
Solving with Q2 elements, global refinement
===========================================
Cycle 0:
- Number of active cells: 4
- Number of degrees of freedom: 25
-Cycle 1:
- Number of active cells: 16
- Number of degrees of freedom: 81
-Cycle 2:
Number of active cells: 64
Number of degrees of freedom: 289
-Cycle 3:
+Cycle 1:
Number of active cells: 256
Number of degrees of freedom: 1089
-Cycle 4:
+Cycle 2:
Number of active cells: 1024
Number of degrees of freedom: 4225
-Cycle 5:
+Cycle 3:
Number of active cells: 4096
Number of degrees of freedom: 16641
-Cycle 6:
+Cycle 4:
Number of active cells: 16384
Number of degrees of freedom: 66049
-cycle cells dofs L2 H1 Linfty
- 0 4 25 1.433e+00 2.445e+00 1.286e+00
- 1 16 81 7.912e-02 1.168e+00 1.728e-01
- 2 64 289 7.755e-03 2.511e-01 1.991e-02
- 3 256 1089 9.969e-04 6.235e-02 2.764e-03
- 4 1024 4225 1.265e-04 1.571e-02 3.527e-04
- 5 4096 16641 1.587e-05 3.937e-03 4.343e-05
- 6 16384 66049 1.986e-06 9.847e-04 5.402e-06
-
-n cells H1 L2
- 0 4 2.445e+00 - 1.433e+00 - -
- 1 16 1.168e+00 1.07 7.912e-02 18.11 4.18
- 2 64 2.511e-01 2.22 7.755e-03 10.20 3.35
- 3 256 6.235e-02 2.01 9.969e-04 7.78 2.96
- 4 1024 1.571e-02 1.99 1.265e-04 7.88 2.98
- 5 4096 3.937e-03 2.00 1.587e-05 7.97 2.99
- 6 16384 9.847e-04 2.00 1.986e-06 7.99 3.00
+cycle cells dofs L2 H1 Linfty
+ 0 64 289 1.606e-01 1.278e+00 3.029e-01
+ 1 256 1089 7.638e-03 5.248e-01 4.816e-02
+ 2 1024 4225 8.601e-04 1.086e-01 4.827e-03
+ 3 4096 16641 1.107e-04 2.756e-02 7.802e-04
+ 4 16384 66049 1.393e-05 6.915e-03 9.971e-05
+
+n cells H1 L2
+0 64 1.278e+00 - - 1.606e-01 - -
+1 256 5.248e-01 2.43 1.28 7.638e-03 21.03 4.39
+2 1024 1.086e-01 4.83 2.27 8.601e-04 8.88 3.15
+3 4096 2.756e-02 3.94 1.98 1.107e-04 7.77 2.96
+4 16384 6.915e-03 3.99 1.99 1.393e-05 7.94 2.99
+
+Solving with Q2 elements, adaptive refinement
+===========================================
+
+Cycle 0:
+ Number of active cells: 64
+ Number of degrees of freedom: 289
+Cycle 1:
+ Number of active cells: 124
+ Number of degrees of freedom: 577
+Cycle 2:
+ Number of active cells: 289
+ Number of degrees of freedom: 1353
+Cycle 3:
+ Number of active cells: 547
+ Number of degrees of freedom: 2531
+Cycle 4:
+ Number of active cells: 1057
+ Number of degrees of freedom: 4919
+Cycle 5:
+ Number of active cells: 2059
+ Number of degrees of freedom: 9223
+Cycle 6:
+ Number of active cells: 3913
+ Number of degrees of freedom: 17887
+Cycle 7:
+ Number of active cells: 7441
+ Number of degrees of freedom: 33807
+Cycle 8:
+ Number of active cells: 14212
+ Number of degrees of freedom: 64731
+
+cycle cells dofs L2 H1 Linfty
+ 0 64 289 1.606e-01 1.278e+00 3.029e-01
+ 1 124 577 7.891e-03 5.256e-01 4.852e-02
+ 2 289 1353 1.070e-03 1.155e-01 4.868e-03
+ 3 547 2531 5.962e-04 5.101e-02 1.876e-03
+ 4 1057 4919 1.977e-04 3.094e-02 7.923e-04
+ 5 2059 9223 7.738e-05 1.974e-02 7.270e-04
+ 6 3913 17887 2.925e-05 8.772e-03 1.463e-04
+ 7 7441 33807 1.024e-05 4.121e-03 8.567e-05
+ 8 14212 64731 3.761e-06 2.108e-03 2.167e-05
@endcode
-Finally, the program generated various LaTeX tables. We show here
-the convergence table of the Q2 element with global refinement, after
-converting the format to HTML:
-
-
-
-<TABLE CELLPADDING=3 BORDER="1" ALIGN="CENTER">
-<TR><TD ALIGN="CENTER" COLSPAN=2>
-n cells</TD>
-<TD ALIGN="CENTER" COLSPAN=2><I>H</I><SUP>1</SUP>-error</TD>
-<TD ALIGN="CENTER" COLSPAN=3><I>L</I><SUP>2</SUP>-error</TD>
-</TR>
-<TR><TD ALIGN="CENTER">0</TD>
-<TD ALIGN="RIGHT">4</TD>
-<TD ALIGN="CENTER">2.445e+00</TD>
-<TD ALIGN="CENTER">-</TD>
-<TD ALIGN="CENTER">1.433e+00</TD>
-<TD ALIGN="CENTER">-</TD>
-<TD ALIGN="CENTER">-</TD>
-</TR>
-<TR><TD ALIGN="CENTER">1</TD>
-<TD ALIGN="RIGHT">16</TD>
-<TD ALIGN="CENTER">1.168e+00</TD>
-<TD ALIGN="CENTER">1.07</TD>
-<TD ALIGN="CENTER">7.912e-02</TD>
-<TD ALIGN="CENTER">18.11</TD>
-<TD ALIGN="CENTER">4.18</TD>
-</TR>
-<TR><TD ALIGN="CENTER">2</TD>
-<TD ALIGN="RIGHT">64</TD>
-<TD ALIGN="CENTER">2.511e-01</TD>
-<TD ALIGN="CENTER">2.22</TD>
-<TD ALIGN="CENTER">7.755e-03</TD>
-<TD ALIGN="CENTER">10.20</TD>
-<TD ALIGN="CENTER">3.35</TD>
-</TR>
-<TR><TD ALIGN="CENTER">3</TD>
-<TD ALIGN="RIGHT">256</TD>
-<TD ALIGN="CENTER">6.235e-02</TD>
-<TD ALIGN="CENTER">2.01</TD>
-<TD ALIGN="CENTER">9.969e-04</TD>
-<TD ALIGN="CENTER">7.78</TD>
-<TD ALIGN="CENTER">2.96</TD>
-</TR>
-<TR><TD ALIGN="CENTER">4</TD>
-<TD ALIGN="RIGHT">1024</TD>
-<TD ALIGN="CENTER">1.571e-02</TD>
-<TD ALIGN="CENTER">1.99</TD>
-<TD ALIGN="CENTER">1.265e-04</TD>
-<TD ALIGN="CENTER">7.88</TD>
-<TD ALIGN="CENTER">2.98</TD>
-</TR>
-<TR><TD ALIGN="CENTER">5</TD>
-<TD ALIGN="RIGHT">4096</TD>
-<TD ALIGN="CENTER">3.937e-03</TD>
-<TD ALIGN="CENTER">2.00</TD>
-<TD ALIGN="CENTER">1.587e-05</TD>
-<TD ALIGN="CENTER">7.97</TD>
-<TD ALIGN="CENTER">2.99</TD>
-</TR>
-<TR><TD ALIGN="CENTER">6</TD>
-<TD ALIGN="RIGHT">16384</TD>
-<TD ALIGN="CENTER">9.847e-04</TD>
-<TD ALIGN="CENTER">2.00</TD>
-<TD ALIGN="CENTER">1.986e-06</TD>
-<TD ALIGN="CENTER">7.99</TD>
-<TD ALIGN="CENTER">3.00</TD>
-</TR>
-</TABLE>
+Finally, the program also generated LaTeX versions of the tables (not shown
+here).
+
+
+<h3> Possible extensions </h3>
+
+<h4> Higher Order Elements </h4>
+
+Go ahead and run the program with higher order elements (Q3, Q4, ...). You
+will notice that assertions in several parts of the code will trigger (for
+example in the generation of the filename for the data output). After fixing
+these you will not see the correct convergence orders that the theory
+predicts. This is because the orders for the quadrature formulas are
+hard-coded in this program and this order is not enough for higher order
+discretizations. What is a good way to pick the orders dynamically?
+
+<h4> Convergence Comparison </h4>
+
+Is Q1 or Q2 better? What about adaptive versus global refinement? A (somewhat
+unfair but typical) metric to compare them, is to look at the error as a
+function of the number of unknowns.
+
+To see this, create a plot in log-log style with the number of unknowns on the
+x axis and the L2 error on the y axis. You can add reference lines for
+$h^2=N^{-1}$ and $h^3=N^{-3/2}$ and check that global and adaptive refinement
+follow those.
+
+Note that changing the half width of the peaks influences if adaptive or
+global refinement is more efficient (if the solution is very smooth, local
+refinement does not give any advantage over global refinement). Verify this.
+Finally, a more fair comparison would be to plot runtime (switch to release
+mode first!) instead of number of unknowns on the x axis. Picking a better
+linear solver might be appropriate though.
// concrete instantiation by substituting <code>dim</code> with a concrete
// value:
template <int dim>
- const double SolutionBase<dim>::width = 1./3.;
+ const double SolutionBase<dim>::width = 1./8.;
// <code>run()</code> function further below. (The default value of
// boundary indicators is <code>0</code>, so faces can only have an
// indicator equal to <code>1</code> if we have explicitly set it.)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary()
+ for (unsigned int face_number=0; face_number<GeometryInfo<dim>::faces_per_cell; ++face_number)
+ if (cell->face(face_number)->at_boundary()
&&
- (cell->face(face)->boundary_indicator() == 1))
+ (cell->face(face_number)->boundary_indicator() == 1))
{
// If we came into here, then we have found an external face
// belonging to Gamma2. Next, we have to compute the values of
// need for the computation of the contour integral. This is
// done using the <code>reinit</code> function which we already
// know from the FEValue class:
- fe_face_values.reinit (cell, face);
+ fe_face_values.reinit (cell, face_number);
// And we can then perform the integration by using a loop over
// all quadrature points.
// since we have Neumann boundary conditions on part of the boundaries, but
// since we don't have a function here that describes the Neumann values (we
// only construct these values from the exact solution when assembling the
- // matrix), we omit this detail even though they would not be hard to add.
+ // matrix), we omit this detail even though doing this in a strictly correct
+ // way would not be hard to add.
//
// At the end of the switch, we have a default case that looks slightly
// strange: an <code>Assert</code> statement with a <code>false</code>
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- typename FunctionMap<dim>::type neumann_boundary;
KellyErrorEstimator<dim>::estimate (dof_handler,
QGauss<dim-1>(3),
- neumann_boundary,
+ typename FunctionMap<dim>::type(),
solution,
estimated_error_per_cell);
template <int dim>
void HelmholtzProblem<dim>::run ()
{
- for (unsigned int cycle=0; cycle<7; ++cycle)
+ const unsigned int n_cycles = (refinement_mode==global_refinement)?5:9;
+ for (unsigned int cycle=0; cycle<n_cycles; ++cycle)
{
if (cycle == 0)
{
GridGenerator::hyper_cube (triangulation, -1, 1);
- triangulation.refine_global (1);
+ triangulation.refine_global (3);
typename Triangulation<dim>::cell_iterator
cell = triangulation.begin (),
endc = triangulation.end();
for (; cell!=endc; ++cell)
- for (unsigned int face=0;
- face<GeometryInfo<dim>::faces_per_cell;
- ++face)
- if ((std::fabs(cell->face(face)->center()(0) - (-1)) < 1e-12)
+ for (unsigned int face_number=0;
+ face_number<GeometryInfo<dim>::faces_per_cell;
+ ++face_number)
+ if ((std::fabs(cell->face(face_number)->center()(0) - (-1)) < 1e-12)
||
- (std::fabs(cell->face(face)->center()(1) - (-1)) < 1e-12))
- cell->face(face)->set_boundary_indicator (1);
+ (std::fabs(cell->face(face_number)->center()(1) - (-1)) < 1e-12))
+ cell->face(face_number)->set_boundary_indicator (1);
}
else
refine_grid ();
// After the last iteration we output the solution on the finest
// grid. This is done using the following sequence of statements which we
// have already discussed in previous examples. The first step is to
- // generate a suitable filename (called <code>gmv_filename</code> here,
- // since we want to output data in GMV format; we add the prefix to
+ // generate a suitable filename (called <code>vtk_filename</code> here,
+ // since we want to output data in VTK format; we add the prefix to
// distinguish the filename from that used for other output files further
// down below). Here, we augment the name by the mesh refinement
// algorithm, and as above we make sure that we abort the program if
// another refinement method is added and not handled by the following
// switch statement:
- std::string gmv_filename;
+ std::string vtk_filename;
switch (refinement_mode)
{
case global_refinement:
- gmv_filename = "solution-global";
+ vtk_filename = "solution-global";
break;
case adaptive_refinement:
- gmv_filename = "solution-adaptive";
+ vtk_filename = "solution-adaptive";
break;
default:
Assert (false, ExcNotImplemented());
switch (fe->degree)
{
case 1:
- gmv_filename += "-q1";
+ vtk_filename += "-q1";
break;
case 2:
- gmv_filename += "-q2";
+ vtk_filename += "-q2";
break;
default:
}
// Once we have the base name for the output file, we add an extension
- // appropriate for GMV output, open a file, and add the solution vector to
+ // appropriate for VTK output, open a file, and add the solution vector to
// the object that will do the actual output:
- gmv_filename += ".gmv";
- std::ofstream output (gmv_filename.c_str());
+ vtk_filename += ".vtk";
+ std::ofstream output (vtk_filename.c_str());
DataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
// way as above.
//
// With the intermediate format so generated, we can then actually write
- // the graphical output in GMV format:
+ // the graphical output:
data_out.build_patches (fe->degree);
- data_out.write_gmv (output);
+ data_out.write_vtk (output);
// @sect5{Output of convergence tables}
convergence_table
.evaluate_convergence_rates("L2", ConvergenceTable::reduction_rate_log2);
convergence_table
+ .evaluate_convergence_rates("H1", ConvergenceTable::reduction_rate);
+ convergence_table
.evaluate_convergence_rates("H1", ConvergenceTable::reduction_rate_log2);
// Each of these function calls produces an additional column that is
// merged with the original column (in our example the `L2' and the
std::cout << std::endl;
}
+ {
+ std::cout << "Solving with Q2 elements, adaptive refinement" << std::endl
+ << "===========================================" << std::endl
+ << std::endl;
+
+ FE_Q<dim> fe(2);
+ HelmholtzProblem<dim>
+ helmholtz_problem_2d (fe, HelmholtzProblem<dim>::adaptive_refinement);
+
+ helmholtz_problem_2d.run ();
+ std::cout << std::endl;
+ }
}
catch (std::exception &exc)
{
# Set the name of the project and target:
SET(TARGET "step-8")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
are in assembling matrix and right hand side, but these are easily
understood as well.
-In the example, we will want to solve the elastic equations. They are
+@dealiiVideoLecture{19}
+
+In this tutorial program we will want to solve the elastic equations. They are
an extension to Laplace's equation with a vector-valued solution that
describes the displacement in each space direction of a rigid body
which is subject to a force. Of course, the force is also
{
Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
- typename FunctionMap<dim>::type neumann_boundary;
KellyErrorEstimator<dim>::estimate (dof_handler,
QGauss<dim-1>(2),
- neumann_boundary,
+ typename FunctionMap<dim>::type(),
solution,
estimated_error_per_cell);
# Set the name of the project and target:
SET(TARGET "step-9")
-# Declare all source files the target consists of:
+# Declare all source files the target consists of. Here, this is only
+# the one step-X.cc file, but as you expand your project you may wish
+# to add other source files as well. If your project becomes much larger,
+# you may want to either replace the following statement by something like
+# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc")
+# FILE(GLOB_RECURSE TARGET_INC "include/*.h")
+# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC})
+# or switch altogether to the large project CMakeLists.txt file discussed
+# in the "CMake in user projects" page accessible from the "User info"
+# page of the documentation.
SET(TARGET_SRC
${TARGET}.cc
- # You can specify additional files here!
)
# Usually, you will not need to modify anything beyond this point...
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
-FIND_PACKAGE(deal.II 8.0 QUIET
+FIND_PACKAGE(deal.II 8.2 QUIET
HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
)
IF(NOT ${deal.II_FOUND})
MESSAGE(FATAL_ERROR "\n"
- "*** Could not locate deal.II. ***\n\n"
+ "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
"You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n"
"or set an environment variable \"DEAL_II_DIR\" that contains this path."
)
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: named_data.h 30036 2013-07-18 16:55:32Z maier $
+//
+// Copyright (C) 2000 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__any_data_h
+#define __deal2__any_data_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+#include <deal.II/base/named_data.h>
+
+#include <boost/any.hpp>
+#include <vector>
+#include <algorithm>
+#include <typeinfo>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * Store any amount of any type of data accessible by an identifier string.
+ *
+ * @todo Deprecate access by index after NamedData has been deprecated
+ * for long enough, then change to a map.
+ */
+class AnyData :
+ public Subscriptor
+{
+public:
+ /// Default constructor for empty object
+ AnyData();
+
+ /// Number of stored data objects.
+ unsigned int size() const;
+
+ /// Add a new data object
+ template <typename type>
+ void add(type entry, const std::string &name);
+
+ /**
+ * @brief Merge the data of another NamedData to the end of this object.
+ */
+ void merge(const AnyData &other);
+
+ /**
+ * @brief Access to stored data object by name.
+ *
+ * Find the object with given name, try to convert it to
+ * <tt>type</tt> and return it. This function throws an exception
+ * if either the name does not exist or if the conversion
+ * fails. If such an exception is not desired, use try_read()
+ * instead.
+ */
+ template <typename type>
+ type entry (const std::string &name);
+
+ /**
+ * @brief Read-only access to stored data object by name.
+ *
+ * Find the object with given name, try to convert it to
+ * <tt>type</tt> and return it. This function throws an exception
+ * if either the name does not exist or if the conversion
+ * fails. If such an exception is not desired, use try_read()
+ * instead.
+ */
+ template <typename type>
+ const type entry (const std::string &name) const;
+
+ /**
+ * @brief Dedicated read only access by name.
+ *
+ * For a constant object, this function equals entry(). For a
+ * non-const object, it forces read only access to the data. In
+ * particular, it throws an exception if the object is not found
+ * or cannot be converted to type. If such an exception is not
+ * desired, use try_read() instead.
+ *
+ * @warning Do not use this function for stored objects which are
+ * pointers. Use read_ptr() instead!
+ */
+ template <typename type>
+ const type read (const std::string &name) const;
+
+ /**
+ * @brief Dedicated read only access by name for pointer data.
+ *
+ * If the stored data object is a pointer to a constant object, the logic
+ * of access becomes fairly complicated. Namely, the standard read
+ * function may fail, depending on whether it was a const pointer
+ * or a regular pointer. This function fixes the logic and
+ * ascertains that the object does not become mutable by accident.
+ */
+ template <typename type>
+ const type *read_ptr (const std::string &name) const;
+
+ /**
+ * Perform the same action as read_ptr(), but do not throw an
+ * exception if the pointer does not exist. Return a null pointer
+ * instead.
+ */
+ template <typename type>
+ const type *try_read_ptr (const std::string &name) const;
+
+ /**
+ * @brief Dedicated read only access by name without exceptions.
+ *
+ * This function tries to find the name in the list and return a
+ * pointer to the associated object. If either the name is not
+ * found or the object cannot be converted to the return type, a
+ * null pointer is returned.
+ */
+ template <typename type>
+ const type *try_read (const std::string &name) const;
+
+ /**
+ * Access to stored data object by index.
+ */
+ template <typename type>
+ type entry (const unsigned int i);
+
+ /// Read-only access to stored data object by index.
+ template <typename type>
+ const type entry (const unsigned int i) const;
+
+ /// Dedicated read only access.
+ template <typename type>
+ const type read (const unsigned int i) const;
+
+ /// Dedicated read only access to pointer object.
+ template <typename type>
+ const type *read_ptr (const unsigned int i) const;
+
+ /// Dedicated read only access to pointer object without exception.
+ template <typename type>
+ const type *try_read_ptr (const unsigned int i) const;
+
+ /// Dedicated read only access without exception.
+ template <typename type>
+ const type *try_read (const unsigned int i) const;
+
+ /// Name of object at index.
+ const std::string &name(const unsigned int i) const;
+
+ /**
+ * @brief Find index of a named object
+ *
+ * Try to find the objecty and return its index in the list. Throw
+ * an exception if the object has not been found.
+ */
+ unsigned int find(const std::string &name) const;
+
+ /**
+ * @brief Try to find index of a named object
+ *
+ * Try to find the objecty and return its index in the
+ * list. returns numbers::invalid_unsigned_int if the name was not
+ * found.
+ */
+ unsigned int try_find(const std::string &name) const;
+
+ /// Find out if object is of a certain type
+ template <typename type>
+ bool is_type(const unsigned int i) const;
+
+ /// List the contents to a stream
+ template <class STREAM>
+ void list (STREAM& os) const;
+
+ /// Conversion from old NamedData
+ template <typename type>
+ AnyData(const NamedData<type> &);
+
+ /// An entry with this name does not exist in the AnyData object.
+ DeclException1(ExcNameNotFound, std::string &,
+ << "No entry with the name " << arg1 << " exists");
+
+ /// The requested type and the stored type are different
+ DeclException2(ExcTypeMismatch,
+ char *, char *,
+ << "The requested type " << arg1
+ << " and the stored type " << arg2
+ << " must coincide");
+
+ /**
+ * Exception indicating that a function expected a vector to have a
+ * certain name, but NamedData had a different name in that
+ * position.
+ */
+ DeclException2(ExcNameMismatch, int, std::string,
+ << "Name at position " << arg1 << " is not equal to " << arg2);
+private:
+ /// The stored data
+ std::vector<boost::any> data;
+ /// The names of the stored data
+ std::vector<std::string> names;
+};
+
+
+inline
+AnyData::AnyData()
+{}
+
+
+template <typename type>
+inline
+AnyData::AnyData(const NamedData<type> &other)
+{
+ for (unsigned int i=0; i<other.size(); ++i)
+ add(other(i), other.name(i));
+}
+
+
+unsigned int
+inline
+AnyData::size () const
+{
+ AssertDimension(data.size(), names.size());
+ return data.size();
+}
+
+
+template <typename type>
+inline
+type
+AnyData::entry (const unsigned int i)
+{
+ AssertIndexRange(i, size());
+ type *p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::entry (const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type *p = boost::any_cast<type>(&data[i]);
+ if (p==0 )
+ p = boost::any_cast<const type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::read(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type *p = boost::any_cast<type>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::read_ptr(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type *const *p = boost::any_cast<type *>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type *>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type *).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::try_read_ptr(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type *const *p = boost::any_cast<type *>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type *>(&data[i]);
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::try_read(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ const type *p = boost::any_cast<type>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type>(&data[i]);
+ return p;
+}
+
+
+inline
+const std::string &
+AnyData::name(const unsigned int i) const
+{
+ AssertIndexRange(i, size());
+ return names[i];
+}
+
+
+inline
+unsigned int
+AnyData::try_find(const std::string &n) const
+{
+ std::vector<std::string>::const_iterator it =
+ std::find(names.begin(), names.end(), n);
+
+ if (it == names.end())
+ return numbers::invalid_unsigned_int;
+
+ return it - names.begin();
+}
+
+
+inline
+unsigned int
+AnyData::find(const std::string &n) const
+{
+ const unsigned int i = try_find(n);
+ Assert(i != numbers::invalid_unsigned_int, ExcNameNotFound(n));
+
+ return i;
+}
+
+
+template <typename type>
+inline
+bool
+AnyData::is_type(const unsigned int i) const
+{
+ return data[i].type() == typeid(type);
+}
+
+
+template <typename type>
+inline
+type
+AnyData::entry (const std::string &n)
+{
+ const unsigned int i = find(n);
+ type *p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::entry (const std::string &n) const
+{
+ const unsigned int i = find(n);
+ const type *p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type
+AnyData::read(const std::string &n) const
+{
+ const unsigned int i = find(n);
+ const type *p = boost::any_cast<type>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::read_ptr(const std::string &n) const
+{
+ const unsigned int i = find(n);
+ const type *const *p = boost::any_cast<type *>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type *>(&data[i]);
+ Assert(p != 0,
+ ExcTypeMismatch(typeid(type).name(),data[i].type().name()));
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::try_read_ptr(const std::string &n) const
+{
+ const unsigned int i = try_find(n);
+ if (i == numbers::invalid_unsigned_int)
+ return 0;
+
+ const type *const *p = boost::any_cast<type *>(&data[i]);
+ if (p==0)
+ p = boost::any_cast<const type *>(&data[i]);
+ return *p;
+}
+
+
+template <typename type>
+inline
+const type *
+AnyData::try_read(const std::string &n) const
+{
+ // Try to find name
+ std::vector<std::string>::const_iterator it =
+ std::find(names.begin(), names.end(), n);
+ // Return null pointer if not found
+ if (it == names.end())
+ return 0;
+
+ // Compute index and return casted pointer
+ unsigned int i=it-names.begin();
+ const type *p = boost::any_cast<type>(&data[i]);
+ return p;
+}
+
+
+template <typename type>
+inline
+void
+AnyData::add(type ent, const std::string &n)
+{
+ boost::any e = ent;
+ data.push_back(e);
+ names.push_back(n);
+}
+
+
+inline
+void
+AnyData::merge(const AnyData &other)
+{
+ for (unsigned int i=0; i<other.size(); ++i)
+ {
+ names.push_back(other.names[i]);
+ data.push_back(other.data[i]);
+ }
+}
+
+
+template <class STREAM>
+inline
+void AnyData::list(STREAM& os) const
+{
+ for (unsigned int i=0;i<names.size();++i)
+ {
+ os << i
+ << '\t' << names[i]
+ << '\t' << data[i].type().name()
+ << std::endl;
+ }
+}
+
+
+//----------------------------------------------------------------------//
+
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
+
+
+
+
+
+
+
+
+
+
#include <deal.II/base/smartpointer.h>
#include <deal.II/lac/solver_control.h>
#include <deal.II/algorithms/operator.h>
+#include <deal.II/algorithms/any_data.h>
DEAL_II_NAMESPACE_OPEN
* #inverse_derivative. It is up to this object to implement
* reassembling accordingly.
*
- * <h3>Contents of the NamedData objects</h3>
+ * <h3>Contents of the AnyData objects</h3>
*
* The only value used by the Newton method is the first vector in the
* parameter <tt>out</tt> of operator()(). It serves as the start
Newton (Operator<VECTOR> &residual, Operator<VECTOR> &inverse_derivative);
/**
- * Declare the parameters
- * applicable to Newton's method.
+ * Declare the parameters applicable to Newton's method.
*/
- void declare_parameters (ParameterHandler ¶m);
+ static void declare_parameters (ParameterHandler ¶m);
/**
- * Read the parameters.
+ * Read the parameters in the ParameterHandler.
*/
- void initialize (ParameterHandler ¶m);
+ void parse_parameters (ParameterHandler ¶m);
+
+ /**
+ * @deprecated Use parse_parameters().
+ */
+ void initialize (ParameterHandler ¶m) DEAL_II_DEPRECATED;
/**
* Initialize the pointer
* down to the objects
* #residual and #inverse_derivative.
*/
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated Use the function using AnyData
+ */
virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
virtual void notify(const Event &);
template <class VECTOR>
void
- Newton<VECTOR>::initialize (ParameterHandler ¶m)
+ Newton<VECTOR>::parse_parameters (ParameterHandler ¶m)
{
param.enter_subsection("Newton");
control.parse_parameters (param);
param.leave_subsection ();
}
+ template <class VECTOR>
+ void
+ Newton<VECTOR>::initialize (ParameterHandler ¶m)
+ {
+ parse_parameters(param);
+ }
+
template <class VECTOR>
void
Newton<VECTOR>::initialize (OutputOperator<VECTOR> &output)
inverse_derivative->notify(e);
}
-
+
template <class VECTOR>
double
Newton<VECTOR>::threshold(const double thr)
assemble_threshold = thr;
return t;
}
-
-
+
+
template <class VECTOR>
void
Newton<VECTOR>::operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in)
+ {
+ Operator<VECTOR>::operator() (out, in);
+ }
+
+ template <class VECTOR>
+ void
+ Newton<VECTOR>::operator() (AnyData &out, const AnyData &in)
{
Assert (out.size() == 1, ExcNotImplemented());
deallog.push ("Newton");
- VECTOR &u = *out(0);
+ VECTOR &u = *out.entry<VECTOR *>(0);
if (debug>2)
deallog << "u: " << u.l2_norm() << std::endl;
typename VectorMemory<VECTOR>::Pointer res(mem);
res->reinit(u);
- NamedData<VECTOR *> src1;
- NamedData<VECTOR *> src2;
- VECTOR *p = &u;
- src1.add(p, "Newton iterate");
+ AnyData src1;
+ AnyData src2;
+ src1.add<const VECTOR *>(&u, "Newton iterate");
src1.merge(in);
- p = res;
- src2.add(p, "Newton residual");
+ src2.add<const VECTOR *>(res, "Newton residual");
src2.merge(src1);
- NamedData<VECTOR *> out1;
- out1.add(p, "Residual");
- p = Du;
- NamedData<VECTOR *> out2;
- out2.add(p, "Update");
+ AnyData out1;
+ out1.add<VECTOR *>(res, "Residual");
+ AnyData out2;
+ out2.add<VECTOR *>(Du, "Update");
unsigned int step = 0;
// fill res with (f(u), v)
double resnorm = res->l2_norm();
double old_residual = resnorm / assemble_threshold + 1;
+ if (debug_vectors)
+ {
+ NamedData<VECTOR *> out;
+ VECTOR *p = &u;
+ out.add(p, "solution");
+ p = Du;
+ out.add(p, "update");
+ p = res;
+ out.add(p, "residual");
+ *data_out << step;
+ *data_out << out;
+ }
+
while (control.check(step++, resnorm) == SolverControl::iterate)
{
// assemble (Df(u), v)
#define __deal2__operator_h
#include <deal.II/base/config.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/named_data.h>
#include <deal.II/base/event.h>
namespace Algorithms
{
/**
+ * @todo Update this documentation and the one of Operator
+ *
* The abstract base class of all algorithms in this library. An
* operator is an object with an operator(), which transforms a set
* of named vectors into another set of named vectors.
* the innermost method in such a nested system will have to compute a
* residual using values from all outer iterations. Since the depth
* and order of such a nesting is hardly predictable when designing a
- * general tool, we use NamedData to access these vectors. Typically,
+ * general tool, we use AnyData to access these vectors. Typically,
* the first vector in <tt>out</tt> contains the start vector when
* operator()() is called, and the solution when the function
* returns. The object <tt>in</tt> is providing additional information
* and forwarded to the inner Operator objects of the nested
* iteration.
*
- * @author Guido Kanschat, 2010
+ * @author Guido Kanschat
+ * @date 2014
*/
- template <class VECTOR>
- class Operator : public Subscriptor
+ class OperatorBase : public Subscriptor
{
public:
/**
* The virtual destructor.
*/
- ~Operator();
+ ~OperatorBase();
/**
* The actual operation, which
* is implemented in a derived class.
*/
- virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in) = 0;
+ virtual void operator() (AnyData &out, const AnyData &in) = 0;
/**
* Register an event triggered
void clear_events();
protected:
/**
- * Accumulate reasons for
- * reassembling here. If any of
+ * Accumulate events here. If any of
* those is set, the function
* solve() of a terminal
* application must take care
* of reassembling the matrix.
*/
Event notifications;
+
+ };
+
+ /**
+ * @deprecated This class has been replaced by OperatorBase.
+ *
+ * The abstract base class of all algorithms in this library. An
+ * operator is an object with an operator(), which transforms a set
+ * of named vectors into another set of named vectors.
+ *
+ * Furthermore, an operator can be notified of parameter changes by
+ * the calling routine. The outer iteration can notify() the Operator
+ * of an Event, which could be for instance a change of mesh, a
+ * different time step size or too slow convergence of Newton's
+ * method, which would then trigger reassembling of a matrix or
+ * similar things.
+ *
+ * <h3>Usage for nested iterations</h3>
+ *
+ * This is probably the most prominent use for Operator, where an
+ * outer iterative method calls an inner solver and so on. Typically,
+ * the innermost method in such a nested system will have to compute a
+ * residual using values from all outer iterations. Since the depth
+ * and order of such a nesting is hardly predictable when designing a
+ * general tool, we use NamedData to access these vectors. Typically,
+ * the first vector in <tt>out</tt> contains the start vector when
+ * operator()() is called, and the solution when the function
+ * returns. The object <tt>in</tt> is providing additional information
+ * and forwarded to the inner Operator objects of the nested
+ * iteration.
+ *
+ * @author Guido Kanschat, 2010
+ */
+ template <class VECTOR>
+ class Operator : public OperatorBase
+ {
+ public:
+ Operator();
+
+ /**
+ * Implementation of the function in the base class in order to do
+ * compatibility conversions between the old and the new
+ * interface.
+ */
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated It is in particular this function which should not be used anymore.
+ *
+ * The actual operation, which
+ * is implemented in a derived class.
+ */
+ virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
+
+ /**
+ * Set this true to avoid compatibility warnings.
+ */
+ bool silent_compatibility;
+
+ private:
+ /**
+ * While we are providing compatibility functions to the old
+ * interface, this variable will ensure there is no endless loop.
+ */
+ bool compatibility_flag;
};
/**
OutputOperator<VECTOR> &operator<< (unsigned int step);
/**
- * Output all the vectors in NamedData.
+ * Output all the vectors in AnyData.
+ */
+ virtual OutputOperator<VECTOR> &operator<< (const AnyData &vectors);
+
+ /**
+ * @deprecated Output all the vectors in NamedData.
*/
- virtual OutputOperator<VECTOR> &operator<< (const NamedData<VECTOR *> &vectors);
+ OutputOperator<VECTOR> &operator<< (const NamedData<VECTOR *> &vectors);
protected:
unsigned int step;
private:
#include <deal.II/algorithms/operator.h>
+#include <deal.II/base/logstream.h>
DEAL_II_NAMESPACE_OPEN
namespace Algorithms
{
template <class VECTOR>
- Operator<VECTOR>::~Operator()
+ Operator<VECTOR>::Operator()
+ : silent_compatibility(false), compatibility_flag(false)
{}
-
template <class VECTOR>
- void Operator<VECTOR>::notify(const Event &e)
+ void
+ Operator<VECTOR>::operator() (AnyData &out, const AnyData &in)
{
- notifications += e;
+ // Had this function been overloaded in a derived clas, it would
+ // not have been called. Therefore, we have to start the
+ // compatibility engine. But before, we have to avoid an endless loop.
+ Assert(!compatibility_flag, ExcMessage("Compatibility resolution of Operator generates and endless loop\n"
+ "Please provide an operator() in a derived class"));
+ compatibility_flag = true;
+
+ NamedData<VECTOR *> new_out;
+ for (unsigned int i=0; i<out.size(); ++i)
+ {
+ if (out.is_type<VECTOR *>(i))
+ new_out.add(out.entry<VECTOR *>(i), out.name(i));
+ else if (!silent_compatibility)
+ deallog << "Cannot convert AnyData argument " << out.name(i) << " to NamedData"
+ << std::endl;
+ }
+
+ NamedData<VECTOR *> new_in;
+ for (unsigned int i=0; i<in.size(); ++i)
+ {
+ // deallog << "Convert " << in.name(i) << std::endl;
+ if (in.is_type<VECTOR *>(i))
+ {
+ // This const cast is due to the wrong constness handling
+ // in NamedData. As soon as NamedData is gone, this code
+ // will not be necessary anymore. And deprecating begins
+ // now.
+ VECTOR *p = const_cast<VECTOR *> (in.entry<VECTOR *>(i));
+ new_in.add(p, in.name(i));
+ }
+ else if (in.is_type<const VECTOR *>(i))
+ {
+ // This const cast is due to the wrong constness handling
+ // in NamedData. As soon as NamedData is gone, this code
+ // will not be necessary anymore. And deprecating begins
+ // now.
+ VECTOR *p = const_cast<VECTOR *> (in.entry<const VECTOR *>(i));
+ new_in.add(p, in.name(i));
+ }
+ else if (!silent_compatibility)
+ deallog << "Cannot convert AnyData argument " << in.name(i)
+ << " to NamedData" << std::endl;
+ }
+ this->operator() (new_out, new_in);
+ compatibility_flag = false;
}
template <class VECTOR>
void
- Operator<VECTOR>::clear_events ()
+ Operator<VECTOR>::operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in)
{
- notifications.clear();
+ // Had this function been overloaded in a derived clas, it would
+ // not have been called. Therefore, we have to start the
+ // compatibility engine. But before, we have to avoid an endless loop.
+ Assert(!compatibility_flag, ExcMessage("Compatibility resolution of Operator generates and endless loop\n"
+ "Please provide an operator() in a derived class"));
+ compatibility_flag = true;
+
+ AnyData new_out;
+ for (unsigned int i=0; i<out.size(); ++i)
+ new_out.add(out(i), out.name(i));
+
+ AnyData new_in;
+ for (unsigned int i=0; i<in.size(); ++i)
+ new_in.add(in(i), in.name(i));
+
+ this->operator() (new_out, new_in);
+ compatibility_flag = false;
}
template <class VECTOR>
OutputOperator<VECTOR> &
- OutputOperator<VECTOR>::operator<< (const NamedData<VECTOR *> &vectors)
+ OutputOperator<VECTOR>::operator<< (const AnyData &vectors)
{
if (os == 0)
{
- //TODO: make this possible
- //deallog << ' ' << step;
- //for (unsigned int i=0;i<vectors.size();++i)
- // vectors(i)->print(deallog);
- //deallog << std::endl;
+ deallog << "Step " << step << std::endl;
+ for (unsigned int i=0; i<vectors.size(); ++i)
+ {
+ const VECTOR *v = vectors.try_read_ptr<VECTOR>(i);
+ if (v == 0) continue;
+ deallog << vectors.name(i);
+ for (unsigned int j=0; j<v->size(); ++j)
+ deallog << ' ' << (*v)(j);
+ deallog << std::endl;
+ }
+ deallog << std::endl;
}
else
{
(*os) << ' ' << step;
for (unsigned int i=0; i<vectors.size(); ++i)
- for (unsigned int j=0; j<vectors(i)->size(); ++j)
- (*os) << ' ' << (*vectors(i))(j);
+ {
+ const VECTOR *v = vectors.try_read_ptr<VECTOR>(i);
+ if (v == 0) continue;
+ for (unsigned int j=0; j<v->size(); ++j)
+ (*os) << ' ' << (*v)(j);
+ }
(*os) << std::endl;
}
return *this;
}
+
+
+ template <class VECTOR>
+ OutputOperator<VECTOR> &
+ OutputOperator<VECTOR>::operator<< (const NamedData<VECTOR *> &vectors)
+ {
+ const AnyData newdata = vectors;
+ (*this) << newdata;
+ return *this;
+ }
}
DEAL_II_NAMESPACE_CLOSE
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2010 - 2013 by the deal.II authors
+// Copyright (C) 2010 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* error term. In order to avoid a loss of convergence order, the
* adaptive theta scheme can be used, where <i>#theta=½+c dt</i>.
*
- * Assume that we want to solve the equation <i>u' + Au = 0</i> with a
+ * Assume that we want to solve the equation <i>u' + F(u) = 0</i> with a
* step size <i>k</i>. A step of the theta scheme can be written as
*
* @f[
- * (M + \theta k A) u_{n+1} = (M - (1-\theta)k A) u_n.
+ * M u_{n+1} + \theta k F(u_{n+1}) = M u_n - (1-\theta)k F(u_n).
* @f]
*
* Here, <i>M</i> is the mass matrix. We see, that the right hand side
* Operator objects, one for the explicit, one for the implicit
* part. Each of these will use its own TimestepData to account for
* the modified step sizes (and different times if the problem is not
- * autonomous).
+ * autonomous). Note that once the explicit part has been computed,
+ * the left hand side actually constitutes a linear or nonlinear
+ * system which has to be solved.
*
- * <h3>Usage of vectors in NamedData</h3>
+ * <h3>Usage AnyData</h3>
*
- * ThetaTimestepping uses NamedData for communicating vectors. With
+ * ThetaTimestepping uses AnyData for communicating vectors and time
+ * step information. With
* outer or inner Operator objects. It does not use itself the input
* vectors provided, but forwards them to the explicit and implicit
* operators.
*
+ * <h4>Vector data</h4>
+ *
* The explicit Operator #op_explicit receives in its input in first
- * place the vector <tt>"Previous iterate"</tt>, which is the solution
+ * place the vector "Previous iterate", which is the solution
* value after the previous timestep. It is followed by all vectors
* provided to ThetaTimestepping::operator() as input
* argument. #op_explicit is supposed to write its result into the
- * first position of its output argument, labeled <tt>"Result"</tt>.
+ * first position of its output argument, labeled "Result".
*
* The implicit Operator #op_implicit receives the result of
- * #op_explicit in its first input vector labeled <tt>"Previous
- * time"</tt>. It is followed by all vectors provided to
+ * #op_explicit in its first input vector labeled "Previous
+ * time". It is followed by all vectors provided to
* ThetaTimestepping::operator() as input argument. The output of
* #op_implicit is directly written into the output argument given to
* ThetaTimestepping.
*
+ * <h4>Scalar data</h4>
+ *
+ * Since the introduction of AnyData, ThetaTimestepping is able to
+ * communicate the current time step information through AnyData as
+ * well. Therefore, the AnyData objects handed as input to
+ * #op_explicit and #op_implicit contain two entries of type
+ * `const double*` named "Time" and "Timestep". Note
+ * that "Time" refers to the time at the beginning of the current
+ * step for #op_explicit and at the end for #op_implicit,
+ * respectively.
+ *
* <h3>Usage of ThetaTimestepping</h3>
*
* The use ThetaTimestepping is more complicated than for instance
* @until End of declarations
*
* These operators will be implemented after the main program. But let
- * us look at how they get used. First, let us define a matrix to be
+ * us look first at how they get used. First, let us define a matrix to be
* used for our system and also an OutputOperator in order to write
* the data of each timestep to a file.
*
* @until out.initialize
*
* Now we create objects for the implicit and explicit parts of the
- * steps as well as the ThetaTimestepping itself. Notice how the
- * TimestepData of ThetaTimestepping gets forwarded to the inner
- * operators. There are two different data objects, because the
- * timestep size is modified by #theta.
+ * steps as well as the ThetaTimestepping itself. We initialize the
+ * timestepping with the output operator in order to be able to see
+ * the output in every step.
*
* @until set_output
*
* is filled with the initial value and is also the vector where the
* solution at each timestep will be. Because the interface of
* Operator has to be able to handle several vectors, we need to store
- * it in a NamedData object. Notice, that we need to create the
- * intermediate pointer <tt>p</tt>. If we would use
- * <code>&value</code> directly in the <code>add</code> function, the
- * resulting object would be constant.
+ * it in an AnyData object. Since our problem has no additional
+ * parameters, the input AnyData object remains empty.
*
* @until add
*
- * Finally, we are ready to tell the solver, that we are looknig at
+ * Finally, we are ready to tell the solver, that we are starting at
* the initial timestep and run it.
*
- * @until outdata
- * @skip Explicit::initialize
+ * @until }
+ *
+ * First the constructor, which simply copies the system matrix into
+ * the member pointer for later use.
+ *
+ * @skip Explicit::
+ * @until }
*
* Now we need to study the application of the implicit and explicit
* operator. We assume that the pointer <code>matrix</code> points to
- * the matrix created in the main program, and that
- * <code>timestep_data</code> points to the correct data object of
- * ThetaTimestepping.
+ * the matrix created in the main program (the constructor did this
+ * for us). Here, we first get the time step size from the AnyData
+ * object that was provided as input. Then, if we are in the first
+ * step or if the timestep has changed, we fill the local matrix
+ * <tt>m</tt>, such that with the given matrix \f$M\f$, it becomes
+ * \f[
+ * m = I - \Delta t M.
+ * \f]
+ * After we have worked off the notifications, we clear them, such
+ * that the matrix is only generated when necessary.
*
* @skipline void
- * @until vmult
+ * @until clear
+ *
+ * Now we multiply the input vector with the new matrix and store on output.
+ *
* @until }
+ * The code for the implicit operator is almost the same, except
+ * that we change the sign in front of the timestep and use the
+ * inverse of t he matrix.
*
+ * @until vmult
+ * @until }
* @author Guido Kanschat
* @date 2010
*/
Operator<VECTOR> &op_implicit);
/**
- * The timestepping scheme. <tt>in</tt>
- * should contain the initial
- * value in first position. <tt>out</tt>
+ * The timestepping scheme.
+ *
+ * @param `in` is ignored by
+ * ThetaTimestepping, but is merged into the AnyData objects used
+ * as input for the operators #op_explicit and #op_implicit.
+ *
+ * @param `out` in its first argument must contain a pointer to a
+ * `VECTOR`, which contains the initial value when the operator is
+ * called. It contains the final value when the operator returns.
+ */
+ virtual void operator() (AnyData &out, const AnyData &in);
+
+ /**
+ * @deprecated Use the function with AnyData arguments
*/
virtual void operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in);
virtual void notify(const Event &);
/**
- * Define an operator which
- * will output the result in
- * each step. Note that no
- * output will be generated
- * without this.
+ * Define an operator which will output the result in each
+ * step. Note that no output will be generated without this.
*/
void set_output(OutputOperator<VECTOR> &output);
- void declare_parameters (ParameterHandler ¶m);
- void initialize (ParameterHandler ¶m);
+ /**
+ * Declare parameters in a parameter handler.
+ */
+ static void declare_parameters (ParameterHandler ¶m);
+
+ /**
+ * Read the parameters in the ParameterHandler.
+ */
+ void parse_parameters (ParameterHandler ¶m);
+
+ /**
+ * @deprecated Use parse_parameters().
+ */
+ void initialize (ParameterHandler ¶m) DEAL_II_DEPRECATED;
/**
* The current time in the
* timestepping scheme.
*/
- const double ¤t_time() const;
+ double current_time() const;
/**
* The current step size.
*/
- const double &step_size() const;
+ double step_size() const;
/**
- * The weight between implicit
- * and explicit part.
+ * The weight between implicit and explicit part.
*/
- const double &theta() const;
+ double theta() const;
/**
- * The data handed to the
- * #op_explicit time stepping
- * operator.
+ * Set a new weight and return the old
+ */
+ double theta(double new_theta);
+
+ /**
+ * The data handed to the #op_explicit time stepping operator.
*
- * The time in here is the time
- * at the beginning of the
- * current step, the time step
- * is (1-#theta) times the
- * actual time step.
+ * The time in here is the time at the beginning of the current
+ * step, the time step is (1-#theta) times the actual time step.
*/
const TimestepData &explicit_data() const;
/**
- * The data handed to the
- * #op_implicit time stepping
- * operator.
+ * The data handed to the #op_implicit time stepping operator.
*
- * The time in here is the time
- * at the beginning of the
- * current step, the time step
- * is #theta times the
- * actual time step.
+ * The time in here is the time at the beginning of the current
+ * step, the time step is #theta times the actual time step.
*/
const TimestepData &implicit_data() const;
private:
/**
- * The object controlling the
- * time step size and computing
- * the new time in each step.
+ * The object controlling the time step size and computing the new
+ * time in each step.
*/
TimestepControl control;
/**
- * The control parameter theta in the
- * range <tt>[0,1]</tt>.
+ * The control parameter theta in the range <tt>[0,1]</tt>. It
+ * defaults to 0.5.
*/
double vtheta;
/**
- * Use adaptive #theta if
- * <tt>true</tt>.
+ * Use adaptive #theta if <tt>true</tt>. Not yet implemented.
*/
bool adaptive;
/**
- * The data for the explicit
- * part of the scheme.
+ * The data for the explicit part of the scheme.
*/
TimestepData d_explicit;
/**
- * The data for the implicit
- * part of the scheme.
+ * The data for the implicit part of the scheme.
*/
TimestepData d_implicit;
/**
- * The operator computing the
- * explicit part of the
- * scheme. This will receive in
- * its input data the value at
- * the current time with name
- * "Current time solution". It
- * should obtain the current
- * time and time step size from
- * explicit_data().
+ * The operator computing the explicit part of the scheme. This
+ * will receive in its input data the value at the current time
+ * with name "Current time solution". It should obtain the current
+ * time and time step size from explicit_data().
*
- * Its return value is
- * <i>Mu+cAu</i>, where
- * <i>u</i> is the current
- * state vector, <i>M</i> the
- * mass matrix, <i>A</i> the
- * operator in space and
- * <i>c</i> is the time step
- * size in explicit_data().
+ * Its return value is <i>Mu+cF(u)</i>, where <i>u</i> is the
+ * current state vector, <i>M</i> the mass matrix, <i>F</i> the
+ * operator in space and <i>c</i> is the adjusted
+ * time step size \f$ (1-\theta) \Delta t\f$.
*/
SmartPointer<Operator<VECTOR>, ThetaTimestepping<VECTOR> > op_explicit;
/**
- * The operator solving the
- * implicit part of the
- * scheme. It will receive in
- * its input data the vector
- * "Previous time". Information on the
- * timestep should be obtained
- * from implicit_data().
+ * The operator solving the implicit part of the scheme. It will
+ * receive in its input data the vector "Previous
+ * time". Information on the timestep should be obtained from
+ * implicit_data().
*
- * Its return value is the
- * solution <i>u</i> of
- * <i>Mu-cAu=f</i>, where
- * <i>f</i> is the dual space
- * vector found in the
- * "Previous time" entry of the
- * input data, <i>M</i> the
- * mass matrix, <i>A</i> the
- * operator in space and
- * <i>c</i> is the time step
- * size in explicit_data().
+ * Its return value is the solution <i>u</i> of <i>Mu-cF(u)=f</i>,
+ * where <i>f</i> is the dual space vector found in the "Previous
+ * time" entry of the input data, <i>M</i> the mass matrix,
+ * <i>F</i> the operator in space and <i>c</i> is the adjusted
+ * time step size \f$ \theta \Delta t\f$
*/
SmartPointer<Operator<VECTOR>, ThetaTimestepping<VECTOR> > op_implicit;
/**
- * The operator writing the
- * output in each time step
+ * The operator writing the output in each time step
*/
SmartPointer<OutputOperator<VECTOR>, ThetaTimestepping<VECTOR> > output;
};
return d_implicit;
}
+
+ template <class VECTOR>
+ inline
+ TimestepControl &
+ ThetaTimestepping<VECTOR>::timestep_control ()
+ {
+ return control;
+ }
+
template <class VECTOR>
inline
void ThetaTimestepping<VECTOR>::set_output (OutputOperator<VECTOR> &out)
{
output = &out;
}
+
+
+ template <class VECTOR>
+ inline
+ double ThetaTimestepping<VECTOR>::theta () const
+ {
+ return vtheta;
+ }
+
+
+ template <class VECTOR>
+ inline
+ double ThetaTimestepping<VECTOR>::theta (double new_theta)
+ {
+ const double tmp = vtheta;
+ vtheta = new_theta;
+ return tmp;
+ }
+
+
+ template <class VECTOR>
+ inline
+ double ThetaTimestepping<VECTOR>::current_time () const
+ {
+ return control.now();
+ }
}
DEAL_II_NAMESPACE_CLOSE
template <class VECTOR>
void
- ThetaTimestepping<VECTOR>::initialize (ParameterHandler ¶m)
+ ThetaTimestepping<VECTOR>::parse_parameters (ParameterHandler ¶m)
{
param.enter_subsection("ThetaTimestepping");
control.parse_parameters (param);
}
+ template <class VECTOR>
+ void
+ ThetaTimestepping<VECTOR>::initialize (ParameterHandler ¶m)
+ {
+ parse_parameters(param);
+ }
+
+
template <class VECTOR>
void
ThetaTimestepping<VECTOR>::operator() (NamedData<VECTOR *> &out, const NamedData<VECTOR *> &in)
+ {
+ Operator<VECTOR>::operator() (out, in);
+ }
+
+
+ template <class VECTOR>
+ void
+ ThetaTimestepping<VECTOR>::operator() (AnyData &out, const AnyData &in)
{
Assert(!adaptive, ExcNotImplemented());
deallog.push ("Theta");
+
+ VECTOR &solution = *out.entry<VECTOR *>(0);
GrowingVectorMemory<VECTOR> mem;
typename VectorMemory<VECTOR>::Pointer aux(mem);
- aux->reinit(*out(0));
+ aux->reinit(solution);
control.restart();
// The data used to compute the
// vector associated with the old
// timestep
- VECTOR *p = out(0);
- NamedData<VECTOR *> src1;
- src1.add(p, "Previous iterate");
+ AnyData src1;
+ src1.add<const VECTOR *>(&solution, "Previous iterate");
+ src1.add<const double *>(&d_explicit.time, "Time");
+ src1.add<const double *>(&d_explicit.step, "Timestep");
+ src1.add<const double *>(&vtheta, "Theta");
src1.merge(in);
- NamedData<VECTOR *> src2;
- src2.add(p, "Previous iterate");
+ AnyData src2;
- p = aux;
- NamedData<VECTOR *> out1;
- out1.add(p, "Result");
- // The data provided to the inner
- // solver
- src2.add(p, "Previous time");
+ AnyData out1;
+ out1.add<VECTOR *>(aux, "Solution");
+ // The data provided to the inner solver
+ src2.add<const VECTOR *>(aux, "Previous time");
+ src2.add<const VECTOR *>(&solution, "Previous iterate");
+ src2.add<const double *>(&d_implicit.time, "Time");
+ src2.add<const double *>(&d_implicit.step, "Timestep");
+ src2.add<const double *>(&vtheta, "Theta");
src2.merge(in);
if (output != 0)
(*output) << 0U << out;
+ // Avoid warnings because time and timestep cannot be converted to VECTOR*
+ const bool explicit_silent = op_explicit->silent_compatibility;
+ const bool implicit_silent = op_implicit->silent_compatibility;
+ op_explicit->silent_compatibility = true;
+ op_implicit->silent_compatibility = true;
+
for (unsigned int count = 1; d_explicit.time < control.final(); ++count)
{
const bool step_change = control.advance();
d_explicit.time = control.now();
}
+ op_explicit->silent_compatibility = explicit_silent;
+ op_implicit->silent_compatibility = implicit_silent;
deallog.pop();
}
}
double max_step = 1.);
/**
- * Declare the control
- * parameters for parameter
- * handler.
+ * Declare the control parameters for parameter handler.
*/
static void declare_parameters (ParameterHandler ¶m);
/**
- * Read the control parameters
- * from a parameter handler.
+ * Read the control parameters from a parameter handler.
*/
void parse_parameters (ParameterHandler ¶m);
*/
double start () const;
/**
- * The right end of the time
- * interval. The control
- * mechanism ensures that the
- * final time step ends at this
- * point.
+ * The right end of the time interval. The control mechanism
+ * ensures that the final time step ends at this point.
*/
double final () const;
/**
- * The tolerance value
- * controlling the time steps.
+ * The tolerance value controlling the time steps.
*/
double tolerance () const;
/**
- * The size of the current time
- * step.
+ * The size of the current time step.
*/
double step () const;
double now () const;
/**
- * Compute the size of the next
- * step size and return true if
- * it differs from the current
- * step size. Advance the
- * current time by the new step
- * size.
+ * Compute the size of the next step and return true if it differs
+ * from the current step size. Advance the current time by the new
+ * step size.
*/
bool advance ();
void strategy (Strategy);
/**
- * Set size of the first
- * step. This may be overwritten
- * by the time stepping strategy.
+ * Set size of the first step. This may be overwritten by the time
+ * stepping strategy.
*/
void start_step (double);
/**
- * Set size of the maximum
- * step size.
+ * Set size of the maximum step size.
*/
void max_step (double);
/**
- * Set now() equal to
- * start(). Initialize step() and
- * print() to their initial
- * values.
+ * Set now() equal to start(). Initialize step() and print() to
+ * their initial values.
*/
void restart ();
/**
- * Return true if this timestep
- * should be written to disk.
+ * Return true if this timestep should be written to disk.
*/
bool print ();
/**
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__aligned_vector_h
+#define __deal2__aligned_vector_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/std_cxx1x/type_traits.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/parallel.h>
+#include <boost/serialization/array.hpp>
+#include <boost/serialization/split_member.hpp>
+
+#include <cstring>
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+#include <emmintrin.h>
+#endif
+
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * This is a replacement class for std::vector to be used in combination with
+ * VectorizedArray and derived data types. It allocates memory aligned to
+ * addresses of a vectorized data type (in order to avoid segmentation faults
+ * when a variable of type VectorizedArray which the compiler assumes to be
+ * aligned to certain memory addresses does not actually follow these
+ * rules). This could also be achieved by proving std::vector with a
+ * user-defined allocator. On the other hand, writing an own small vector
+ * class lets us implement parallel copy and move operations with TBB, insert
+ * deal.II-style assertions, and cut some unnecessary functionality. Note that
+ * this vector is a bit more memory-consuming than std::vector because of
+ * alignment, so it is recommended to only use this vector on long vectors.
+ *
+ * @p author Katharina Kormann, Martin Kronbichler, 2011
+ */
+template < class T >
+class AlignedVector
+{
+public:
+ /**
+ * Declare standard types used in all containers. These types parallel those
+ * in the <tt>C++</tt> standard libraries <tt>vector<...></tt> class.
+ */
+ typedef T value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef value_type *iterator;
+ typedef const value_type *const_iterator;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef std::size_t size_type;
+
+ /**
+ * Empty constructor. Sets the vector size to zero.
+ */
+ AlignedVector ();
+
+ /**
+ * Sets the vector size to the given size and initializes all elements with
+ * T().
+ *
+ * @dealiiOperationIsMultithreaded
+ */
+ AlignedVector (const size_type size,
+ const T &init = T());
+
+ /**
+ * Destructor.
+ */
+ ~AlignedVector ();
+
+ /**
+ * Copy constructor.
+ *
+ * @dealiiOperationIsMultithreaded
+ */
+ AlignedVector (const AlignedVector<T> &vec);
+
+ /**
+ * Assignment to the input vector @p vec.
+ *
+ * @dealiiOperationIsMultithreaded
+ */
+ AlignedVector &
+ operator = (const AlignedVector<T> &vec);
+
+ /**
+ * Change the size of the vector. It keeps old elements previously available
+ * but does not initialize the newly allocated memory, leaving it in an
+ * undefined state.
+ */
+ void resize_fast (const size_type size);
+
+ /**
+ * Change the size of the vector. It keeps old elements previously
+ * available, and initializes each element with the specified data. If the
+ * new vector size is shorter than the old one, the memory is not released
+ * unless the new size is zero.
+ *
+ * @dealiiOperationIsMultithreaded
+ */
+ void resize (const size_type size_in,
+ const T &init = T());
+
+ /**
+ * Reserve memory space for @p size elements. If the argument @p size is set
+ * to zero, all previously allocated memory is released.
+ *
+ * In order to avoid too frequent reallocation (which involves copy of the
+ * data), this function doubles the amount of memory occupied when the given
+ * size is larger than the previously allocated size.
+ */
+ void reserve (const size_type size_alloc);
+
+ /**
+ * Releases all previously allocated memory and leaves the vector in a state
+ * equivalent to the state after the default constructor has been called.
+ */
+ void clear ();
+
+ /**
+ * Inserts an element at the end of the vector, increasing the vector size
+ * by one. Note that the allocated size will double whenever the previous
+ * space is not enough to hold the new element.
+ */
+ void push_back (const T in_data);
+
+ /**
+ * Returns the last element of the vector (read and write access).
+ */
+ reference back ();
+
+ /**
+ * Returns the last element of the vector (read-only access).
+ */
+ const_reference back () const;
+
+ /**
+ * Inserts several elements at the end of the vector given by a range of
+ * elements.
+ */
+ template <typename ForwardIterator>
+ void insert_back (ForwardIterator begin,
+ ForwardIterator end);
+
+ /**
+ * Fills the vector with size() copies of the given input.
+ *
+ * @dealiiOperationIsMultithreaded
+ */
+ void fill (const T &element);
+
+ /**
+ * Swaps the given vector with the calling vector.
+ */
+ void swap (AlignedVector<T> &vec);
+
+ /**
+ * Returns whether the vector is empty, i.e., its size is zero.
+ */
+ bool empty () const;
+
+ /**
+ * Returns the size of the vector.
+ */
+ size_type size () const;
+
+ /**
+ * Returns the capacity of the vector, i.e., the size this vector can hold
+ * without reallocation. Note that capacity() >= size().
+ */
+ size_type capacity () const;
+
+ /**
+ * Read-write access to entry @p index in the vector.
+ */
+ reference
+ operator [] (const size_type index);
+
+ /**
+ * Read-only access to entry @p index in the vector.
+ */
+ const_reference operator [] (const size_type index) const;
+
+ /**
+ * Returns a read and write pointer to the beginning of the data array.
+ */
+ iterator begin ();
+
+ /**
+ * Returns a read and write pointer to the end of the data array.
+ */
+ iterator end ();
+
+ /**
+ * Returns a read-only pointer to the beginning of the data array.
+ */
+ const_iterator begin () const;
+
+ /**
+ * Returns a read-only pointer to the end of the data array.
+ */
+ const_iterator end () const;
+
+ /**
+ * Returns the memory consumption of the allocated memory in this class. If
+ * the underlying type @p T allocates memory by itself, this memory is not
+ * counted.
+ */
+ size_type memory_consumption () const;
+
+ /**
+ * Write the data of this object to
+ * a stream for the purpose of serialization.
+ */
+ template <class Archive>
+ void save (Archive &ar, const unsigned int version) const;
+
+ /**
+ * Read the data of this object
+ * from a stream for the purpose of serialization.
+ */
+ template <class Archive>
+ void load (Archive &ar, const unsigned int version);
+
+ BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+private:
+
+ /**
+ * Pointer to actual class data.
+ */
+ T *_data;
+
+ /**
+ * Pointer to the end of valid data fields.
+ */
+ T *_end_data;
+
+ /**
+ * Pointer to the end of the allocated memory.
+ */
+ T *_end_allocated;
+};
+
+
+// ------------------------------- inline functions --------------------------
+
+/**
+ * This namespace defines the copy and set functions used in
+ * AlignedVector. These functions operate in parallel when there are enough
+ * elements in the vector.
+ */
+namespace internal
+{
+ /**
+ * Move and class that actually issues the copy commands in
+ * AlignedVector. This class is based on the specialized for loop base class
+ * ParallelForLoop in parallel.h whose purpose is the following: When
+ * calling a parallel for loop on AlignedVector with apply_to_subranges, it
+ * generates different code for every different argument we might choose (as
+ * it is templated). This gives a lot of code (e.g. it triples the memory
+ * required for compiling the file matrix_free.cc and the final object size
+ * is several times larger) which is completely useless. Therefore, this
+ * class channels all copy commands through one call to apply_to_subrange
+ * for all possible types, which makes the copy operation much cleaner
+ * (thanks to a virtual function, whose cost is negligible in this context).
+ *
+ * @relates AlignedVector
+ */
+ template <typename T>
+ class AlignedVectorMove : private parallel::ParallelForInteger
+ {
+ static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
+ public:
+ /**
+ * Constructor. Issues a parallel call if there are sufficiently many
+ * elements, otherwise work in serial. Copies the data from source to
+ * destination and then calls destructor on the source. If the optional
+ * argument is set to true, the source is left untouched instead.
+ */
+ AlignedVectorMove (T *source_begin,
+ T *source_end,
+ T *destination,
+ bool copy_only = false)
+ :
+ source_ (source_begin),
+ destination_ (destination),
+ copy_only_ (copy_only)
+ {
+ Assert (source_end >= source_begin, ExcInternalError());
+ const std::size_t size = source_end - source_begin;
+ if (size < minimum_parallel_grain_size)
+ apply_to_subrange (0, size);
+ else
+ apply_parallel (0, size, minimum_parallel_grain_size);
+ }
+
+ /**
+ * This method moves elements from the source to the destination given in
+ * the constructor on a subrange given by two integers.
+ */
+ virtual void apply_to_subrange (const std::size_t begin,
+ const std::size_t end) const
+ {
+ // for classes trivial assignment can use memcpy. cast element to
+ // (void*) to silence compiler warning for virtual classes (they will
+ // never arrive here because they are non-trivial).
+
+ if (std_cxx1x::is_trivial<T>::value == true)
+ std::memcpy ((void*)(destination_+begin), source_+begin,
+ (end-begin)*sizeof(T));
+ else if (copy_only_ == false)
+ for (std::size_t i=begin; i<end; ++i)
+ {
+ // initialize memory (copy construct), and destruct
+ new (&destination_[i]) T(source_[i]);
+ source_[i].~T();
+ }
+ else
+ for (std::size_t i=begin; i<end; ++i)
+ {
+ new (&destination_[i]) T(source_[i]);
+ }
+ }
+
+ private:
+ T *source_;
+ T *destination_;
+ const bool copy_only_;
+ };
+
+ /**
+ * Class that issues the set commands for AlignedVector.
+ *
+ * @relates AlignedVector
+ */
+ template <typename T>
+ class AlignedVectorSet : private parallel::ParallelForInteger
+ {
+ static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
+ public:
+ /**
+ * Constructor. Issues a parallel call if there are sufficiently many
+ * elements, otherwise work in serial.
+ */
+ AlignedVectorSet (const std::size_t size,
+ const T &element,
+ T *destination)
+ :
+ element_ (element),
+ destination_ (destination),
+ trivial_element (false)
+ {
+ if (size == 0)
+ return;
+
+ // do not use memcmp for long double because on some systems it does not
+ // completely fill its memory and may lead to false positives in
+ // e.g. valgrind
+ if (std_cxx1x::is_trivial<T>::value == true &&
+ types_are_equal<T,long double>::value == false)
+ {
+ const unsigned char zero [sizeof(T)] = {};
+ // cast element to (void*) to silence compiler warning for virtual
+ // classes (they will never arrive here because they are
+ // non-trivial).
+ if (std::memcmp(zero, (void*)&element, sizeof(T)) == 0)
+ trivial_element = true;
+ }
+ if (size < minimum_parallel_grain_size)
+ apply_to_subrange (0, size);
+ else
+ apply_parallel (0, size, minimum_parallel_grain_size);
+ }
+
+ private:
+
+ /**
+ * This sets elements on a subrange given by two integers.
+ */
+ virtual void apply_to_subrange (const std::size_t begin,
+ const std::size_t end) const
+ {
+ // for classes with trivial assignment of zero can use memset. cast
+ // element to (void*) to silence compiler warning for virtual
+ // classes (they will never arrive here because they are
+ // non-trivial).
+ if (std_cxx1x::is_trivial<T>::value == true && trivial_element)
+ std::memset ((void*)(destination_+begin), 0, (end-begin)*sizeof(T));
+ else
+ // initialize memory and set
+ for (std::size_t i=begin; i<end; ++i)
+ new (&destination_[i]) T(element_);
+ }
+
+ const T &element_;
+ mutable T *destination_;
+ bool trivial_element;
+ };
+
+} // end of namespace internal
+
+
+#ifndef DOXYGEN
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector ()
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector (const size_type size,
+ const T &init)
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{
+ if (size > 0)
+ resize (size, init);
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::~AlignedVector ()
+{
+ clear();
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>::AlignedVector (const AlignedVector<T> &vec)
+ :
+ _data (0),
+ _end_data (0),
+ _end_allocated (0)
+{
+ // do not invalidate old data
+ resize_fast (vec._end_data - vec._data);
+ internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
+}
+
+
+
+template < class T >
+inline
+AlignedVector<T>&
+AlignedVector<T>::operator = (const AlignedVector<T> &vec)
+{
+ resize(0);
+ resize_fast (vec._end_data - vec._data);
+ internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
+ return *this;
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::resize_fast (const size_type size)
+{
+ reserve (size);
+ _end_data = _data + size;
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::resize (const size_type size_in,
+ const T &init)
+{
+ const size_type old_size = size();
+ if (std_cxx1x::is_trivial<T>::value == false && size_in < old_size)
+ {
+ // call destructor on fields that are released
+ while (_end_data != _data+size_in)
+ (--_end_data)->~T();
+ }
+
+ resize_fast (size_in);
+ // now _size is set correctly, need to set the
+ // values
+ if (size_in > old_size)
+ dealii::internal::AlignedVectorSet<T> (size_in-old_size, init, _data+old_size);
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::reserve (const size_type size_alloc)
+{
+ const size_type old_size = _end_data - _data;
+ const size_type allocated_size = _end_allocated - _data;
+ if (size_alloc > allocated_size)
+ {
+ // if we continuously increase the size of the vector, we might be
+ // reallocating a lot of times. therefore, try to increase the size more
+ // aggressively
+ size_type new_size = size_alloc;
+ if (size_alloc < (2 * allocated_size))
+ new_size = 2 * allocated_size;
+
+ const size_type size_actual_allocate = new_size * sizeof(T);
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+
+ // allocate and align along 64-byte boundaries (this is enough for all
+ // levels of vectorization currently supported by deal.II)
+ T *new_data = static_cast<T *>(_mm_malloc (size_actual_allocate, 64));
+#else
+ T *new_data = static_cast<T *>(malloc (size_actual_allocate));
+#endif
+ if (new_data == 0)
+ throw std::bad_alloc();
+
+ // copy data in case there was some content before and release the old
+ // memory with the function corresponding to the one used for allocating
+ std::swap (_data, new_data);
+ _end_data = _data + old_size;
+ _end_allocated = _data + new_size;
+ if (_end_data != _data)
+ {
+ dealii::internal::AlignedVectorMove<T>(new_data, new_data + old_size,
+ _data);
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ _mm_free(new_data);
+#else
+ free(new_data);
+#endif
+ }
+ }
+ else if (size_alloc == 0)
+ clear();
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::clear ()
+{
+ if (_data != 0)
+ {
+ if (std_cxx1x::is_trivial<T>::value == false)
+ while (_end_data != _data)
+ (--_end_data)->~T();
+
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ _mm_free(_data);
+#else
+ free(_data);
+#endif
+ }
+ _data = 0;
+ _end_data = 0;
+ _end_allocated = 0;
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::push_back (const T in_data)
+{
+ Assert (_end_data <= _end_allocated, ExcInternalError());
+ if (_end_data == _end_allocated)
+ reserve (std::max(2*capacity(),static_cast<size_type>(16)));
+ if (std_cxx1x::is_trivial<T>::value == false)
+ new (_end_data) T;
+ *_end_data++ = in_data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::reference
+AlignedVector<T>::back ()
+{
+ AssertIndexRange (0, size());
+ T *field = _end_data - 1;
+ return *field;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_reference
+AlignedVector<T>::back () const
+{
+ AssertIndexRange (0, size());
+ const T *field = _end_data - 1;
+ return *field;
+}
+
+
+
+template < class T >
+template <typename ForwardIterator>
+inline
+void
+AlignedVector<T>::insert_back (ForwardIterator begin,
+ ForwardIterator end)
+{
+ const unsigned int old_size = size();
+ reserve (old_size + (end-begin));
+ for ( ; begin != end; ++begin, ++_end_data)
+ {
+ if (std_cxx1x::is_trivial<T>::value == false)
+ new (_end_data) T;
+ *_end_data = *begin;
+ }
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::fill (const T &value)
+{
+ dealii::internal::AlignedVectorSet<T> (size(), value, _data);
+}
+
+
+
+template < class T >
+inline
+void
+AlignedVector<T>::swap (AlignedVector<T> &vec)
+{
+ std::swap (_data, vec._data);
+ std::swap (_end_data, vec._end_data);
+ std::swap (_end_allocated, vec._end_allocated);
+}
+
+
+
+template < class T >
+inline
+bool
+AlignedVector<T>::empty () const
+{
+ return _end_data == _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::size () const
+{
+ return _end_data - _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::capacity () const
+{
+ return _end_allocated - _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::reference
+AlignedVector<T>::operator [] (const size_type index)
+{
+ AssertIndexRange (index, size());
+ return _data[index];
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_reference
+AlignedVector<T>::operator [] (const size_type index) const
+{
+ AssertIndexRange (index, size());
+ return _data[index];
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::iterator
+AlignedVector<T>::begin ()
+{
+ return _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::iterator
+AlignedVector<T>::end ()
+{
+ return _end_data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_iterator
+AlignedVector<T>::begin () const
+{
+ return _data;
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::const_iterator
+AlignedVector<T>::end () const
+{
+ return _end_data;
+}
+
+
+
+template < class T >
+template < class Archive >
+inline
+void
+AlignedVector<T>::save (Archive &ar, const unsigned int) const
+{
+ size_type vec_size (size());
+ ar &vec_size;
+ if (vec_size > 0)
+ ar &boost::serialization::make_array(_data, vec_size);
+}
+
+
+
+template < class T >
+template < class Archive >
+inline
+void
+AlignedVector<T>::load (Archive &ar, const unsigned int)
+{
+ size_type vec_size = 0;
+ ar &vec_size ;
+
+ if (vec_size > 0)
+ {
+ reserve(vec_size);
+ ar &boost::serialization::make_array(_data, vec_size);
+ _end_data = _data + vec_size;
+ }
+}
+
+
+
+template < class T >
+inline
+typename AlignedVector<T>::size_type
+AlignedVector<T>::memory_consumption () const
+{
+ size_type memory = sizeof(*this);
+ for (const T* t = _data ; t != _end_data; ++t)
+ memory += dealii::MemoryConsumption::memory_consumption(*t);
+ memory += sizeof(T) * (_end_allocated-_end_data);
+ return memory;
+}
+
+
+#endif // ifndef DOXYGEN
+
+
+/**
+ * Relational operator == for AlignedVector
+ *
+ * @relates AlignedVector
+ */
+template < class T >
+bool operator == (const AlignedVector<T> &lhs,
+ const AlignedVector<T> &rhs)
+{
+ if (lhs.size() != rhs.size())
+ return false;
+ for (typename AlignedVector<T>::const_iterator lit = lhs.begin(),
+ rit = rhs.begin(); lit != lhs.end(); ++lit, ++rit)
+ if (*lit != *rit)
+ return false;
+ return true;
+}
+
+
+
+
+/**
+ * Relational operator != for AlignedVector
+ *
+ * @relates AlignedVector
+ */
+template < class T >
+bool operator != (const AlignedVector<T> &lhs,
+ const AlignedVector<T> &rhs)
+{
+ return !(operator==(lhs, rhs));
+}
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
* Configured in setup_deal_ii.cmake: *
**************************************/
-/* Defined to the full name of this package. */
+/** Defined to the full name of this package. */
#define DEAL_II_PACKAGE_NAME "@DEAL_II_PACKAGE_NAME@"
-/* Defined to the version of this package. */
+/** Defined to the version of this package. */
#define DEAL_II_PACKAGE_VERSION "@DEAL_II_PACKAGE_VERSION@"
-/* Major version number of deal.II */
+/** Major version number of deal.II */
#define DEAL_II_VERSION_MAJOR @DEAL_II_VERSION_MAJOR@
#define DEAL_II_MAJOR @DEAL_II_VERSION_MAJOR@
-/* Minor version number of deal.II */
+/** Minor version number of deal.II */
#define DEAL_II_VERSION_MINOR @DEAL_II_VERSION_MINOR@
#define DEAL_II_MINOR @DEAL_II_VERSION_MINOR@
* Configured in check_1_compiler_features: *
********************************************/
-/* Defined if the compiler can use arithmetic operations on vectorized data types */
+/** Defined if the compiler can use arithmetic operations on vectorized data types */
#cmakedefine DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
-/* Defined if vector iterators are just plain pointers */
+/** Defined if vector iterators are just plain pointers */
#cmakedefine DEAL_II_VECTOR_ITERATOR_IS_POINTER
-/* Define if the compiler provides __builtin_expect */
+/** Define if the compiler provides __builtin_expect */
#cmakedefine HAVE_BUILTIN_EXPECT
-/* Define if the compiler provides __verbose_terminate_handler */
+/** Define if the compiler provides __verbose_terminate_handler */
#cmakedefine HAVE_VERBOSE_TERMINATE
-/* Define if deal.II is linked against a libc that provides stacktrace
+/** Define if deal.II is linked against a libc that provides stacktrace
* debug information that can be printed out in the exception class
* */
#cmakedefine HAVE_GLIBC_STACKTRACE
-/* Defined if the std c++ library provides a demangler conforming to the
+/** Defined if the std c++ library provides a demangler conforming to the
* GCC libstdc++ interface.
*/
#cmakedefine HAVE_LIBSTDCXX_DEMANGLER
-/* If already available, do not define at all. Otherwise, define to
+/** If already available, do not define at all. Otherwise, define to
* __func__ if that is available. In all other cases, indicate that no
* information about the present function is available for this compiler.
*/
#cmakedefine __PRETTY_FUNCTION__ @__PRETTY_FUNCTION__@
-/* If the compiler supports it, then this variable is defined to a string
+/** If the compiler supports it, then this variable is defined to a string
* that when written after a function name makes the compiler emit a warning
* whenever this function is used somewhere that its use is deprecated.
*/
* Configured in check_1_cpu_features: *
***************************************/
-/* Defined if the system stores words with the most significant byte first */
+/** Defined if the system stores words with the most significant byte first */
#cmakedefine DEAL_II_WORDS_BIGENDIAN
-/* Equal to 0 in the generic case, equal to 1 if CPU compiled for supports
+/** Equal to 0 in the generic case, equal to 1 if CPU compiled for supports
* SSE2, equal to 2 if CPU compiled for supports AVX
*/
#define DEAL_II_COMPILER_VECTORIZATION_LEVEL @DEAL_II_COMPILER_VECTORIZATION_LEVEL@
* Configured in check_1_cxx_features: *
***************************************/
-/* Defined if the compiler we use supports the C++2011 standard well enough
+/** Defined if the compiler we use supports the C++2011 standard well enough
* to allow using the standard library classes instead of the corresponding
* BOOST classes.
*/
#cmakedefine DEAL_II_WITH_CXX11
#ifdef DEAL_II_WITH_CXX11
-/* Compatibility definition (with naming from deal.II 8.0): */
+/** Compatibility definition (with naming from deal.II 8.0): */
# define DEAL_II_USE_CXX11
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_CAN_USE_CXX11
# define DEAL_II_CAN_USE_CXX1X
#endif
-/* Defined if C++11 is enabled and the standard library supports
+/** Defined if C++11 is enabled and the standard library supports
* template<typename T> std::is_trivially_copyable<T>
*/
#cmakedefine DEAL_II_HAVE_CXX11_IS_TRIVIALLY_COPYABLE
-/* Defined if isnan is available */
+/** Defined if isnan is available */
#cmakedefine HAVE_ISNAN
-/* Defined if _isnan is available */
+/** Defined if _isnan is available */
#cmakedefine HAVE_UNDERSCORE_ISNAN
-/* Defined if std::isfinite is available */
+/** Defined if std::isfinite is available */
#cmakedefine DEAL_II_HAVE_ISFINITE
* Configured in check_1_system_features: *
******************************************/
-/* Defined if you have the <sys/resource.h> header file */
+/** Defined if you have the <sys/resource.h> header file */
#cmakedefine HAVE_SYS_RESOURCE_H
-/* Defined if you have the <sys/time.h> header file. */
+/** Defined if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H
-/* Defined if you have the <sys/times.h> header file. */
+/** Defined if you have the <sys/times.h> header file. */
#cmakedefine HAVE_SYS_TIMES_H
-/* Defined if you have the <sys/types.h> header file. */
+/** Defined if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H
-/* Defined if you have the <unistd.h> header file. */
+/** Defined if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H
-/* Defined if you have the "gethostname" function. */
+/** Defined if you have the "gethostname" function. */
#cmakedefine HAVE_GETHOSTNAME
-/* Defined if you have the "getpid' function. */
+/** Defined if you have the "getpid' function. */
#cmakedefine HAVE_GETPID
-/* Defined if you have the "rand_r" function */
+/** Defined if you have the "rand_r" function */
#cmakedefine HAVE_RAND_R
-/* Defined if you have the "times" function. */
+/** Defined if you have the "times" function. */
#cmakedefine HAVE_TIMES
-/* Defined if you have the "jn" function. */
+/** Defined if you have the "jn" function. */
#cmakedefine HAVE_JN
-/* Defined if deal.II was configured on a native Windows platform. */
+/** Defined if deal.II was configured on a native Windows platform. */
#cmakedefine DEAL_II_MSVC
-/* Disable a bunch of warnings for Microsoft Visual C++. */
+/** Disable a bunch of warnings for Microsoft Visual C++. */
#ifdef _MSC_VER
# pragma warning( disable : 4244 ) /* implied downcasting from double to float */
# pragma warning( disable : 4267 ) /* implied downcasting from size_t to unsigned int */
# pragma warning( disable : 4789 ) /* destination of memory copy is too small */
# pragma warning( disable : 4808 ) /* case 'value' is not a valid value for switch condition of type 'bool */
-/* Also make sure we don't let MS Windows headers define min/max as
+/** Also make sure we don't let MS Windows headers define min/max as
macros, see http://support.microsoft.com/kb/143208 */
# define NOMINMAX
#endif /*_MSC_VER*/
* Configured in check_3_compiler_bugs: *
****************************************/
-/* Defined if we have to work around a bug with some compilers that will not
+/** Defined if we have to work around a bug with some compilers that will not
* allow us to specify a fully specialized class of a template as a friend.
* See the aclocal.m4 file in the top-level directory for a description of
* this bug.
* */
#cmakedefine DEAL_II_TEMPL_SPEC_FRIEND_BUG
-/* Defined if the compiler refuses to allow the explicit specialization of
+/** Defined if the compiler refuses to allow the explicit specialization of
* static member arrays. For the exact failure mode, look at aclocal.m4 in the
* top-level directory.
*/
#cmakedefine DEAL_II_MEMBER_ARRAY_SPECIALIZATION_BUG
-/* Defined if the compiler refuses to allow the explicit specialization of
+/** Defined if the compiler refuses to allow the explicit specialization of
* static member variables.
*/
#cmakedefine DEAL_II_MEMBER_VAR_SPECIALIZATION_BUG
-/* Defined if the compiler does not honor the explicit keyword on template
+/** Defined if the compiler does not honor the explicit keyword on template
* constructors.
*/
#cmakedefine DEAL_II_EXPLICIT_CONSTRUCTOR_BUG
-/* Defined if the compiler has a bug in deducing the type of pointers to const
+/** Defined if the compiler has a bug in deducing the type of pointers to const
* member functions.
*/
#cmakedefine DEAL_II_CONST_MEMBER_DEDUCTION_BUG
-/* Defined if the compiler gets an internal error compiling some code that
+/** Defined if the compiler gets an internal error compiling some code that
* involves boost::bind
*/
#cmakedefine DEAL_II_BOOST_BIND_COMPILER_BUG
-/* Defined if the compiler incorrectly deduces a constexpr as not being a
+/**
+ * Defined if there is no const operator() in the class type returned
+ * by std::bind.
+ */
+#cmakedefine DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+
+/** Defined if the compiler incorrectly deduces a constexpr as not being a
* constant integral expression under certain optimization (notably
* gcc-4.8.1 on Windows and Mac)
*/
#cmakedefine DEAL_II_WITH_ARPACK
#ifdef DEAL_II_WITH_ARPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_ARPACK
#endif
#cmakedefine DEAL_II_WITH_FUNCTIONPARSER
#ifdef DEAL_II_WITH_FUNCTIONPARSER
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_FUNCTIONPARSER
#endif
#cmakedefine DEAL_II_WITH_HDF5
#ifdef DEAL_II_WITH_HDF5
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_HAVE_HDF5
#endif
#cmakedefine DEAL_II_WITH_LAPACK
#ifdef DEAL_II_WITH_LAPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBLAPACK
-
-/* Defined if the corresponding BLAS or LAPACK function is available */
-#cmakedefine HAVE_DAXPY_
-#cmakedefine HAVE_DGEEVX_
-#cmakedefine HAVE_DGEEV_
-#cmakedefine HAVE_DGELSD_
-#cmakedefine HAVE_DGEMM_
-#cmakedefine HAVE_DGEMV_
-#cmakedefine HAVE_DGEQRF_
-#cmakedefine HAVE_DGESDD_
-#cmakedefine HAVE_DGESVD_
-#cmakedefine HAVE_DGETRF_
-#cmakedefine HAVE_DGETRI_
-#cmakedefine HAVE_DGETRS_
-#cmakedefine HAVE_DORGQR_
-#cmakedefine HAVE_DORMQR_
-#cmakedefine HAVE_DSTEV_
-#cmakedefine HAVE_DSYEVX_
-#cmakedefine HAVE_DSYGV_
-#cmakedefine HAVE_DSYGVX_
-#cmakedefine HAVE_DTRTRS_
-#cmakedefine HAVE_SAXPY_
-#cmakedefine HAVE_SGEEVX_
-#cmakedefine HAVE_SGEEV_
-#cmakedefine HAVE_SGELSD_
-#cmakedefine HAVE_SGEMM_
-#cmakedefine HAVE_SGEMV_
-#cmakedefine HAVE_SGEQRF_
-#cmakedefine HAVE_SGESDD_
-#cmakedefine HAVE_SGESVD_
-#cmakedefine HAVE_SGETRF_
-#cmakedefine HAVE_SGETRI_
-#cmakedefine HAVE_SGETRS_
-#cmakedefine HAVE_SORGQR_
-#cmakedefine HAVE_SORMQR_
-#cmakedefine HAVE_SSTEV_
-#cmakedefine HAVE_SSYEVX_
-#cmakedefine HAVE_SSYGV_
-#cmakedefine HAVE_SSYGVX_
-#cmakedefine HAVE_STRTRS_
+# define HAVE_DAXPY_
+# define HAVE_DGEEVX_
+# define HAVE_DGEEV_
+# define HAVE_DGELSD_
+# define HAVE_DGEMM_
+# define HAVE_DGEMV_
+# define HAVE_DGEQRF_
+# define HAVE_DGESDD_
+# define HAVE_DGESVD_
+# define HAVE_DGETRF_
+# define HAVE_DGETRI_
+# define HAVE_DGETRS_
+# define HAVE_DORGQR_
+# define HAVE_DORMQR_
+# define HAVE_DSTEV_
+# define HAVE_DSYEVX_
+# define HAVE_DSYGV_
+# define HAVE_DSYGVX_
+# define HAVE_DTRTRS_
+# define HAVE_SAXPY_
+# define HAVE_SGEEVX_
+# define HAVE_SGEEV_
+# define HAVE_SGELSD_
+# define HAVE_SGEMM_
+# define HAVE_SGEMV_
+# define HAVE_SGEQRF_
+# define HAVE_SGESDD_
+# define HAVE_SGESVD_
+# define HAVE_SGETRF_
+# define HAVE_SGETRI_
+# define HAVE_SGETRS_
+# define HAVE_SORGQR_
+# define HAVE_SORMQR_
+# define HAVE_SSTEV_
+# define HAVE_SSYEVX_
+# define HAVE_SSYGV_
+# define HAVE_SSYGVX_
+# define HAVE_STRTRS_
#endif
#cmakedefine DEAL_II_WITH_METIS
#ifdef DEAL_II_WITH_METIS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_METIS
#endif
#cmakedefine DEAL_II_WITH_MPI
#ifdef DEAL_II_WITH_MPI
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_COMPILER_SUPPORTS_MPI
#endif
#cmakedefine DEAL_II_WITH_MUMPS
#ifdef DEAL_II_WITH_MUMPS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_MUMPS
#endif
+/*************************************************
+ * Configured in configure_functionparser.cmake: *
+ *************************************************/
+
+#cmakedefine DEAL_II_WITH_MUPARSER
+
+
/*****************************************
* Configured in configure_netcdf.cmake: *
*****************************************/
#cmakedefine DEAL_II_WITH_NETCDF
#ifdef DEAL_II_WITH_NETCDF
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBNETCDF
#endif
#cmakedefine DEAL_II_WITH_P4EST
#ifdef DEAL_II_WITH_P4EST
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_P4EST
# define DEAL_II_P4EST_VERSION_MAJOR @P4EST_VERSION_MAJOR@
#cmakedefine DEAL_II_WITH_PETSC
#ifdef DEAL_II_WITH_PETSC
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_PETSC
#endif
#cmakedefine DEAL_II_WITH_SLEPC
#ifdef DEAL_II_WITH_SLEPC
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_SLEPC
#endif
#cmakedefine DEAL_II_WITH_THREADS
#ifdef DEAL_II_WITH_THREADS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_MT
#endif
*/
#cmakedefine DEAL_II_USE_MT_POSIX
-/* Defined if POSIX is supported but not the newer POSIX barrier functions.
+/** Defined if POSIX is supported but not the newer POSIX barrier functions.
* Barriers will then not work in the library, but the other threading
* functionality is available.
*/
#cmakedefine DEAL_II_WITH_ZLIB
#ifdef DEAL_II_WITH_ZLIB
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBZ
#endif
#cmakedefine DEAL_II_WITH_TRILINOS
#ifdef DEAL_II_WITH_TRILINOS
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define DEAL_II_USE_TRILINOS
+
+# define DEAL_II_TRILINOS_VERSION_MAJOR @TRILINOS_VERSION_MAJOR@
+# define DEAL_II_TRILINOS_VERSION_MINOR @TRILINOS_VERSION_MINOR@
+# define DEAL_II_TRILINOS_VERSION_SUBMINOR @TRILINOS_VERSION_SUBMINOR@
+
+# define DEAL_II_TRILINOS_VERSION_GTE(major,minor,subminor) \
+ ((DEAL_II_TRILINOS_VERSION_MAJOR * 10000 + \
+ DEAL_II_TRILINOS_VERSION_MINOR * 100 + \
+ DEAL_II_TRILINOS_VERSION_SUBMINOR) \
+ >= \
+ (major)*10000 + (minor)*100 + (subminor))
#endif
#cmakedefine DEAL_II_WITH_UMFPACK
#ifdef DEAL_II_WITH_UMFPACK
-/* Compatibility definition (with naming from deal.II < 8.0): */
+/** Compatibility definition (with naming from deal.II < 8.0): */
# define HAVE_LIBUMFPACK
#endif
Table<2,float> data;
/**
- * Bool flag indicating, whether the coordinates of the inner
- * patch points are appended to the @p data table (@p true) or not
- * (@p false), where the second is the standard and can be found
- * for all cells in the interior of a domain.
+ * A flag indicating whether the coordinates of the interior patch points
+ * (assuming that the patch is supposed to be subdivided further) are
+ * appended to the @p data table (@p true) or not (@p false). The latter
+ * is the default and in this case the locations of the points interior to
+ * this patch are computed by (bi-, tri-)linear interpolation from the
+ * vertices of the patch.
*
- * On the boundary of a domain, patch points are evaluated using a
- * Mapping and therefore have to be stored inside the patch, as
- * the Mapping and the corresponding boundary information are no
- * longer available later on when we actually write the patch out
- * to an output stream.
+ * This option exists since patch points may be evaluated using a Mapping
+ * (rather than by a linear interpolation) and therefore have to be stored
+ * in the Patch structure.
*/
bool points_are_available;
/**
- * Default constructor. Sets #n_subdivisions to one.
+ * Default constructor. Sets #n_subdivisions to one, #points_are_available
+ * to false, and #patch_index to #no_neighbor.
*/
Patch ();
* need a <code>.pvtu</code> file that describes which VTU files form
* a group. The DataOutInterface::write_pvtu_record() function can
* generate such a master record. Likewise,
- * DataOutInterface::write_visit_record() does the same for VisIt.
+ * DataOutInterface::write_visit_record() does the same for VisIt
+ * (although VisIt can also read <code>pvtu</code> records since version 2.5.1).
* Finally, for time dependent problems, you may also want to look
* at DataOutInterface::write_pvd_record()
*
* function can generate such a
* master record. Likewise,
* DataOutInterface::write_visit_record()
- * does the same for VisIt. Finally,
- * DataOutInterface::write_pvd_record()
- * can be used to group together
- * the files that jointly make up
- * a time dependent simulation.
+ * does the same for older versions of VisIt
+ * (although VisIt can also read <code>pvtu</code> records since version 2.5.1).
+ * Finally, DataOutInterface::write_pvd_record()
+ * can be used to group together
+ * the files that jointly make up
+ * a time dependent simulation.
*/
void write_vtu (std::ostream &out) const;
* @note The use of this function is
* explained in step-40.
*
- * @note In order to tell Paraview to
- * group together multiple <code>pvtu</code>
- * files that each describe one time
- * step of a time dependent simulation,
- * see the
+ * @note In order to tell Paraview to
+ * group together multiple <code>pvtu</code>
+ * files that each describe one time
+ * step of a time dependent simulation,
+ * see the
* DataOutInterface::write_pvd_record()
- * function.
- *
- * @note At the time of writing,
- * the other big VTK-based
- * visualization program, VisIt,
+ * function.
+ *
+ * @note Older versions of VisIt (before 2.5.1),
* can not read <code>pvtu</code>
* records. However, it can read
* visit records as written by
/**
* This function is the exact equivalent of the write_pvtu_record()
- * function but for the VisIt visualization program and for one visualization graph
+ * function but for older versions of the VisIt visualization program and for one visualization graph
* (or one time step only). See there for the purpose of this function.
*
* This function is documented in the "Creating a master file for
*
* <tt>values</tt> shall have the right size beforehand, i.e.
* #n_components.
+ *
+ * The default implementation will call value() for each component.
*/
virtual void vector_value (const Point<dim> &p,
Vector<double> &values) const;
#include <deal.II/base/function.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/point.h>
+#include <deal.II/base/thread_local_storage.h>
#include <vector>
#include <map>
-namespace fparser
+namespace mu
{
- class FunctionParser;
+ class Parser;
}
DEAL_II_NAMESPACE_OPEN
/**
* This class implements a function object that gets its value by parsing a
- * string describing this function. It is a wrapper class for the fparser
- * library (see http://warp.povusers.org/FunctionParser/). This class
- * lets you evaluate strings such as "sqrt(1-x^2+y^2)" for given values of
- * 'x' and 'y'. Some of the information contained here is copied verbatim
- * from the fparser.txt file that comes with the fparser library. Please refer
- * also to that file both for clarifications on how this wrapper works, as
- * well as for any issue regarding the license that applies to this class.
- * This class is used in the step-33 and step-36
- * tutorial programs (the latter being much simpler to understand).
- *
- * By using this class you indicate that you accept the terms of the license
- * that comes with the fparser library. If you do not agree with them, you
- * should not use this class or configure the deal.II library without the
- * function parser (see the ReadMe file of deal.II on instructions for this).
- *
- * The following example shows how to use this class:
+ * string describing this function. It is a wrapper class for the muparser
+ * library (see http://muparser.beltoforion.de/). This class lets you evaluate
+ * strings such as "sqrt(1-x^2+y^2)" for given values of 'x' and 'y'. Please
+ * refer to the muparser documentation for more information. This class is
+ * used in the step-33 and step-36 tutorial programs (the latter being much
+ * simpler to understand).
+ *
+ * The following examples shows how to use this class:
* @code
- // Define some constants that will be used by the function parser
- std::map<std::string,double> constants;
- constants["pi"] = numbers::PI;
-
- // Define the variables that will be used inside the expressions
- std::string variables = "x,y,z";
-
- // Define the expressions of the individual components of a
- // vector valued function with two components:
- std::vector<std::string> expressions(2);
- expressions[0] = "sin(2*pi*x)+sinh(pi*z)";
- expressions[1] = "sin(2*pi*y)*exp(x^2)";
-
- // Generate an empty function for these two components.
- ParsedFunction<3> vector_function(2);
-
- // And populate it with the newly created objects.
- vector_function.initialize(variables,
- expressions,
- constants);
- @endcode
-
- * FunctionParser also provides an option to use <b>units</b> in expressions.
- * We illustrate the use of this functionality with the following example:
+ * // set up problem:
+ * std::string variables = "x,y";
+ * std::string expression = "cos(x)+sqrt(y)";
+ * std::map<std::string,double> constants;
+ *
+ * // FunctionParser with 2 variables and 1 component:
+ * FunctionParser<2> fp(1);
+ * fp.initialize(variables,
+ * expression,
+ * constants);
+ *
+ * // Point at which we want to evaluate the function
+ * Point<2> point(0.0, 4.0);
+ *
+ * // evaluate the expression at 'point':
+ * double result = fp.value(point);
+ *
+ * deallog << "Function '" << expression << "'"
+ * << " @ " << point
+ * << " is " << result << std::endl;
+ * @endcode
+ * The second example is a bit more complex:
* @code
- // Define some constants that will be used by the function parser
- std::map<std::string> constants;
- std::map<std::string> units;
- constants["PI"] = numbers::PI;
- units["cm"] = 10;
- units["m"] = 1000;
-
- // Define the variables that will be used inside the expressions
- std::string variables = "x,y";
-
- // Define the expressions of the individual components of a
- // vector valued function with two components:
- std::vector<std::string> expressions(1);
- expressions[0] = "x cm + y m + PI cm";
-
- // Generate an empty function for these two components.
- FunctionParser<2> vector_function;
-
- // And populate it with the newly created objects.
- vector_function.initialize(variables,
- expressions,
- constants,
- units); //An extra argument here
-
- // Point at which we want to evaluate the function
- Point<2> point(2.0, 3.0);
-
- // Output the evaluated function
- std::cout << "Function " << "[" << expressions[0] << "]" <<
- " @point " << "[" << point << "]" << " is " <<
- "[" << vector_function.value(point) << "]" << std::endl;
-
+ * // Define some constants that will be used by the function parser
+ * std::map<std::string,double> constants;
+ * constants["pi"] = numbers::PI;
+ *
+ * // Define the variables that will be used inside the expressions
+ * std::string variables = "x,y,z";
+ *
+ * // Define the expressions of the individual components of a
+ * // vector valued function with two components:
+ * std::vector<std::string> expressions(2);
+ * expressions[0] = "sin(2*pi*x)+sinh(pi*z)";
+ * expressions[1] = "sin(2*pi*y)*exp(x^2)";
+ *
+ * // function parser with 3 variables and 2 components
+ * FunctionParser<3> vector_function(2);
+ *
+ * // And populate it with the newly created objects.
+ * vector_function.initialize(variables,
+ * expressions,
+ * constants);
+ *
+ * // Point at which we want to evaluate the function
+ * Point<3> point(0.0, 1.0, 1.0);
+ *
+ * // This Vector will store the result
+ * Vector<double> result(2);
+ *
+ * // Fill 'result' by evaluating the function
+ * vector_function.vector_value(point, result);
+ *
+ * // We can also only evaluate the 2nd component:
+ * double c = vector_function.value(point, 1);
+ *
+ * // Output the evaluated function
+ * deallog << "Function '" << expressions[0] << "," << expressions[1] << "'"
+ * << " @ " << point
+ * << " is " << result << std::endl;
* @endcode
*
- * Units are similar to <b>constants</b> in the way they are passed to the
- * parser, i.e. via std::map<std::string,double>. But units are slightly different
- * in that they have a higher precedence than any other operator
- * (except parentheses). Thus for example "5/2in" is parsed as "5/(2*300)".
- * (If you actually do want 5/2 inches, it has to be written as "(5/2)in".)
- *
- * Overall, the main point of units is to make input expressions more readable
- * since expressing, say, length as 10cm looks more natural than 10*cm.
- *
- * Beware that the user has full control over units as well as full
- * responsibility for "sanity" of the parsed expressions, because the parser
- * does NOT know anything about the physical nature of units and one would not
- * be warned when adding kilometers to kilograms.
- *
- * The <b>units</b> argument to the initialize function is <b>optional</b>, i.e. the
- * user does NOT have to use this functionality.
- *
- * For more information on this feature, please see
- * contrib/functionparser/fparser.txt
-
-
- *
- * See http://warp.povusers.org/FunctionParser/ for an
- * explanation on how the underlying library works.
- *
-
- From the fparser.txt file:
- @verbatim
-
- The library is intended to be very fast. It byte-compiles the
- function string at parse time and interprets this byte-code at
- evaluation time. The evaluation is straightforward and no recursions
- are done (uses stack arithmetic). Empirical tests show that it indeed
- is very fast (specially compared to libraries which evaluate functions
- by just interpreting the raw function string).
-
- @endverbatim
- *
- * This class overloads the virtual methods value() and
- * vector_value() of the Function base class with the byte compiled versions
- * of the expressions given to the initialize() methods. Note that the class
- * will not work unless you first call the initialize() method that accepts
- * the text description of the function as an argument (among other
- * things). The reason for this is that this text description may be read from
- * an input file, and may therefore not be available at object construction
- * time yet.
- *
- * The syntax to describe a function follows usual programming practice,
- * and is explained in this snippet from the fparser.txt file:
- @verbatim
- The function string understood by the class is very similar to the C-syntax.
- Arithmetic float expressions can be created from float literals, variables
- or functions using the following operators in this order of precedence:
-
- () expressions in parentheses first
- -A unary minus
- A^B exponentiation (A raised to the power B)
- A*B A/B A%B multiplication, division and modulo
- A+B A-B addition and subtraction
- A=B A<B A>B comparison between A and B (result is either 0 or 1)
- A&B result is 1 if int(A) and int(B) differ from 0, else 0.
- A|B result is 1 if int(A) or int(B) differ from 0, else 0.
-
- Since the unary minus has higher precedence than any other operator, for
- example the following expression is valid: x*-y
- Note that the '=' comparison can be inaccurate due to floating point
- precision problems (eg. "sqrt(100)=10" probably returns 0, not 1).
-
- The class supports these functions:
-
- abs(A) : Absolute value of A. If A is negative, returns -A otherwise
- returns A.
- acos(A) : Arc-cosine of A. Returns the angle, measured in radians,
- whose cosine is A.
- acosh(A) : Same as acos() but for hyperbolic cosine.
- asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose
- sine is A.
- asinh(A) : Same as asin() but for hyperbolic sine.
- atan(A) : Arc-tangent of (A). Returns the angle, measured in radians,
- whose tangent is (A).
- atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is
- that it will return the right angle depending on the signs of
- A and B (atan() can only return values between -pi/2 and pi/2),
- and that the return value of pi/2 and -pi/2 are possible.
- atanh(A) : Same as atan() but for hyperbolic tangent.
- ceil(A) : Ceiling of A. Returns the smallest integer greater than A.
- Rounds up to the next higher integer.
- cos(A) : Cosine of A. Returns the cosine of the angle A, where A is
- measured in radians.
- cosh(A) : Same as cos() but for hyperbolic cosine.
- cot(A) : Cotangent of A (equivalent to 1/tan(A)).
- csc(A) : Cosecant of A (equivalent to 1/sin(A)).
- eval(...) : This a recursive call to the function to be evaluated. The
- number of parameters must be the same as the number of parameters
- taken by the function. Usually called inside if() to avoid
- infinite recursion.
- exp(A) : Exponential of A. Returns the value of e raised to the power
- A where e is the base of the natural logarithm, i.e. the
- non-repeating value approximately equal to 2.71828182846.
- floor(A) : Floor of A. Returns the largest integer less than A. Rounds
- down to the next lower integer.
- if(A,B,C) : If int(A) differs from 0, the return value of this function is B,
- else C. Only the parameter which needs to be evaluated is
- evaluated, the other parameter is skipped; this makes it safe to
- use eval() in them.
- int(A) : Rounds A to the closest integer. 0.5 is rounded to 1.
- log(A) : Natural (base e) logarithm of A.
- log10(A) : Base 10 logarithm of A.
- max(A,B) : If A>B, the result is A, else B.
- min(A,B) : If A<B, the result is A, else B.
- sec(A) : Secant of A (equivalent to 1/cos(A)).
- sin(A) : Sine of A. Returns the sine of the angle A, where A is
- measured in radians.
- sinh(A) : Same as sin() but for hyperbolic sine.
- sqrt(A) : Square root of A. Returns the value whose square is A.
- tan(A) : Tangent of A. Returns the tangent of the angle A, where A
- is measured in radians.
- tanh(A) : Same as tan() but for hyperbolic tangent.
-
-
- Examples of function string understood by the class:
-
- "1+2"
- "x-1"
- "-sin(sqrt(x^2+y^2))"
- "sqrt(XCoord*XCoord + YCoord*YCoord)"
-
- An example of a recursive function is the factorial function:
-
- "if(n>1, n*eval(n-1), 1)"
-
- Note that a recursive call has some overhead, which makes it a bit slower
- than any other operation. It may be a good idea to avoid recursive functions
- in very time-critical applications. Recursion also takes some memory, so
- extremely deep recursions should be avoided (eg. millions of nested recursive
- calls).
-
- Also note that the if() function is the only place where making a recursive
- call is safe. In any other place it will cause an infinite recursion (which
- will make the program eventually run out of memory).
- @endverbatim
+ * This class overloads the virtual methods value() and vector_value() of the
+ * Function base class with the byte compiled versions of the expressions
+ * given to the initialize() methods. Note that the class will not work unless
+ * you first call the initialize() method that accepts the text description of
+ * the function as an argument (among other things).
+ *
+ * The syntax to describe a function follows usual programming practice, and
+ * is explained in this snippet from the fparser.txt file:
+ * @verbatim
+ * The function string understood by the class is very similar to the C-syntax.
+ * Arithmetic float expressions can be created from float literals, variables
+ * or functions using the following operators in this order of precedence:
+ *
+ * -A unary minus
+ * A^B exponentiation (A raised to the power B)
+ * A*B A/B A%B multiplication, division and modulo
+ * A+B A-B addition and subtraction
+ * A==B A<B A>B comparison between A and B (result is either 0 or 1)
+ * A&&B A||B logical 'and' and 'or'
+ * A&B A|B same, implemented for compatibility
+ *
+ * Since the unary minus has higher precedence than any other operator, for
+ * example the following expression is valid: x*-y
+ *
+ * Note that the '==' comparison can be inaccurate due to floating point
+ * precision problems, so it should be avoided (eg. "sqrt(100)=10" probably
+ * returns 0, not 1).
+ *
+ * The class supports these functions:
+ *
+ * abs(A) : Absolute value of A. If A is negative, returns -A otherwise
+ * returns A.
+ * acos(A) : Arc-cosine of A. Returns the angle, measured in radians,
+ * whose cosine is A.
+ * acosh(A) : Same as acos() but for hyperbolic cosine.
+ * asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose
+ * sine is A.
+ * asinh(A) : Same as asin() but for hyperbolic sine.
+ * atan(A) : Arc-tangent of (A). Returns the angle, measured in radians,
+ * whose tangent is (A).
+ * atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is
+ * that it will return the right angle depending on the signs of
+ * A and B (atan() can only return values between -pi/2 and pi/2),
+ * and that the return value of pi/2 and -pi/2 are possible.
+ * atanh(A) : Same as atan() but for hyperbolic tangent.
+ * ceil(A) : Ceiling of A. Returns the smallest integer greater than A.
+ * Rounds up to the next higher integer.
+ * cos(A) : Cosine of A. Returns the cosine of the angle A, where A is
+ * measured in radians.
+ * cosh(A) : Same as cos() but for hyperbolic cosine.
+ * cot(A) : Cotangent of A (equivalent to 1/tan(A)).
+ * csc(A) : Cosecant of A (equivalent to 1/sin(A)).
+ * exp(A) : Exponential of A. Returns the value of e raised to the power
+ * A where e is the base of the natural logarithm, i.e. the
+ * non-repeating value approximately equal to 2.71828182846.
+ * floor(A) : Floor of A. Returns the largest integer less than A. Rounds
+ * down to the next lower integer.
+ * if(A,B,C) : If int(A) differs from 0, the return value of this function is B,
+ * else C. Only the parameter which needs to be evaluated is
+ * evaluated, the other parameter is skipped; this makes it safe to
+ * use eval() in them.
+ * int(A) : Rounds A to the closest integer. 0.5 is rounded to 1.
+ * log(A) : Natural (base e) logarithm of A.
+ * log10(A) : Base 10 logarithm of A.
+ * max(A,B) : If A>B, the result is A, else B.
+ * min(A,B) : If A<B, the result is A, else B.
+ * sec(A) : Secant of A (equivalent to 1/cos(A)).
+ * sin(A) : Sine of A. Returns the sine of the angle A, where A is
+ * measured in radians.
+ * sinh(A) : Same as sin() but for hyperbolic sine.
+ * sqrt(A) : Square root of A. Returns the value whose square is A.
+ * tan(A) : Tangent of A. Returns the tangent of the angle A, where A
+ * is measured in radians.
+ * tanh(A) : Same as tan() but for hyperbolic tangent.
+ *
+ *
+ * Examples of function string understood by the class:
+ *
+ * "1+2"
+ * "x-1"
+ * "-sin(sqrt(x^2+y^2))"
+ * "sqrt(XCoord*XCoord + YCoord*YCoord)"
+ * @endverbatim
+ *
+ * For a wrapper of the FunctionParser class that supports ParameterHandler,
+ * see ParsedFunction.
*
* Vector-valued functions can either be declared using strings where the
* function components are separated by semicolons, or using a vector of
* strings each defining one vector component.
*
* An example of time dependent scalar function is the following:
- @code
-
- // Empty constants object
- std::map<std::string> constants;
-
- // Variables that will be used inside the expressions
- std::string variables = "x,y,t";
-
- // Define the expression of the scalar time dependent function.
- std::string expression = "exp(y*x)*exp(-t)";
-
- // Generate an empty scalar function
- FunctionParser<2> function;
-
- // And populate it with the newly created objects.
- function.initialize(variables,
- expression,
- constants,
- true); // This tells the parser that
- // it is a time-dependent function
- // and there is another variable
- // to be taken into account (t).
-
- @endcode
-
- * The following is another example of how to instantiate a
- * vector valued function by using a single string:
- @code
-
- // Empty constants object
- std::map<std::string> constants;
-
- // Variables that will be used inside the expressions
- std::string variables = "x,y";
-
- // Define the expression of the vector valued function.
- std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)";
-
- // Generate an empty vector valued function
- FunctionParser<2> function(2);
-
- // And populate it with the newly created objects.
- function.initialize(variables,
- expression,
- constants);
-
- @endcode
+ * @code
+ * // Empty constants object
+ * std::map<std::string> constants;
+ *
+ * // Variables that will be used inside the expressions
+ * std::string variables = "x,y,t";
+ *
+ * // Define the expression of the scalar time dependent function.
+ * std::string expression = "exp(y*x)*exp(-t)";
+ *
+ * // Generate an empty scalar function
+ * FunctionParser<2> function;
+ *
+ * // And populate it with the newly created objects.
+ * function.initialize(variables,
+ * expression,
+ * constants,
+ * true); // This tells the parser that
+ * // it is a time-dependent function
+ * // and there is another variable
+ * // to be taken into account (t).
+ * @endcode
+ *
+ * The following is another example of how to instantiate a vector valued
+ * function by using a single string:
+ * @code
+ * // Empty constants object
+ * std::map<std::string> constants;
+ *
+ * // Variables that will be used inside the expressions
+ * std::string variables = "x,y";
+ *
+ * // Define the expression of the vector valued function.
+ * std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)";
+ *
+ * // Generate an empty vector valued function
+ * FunctionParser<2> function(2);
+ *
+ * // And populate it with the newly created objects.
+ * function.initialize(variables,
+ * expression,
+ * constants);
+ * @endcode
*
*
* @ingroup functions
- * @author Luca Heltai, 2005
+ * @author Luca Heltai, Timo Heister 2005, 2014
*/
template <int dim>
class FunctionParser : public Function<dim>
{
-public:
- /**
- * Constructor for Parsed
- * functions. Its arguments are
- * the same of the base class
- * Function. The only difference
- * is that this object needs to
- * be initialized with
- * initialize() method before you
- * can use it. If an attempt to
- * use this function is made
- * before the initialize() method
- * has been called, then an
- * exception is thrown.
- */
- FunctionParser (const unsigned int n_components = 1,
- const double initial_time = 0.0);
-
- /**
- * Destructor. Explicitly delete
- * the FunctionParser objects
- * (there is one for each
- * component of the function).
- */
- ~FunctionParser();
-
- /**
- * Type for the constant
- * map. Used by the initialize()
- * method.
- */
- typedef std::map<std::string, double> ConstMap;
-
- /**
- * Iterator for the constants
- * map. Used by the initialize()
- * method.
- */
- typedef ConstMap::iterator ConstMapIterator;
-
- /**
- * Initialize the function. This methods
- * accepts the following parameters:
- *
- * <b>vars</b>: a string with
- * the variables that will be used by the
- * expressions to be evaluated. Note that
- * the variables can have any name (of
- * course different from the function
- * names defined above!), but the order
- * IS important. The first variable will
- * correspond to the first component of
- * the point in which the function is
- * evaluated, the second variable to the
- * second component and so forth. If this
- * function is also time dependent, then
- * it is necessary to specify it by
- * setting the <tt>time_dependent</tt> parameter
- * to true. An exception is thrown if
- * the number of variables specified here
- * is different from dim (if this
- * function is not time-dependent) or
- * from dim+1 (if it is time-dependent).
- *
- * <b>expressions</b>: a list of strings
- * containing the expressions that will
- * be byte compiled by the internal
- * parser (FunctionParser). Note that the
- * size of this vector must match exactly
- * the number of components of the
- * FunctionParser, as declared in the
- * constructor. If this is not the case,
- * an exception is thrown.
- *
- *
- * <b>constants</b>: a map of constants
- * used to pass any necessary constant
- * that we want to specify in our
- * expressions (in the example above the
- * number pi). An expression is valid if
- * and only if it contains only defined
- * variables and defined constants (other
- * than the functions specified
- * above). If a constant is given whose
- * name is not valid (eg:
- * <tt>constants["sin"] = 1.5;</tt>) an
- * exception is thrown.
- *
- * <b>time_dependent</b>. If this is a
- * time dependent function, then the last
- * variable declared in <b>vars</b> is
- * assumed to be the time variable, and
- * this->get_time() is used to initialize
- * it when evaluating the
- * function. Naturally the number of
- * variables parsed by the initialize()
- * method in this case is dim+1. The
- * value of this parameter defaults to
- * false, i.e. do not consider time.
- *
- * <b>use_degrees</b>. Parameter to
- * decide if the trigonometric functions
- * work in radians or degrees. The
- * default for this parameter is false,
- * i.e. use radians and not degrees.
- */
- void initialize (const std::string &vars,
- const std::vector<std::string> &expressions,
- const ConstMap &constants,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
-
- /**
- * Initialize the function. Same as
- * above, but with an additional argument
- * <b> units </b> - a map of units passed to
- * FunctionParser via AddUnint.
- *
- * Can be used as "3cm".
- * Have higher precedence in parsing, i.e.
- * if cm=10 then 3/2cm is 3 /(2*10).
- * See contrib/functionparser/fparser.txt
- * for more details.
- */
- void initialize (const std::string &vars,
- const std::vector<std::string> &expressions,
- const ConstMap &constants,
- const ConstMap &units,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * Initialize the function. Same as
- * above, but accepts a string rather
- * than a vector of strings. If this is a
- * vector valued function, its
- * components are expected to be
- * separated by a semicolon. An exception
- * is thrown if this method is called and
- * the number of components successfully
- * parsed does not match the number of
- * components of the base function.
- */
- void initialize (const std::string &vars,
- const std::string &expression,
- const ConstMap &constants,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * Initialize the function. Same as
- * above, but with <b>units</b>.
- */
-
- void initialize (const std::string &vars,
- const std::string &expression,
- const ConstMap &constants,
- const ConstMap &units,
- const bool time_dependent = false,
- const bool use_degrees = false);
-
- /**
- * A function that returns
- * default names for variables,
- * to be used in the first
- * argument of the initialize()
- * functions: it returns "x" in
- * 1d, "x,y" in 2d, and "x,y,z"
- * in 3d.
- */
- static
- std::string
- default_variable_names ();
-
- /**
- * Return the value of the
- * function at the given
- * point. Unless there is only
- * one component (i.e. the
- * function is scalar), you
- * should state the component you
- * want to have evaluated; it
- * defaults to zero, i.e. the
- * first component.
- */
- virtual double value (const Point<dim> &p,
- const unsigned int component = 0) const;
-
- /**
- * Return all components of a
- * vector-valued function at the
- * given point @p p.
- *
- * <tt>values</tt> shall have the
- * right size beforehand,
- * i.e. #n_components.
- */
- virtual void vector_value (const Point<dim> &p,
- Vector<double> &values) const;
-
- /** @addtogroup Exceptions
- * @{ */
- DeclException2 (ExcParseError,
- int, char *,
- << "Parsing Error at Column " << arg1
- << ". The parser said: " << arg2);
-
- DeclException2 (ExcInvalidExpressionSize,
- int, int,
- << "The number of components (" << arg1
- << ") is not equal to the number of expressions ("
- << arg2 << ").");
-
- //@}
-private:
- /**
- * A pointer to the actual
- * function parsers. The pointer is
- * to an array of parsers, not
- * just a single one. The length of
- * the array equals the number of
- * vector components.
- */
- fparser::FunctionParser *fp;
-
- /**
- * State of usability. This
- * variable is checked every time
- * the function is called for
- * evaluation. It's set to true
- * in the initialize() methods.
- */
- bool initialized;
-
- /**
- * Number of variables. If this
- * is also a function of time,
- * then the number of variables
- * is dim+1, otherwise it is
- * dim. In the case that this is
- * a time dependent function, the
- * time is supposed to be the
- * last variable. If #n_vars is
- * not identical to the number of
- * the variables parsed by the
- * initialize() method, then an
- * exception is thrown.
- */
- unsigned int n_vars;
+ public:
+ /**
+ * Constructor for Parsed functions. Its arguments are the same of the
+ * base class Function. The only difference is that this object needs to
+ * be initialized with initialize() method before you can use it. If an
+ * attempt to use this function is made before the initialize() method has
+ * been called, then an exception is thrown.
+ */
+ FunctionParser (const unsigned int n_components = 1,
+ const double initial_time = 0.0);
+
+ /**
+ * Destructor. Explicitly delete the FunctionParser objects (there is one
+ * for each component of the function).
+ */
+ ~FunctionParser();
+
+ /**
+ * Type for the constant map. Used by the initialize() method.
+ */
+ typedef std::map<std::string, double> ConstMap;
+
+ /**
+ * Iterator for the constants map. Used by the initialize() method.
+ */
+ typedef ConstMap::iterator ConstMapIterator;
+
+ /**
+ * Initialize the function. This methods accepts the following
+ * parameters:
+ *
+ * <b>vars</b>: a string with the variables that will be used by the
+ * expressions to be evaluated. Note that the variables can have any name
+ * (of course different from the function names defined above!), but the
+ * order IS important. The first variable will correspond to the first
+ * component of the point in which the function is evaluated, the second
+ * variable to the second component and so forth. If this function is also
+ * time dependent, then it is necessary to specify it by setting the
+ * <tt>time_dependent</tt> parameter to true. An exception is thrown if
+ * the number of variables specified here is different from dim (if this
+ * function is not time-dependent) or from dim+1 (if it is time-
+ * dependent).
+ *
+ * <b>expressions</b>: a list of strings containing the expressions that
+ * will be byte compiled by the internal parser (FunctionParser). Note
+ * that the size of this vector must match exactly the number of
+ * components of the FunctionParser, as declared in the constructor. If
+ * this is not the case, an exception is thrown.
+ *
+ *
+ * <b>constants</b>: a map of constants used to pass any necessary
+ * constant that we want to specify in our expressions (in the example
+ * above the number pi). An expression is valid if and only if it contains
+ * only defined variables and defined constants (other than the functions
+ * specified above). If a constant is given whose name is not valid (eg:
+ * <tt>constants["sin"] = 1.5;</tt>) an exception is thrown.
+ *
+ * <b>time_dependent</b>. If this is a time dependent function, then the
+ * last variable declared in <b>vars</b> is assumed to be the time
+ * variable, and this->get_time() is used to initialize it when evaluating
+ * the function. Naturally the number of variables parsed by the
+ * initialize() method in this case is dim+1. The value of this parameter
+ * defaults to false, i.e. do not consider time.
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const bool time_dependent = false);
+
+ /**
+ * Same as above, but with an additional parameter: <b>use_degrees</b>.
+ * Parameter to decide if the trigonometric functions work in radians or
+ * degrees. The default for this parameter is false, i.e. use radians and
+ * not degrees.
+ *
+ * @note: this function is deprecated. Use the function without this
+ * argument instead (which has the default use_degrees=false).
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const bool time_dependent,
+ const bool use_degrees) DEAL_II_DEPRECATED;
+
+
+ /**
+ * Initialize the function. Same as above, but with an additional argument
+ * <b> units </b> - a map of units passed to FunctionParser via AddUnint.
+ *
+ * Can be used as "3cm". Have higher precedence in parsing, i.e. if cm=10
+ * then 3/2cm is 3 /(2*10). See contrib/functionparser/fparser.txt for
+ * more details.
+ */
+ void initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const ConstMap &constants,
+ const ConstMap &units,
+ const bool time_dependent = false,
+ const bool use_degrees = false) DEAL_II_DEPRECATED;
+
+ /**
+ * Initialize the function. Same as above, but accepts a string rather
+ * than a vector of strings. If this is a vector valued function, its
+ * components are expected to be separated by a semicolon. An exception is
+ * thrown if this method is called and the number of components
+ * successfully parsed does not match the number of components of the base
+ * function.
+ */
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const bool time_dependent = false);
+
+ /**
+ * Same as above, but with an additional parameter: <b>use_degrees</b>.
+ * Parameter to decide if the trigonometric functions work in radians or
+ * degrees. The default for this parameter is false, i.e. use radians and
+ * not degrees.
+ *
+ * @note: this function is deprecated. Use the function without this
+ * argument instead (which has the default use_degrees=false).
+ */
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const bool time_dependent,
+ const bool use_degrees) DEAL_II_DEPRECATED;
+ /**
+ * Initialize the function. Same as above, but with <b>units</b>.
+ */
+
+ void initialize (const std::string &vars,
+ const std::string &expression,
+ const ConstMap &constants,
+ const ConstMap &units,
+ const bool time_dependent = false,
+ const bool use_degrees = false) DEAL_II_DEPRECATED;
+
+ /**
+ * A function that returns default names for variables, to be used in the
+ * first argument of the initialize() functions: it returns "x" in 1d,
+ * "x,y" in 2d, and "x,y,z" in 3d.
+ */
+ static
+ std::string
+ default_variable_names ();
+
+ /**
+ * Return the value of the function at the given point. Unless there is
+ * only one component (i.e. the function is scalar), you should state the
+ * component you want to have evaluated; it defaults to zero, i.e. the
+ * first component.
+ */
+ virtual double value (const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ /**
+ * Return all components of a vector-valued function at the given point @p
+ * p.
+ *
+ * <tt>values</tt> shall have the right size beforehand, i.e.
+ * #n_components.
+ */
+ virtual void vector_value (const Point<dim> &p,
+ Vector<double> &values) const;
+
+ /**
+ * @addtogroup Exceptions
+ * @{
+ */
+ DeclException2 (ExcParseError,
+ int, char *,
+ << "Parsing Error at Column " << arg1
+ << ". The parser said: " << arg2);
+
+ DeclException2 (ExcInvalidExpressionSize,
+ int, int,
+ << "The number of components (" << arg1
+ << ") is not equal to the number of expressions ("
+ << arg2 << ").");
+
+ //@}
+ private:
+#ifdef DEAL_II_WITH_MUPARSER
+ /**
+ * place for the variables for each thread
+ */
+ mutable Threads::ThreadLocalStorage<std::vector<double> > vars;
+ /**
+ * the muParser objects for each thread (and one for each component)
+ */
+ mutable Threads::ThreadLocalStorage<std::vector<mu::Parser> > fp;
+
+ /**
+ * keep track of all the constants, required to initialize fp in each
+ * thread
+ */
+ std::map< std::string, double > constants;
+ /**
+ * variable names, required to initialize fp in each thread
+ */
+ std::vector<std::string> var_names;
+ /**
+ * the expressions, required to initialize fp in each thread
+ */
+ std::vector<std::string> expressions;
+ /**
+ * this function will initialize fp on the current thread
+ */
+ void init_muparser() const;
+#endif
+
+ /**
+ * State of usability. This variable is checked every time the function is
+ * called for evaluation. It's set to true in the initialize() methods.
+ */
+ bool initialized;
+
+ /**
+ * Number of variables. If this is also a function of time, then the
+ * number of variables is dim+1, otherwise it is dim. In the case that
+ * this is a time dependent function, the time is supposed to be the last
+ * variable. If #n_vars is not identical to the number of the variables
+ * parsed by the initialize() method, then an exception is thrown.
+ */
+ unsigned int n_vars;
};
FunctionParser<dim>::default_variable_names ()
{
switch (dim)
- {
- case 1:
- return "x";
- case 2:
- return "x,y";
- case 3:
- return "x,y,z";
- default:
- Assert (false, ExcNotImplemented());
- }
+ {
+ case 1:
+ return "x";
+ case 2:
+ return "x,y";
+ case 3:
+ return "x,y,z";
+ default:
+ Assert (false, ExcNotImplemented());
+ }
return "";
}
/**
* Constructs the IndexSet from a text based representation given by the
- * stream @param in written by the write() function.
+ * stream @p in written by the write() function.
*/
void read(std::istream &in);
/**
* Constructs the IndexSet from a binary representation given by the stream
- * @param in written by the write_block() function.
+ * @p in written by the write_block() function.
*/
void block_read(std::istream &in);
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
DEAL_II_NAMESPACE_OPEN
+// forward declaration
+template <typename T> class VectorizedArray;
+
+
/**
* This namespace provides functions helping to determine the amount
* of memory used by objects. The goal is not necessarily to give the
inline
std::size_t memory_consumption (const std::complex<T> &);
+ /**
+ * Determine the amount of memory in bytes consumed by a
+ * <tt>VectorizedArray</tt> variable.
+ */
+ template <typename T>
+ inline
+ std::size_t memory_consumption (const VectorizedArray<T> &);
+
/**
* Determine an estimate of the
* amount of memory in bytes
}
+
template <typename T>
inline
std::size_t memory_consumption (const std::complex<T> &)
+ template <typename T>
+ inline
+ std::size_t memory_consumption (const VectorizedArray<T> &)
+ {
+ return sizeof(VectorizedArray<T>);
+ }
+
+
+
inline
std::size_t memory_consumption (const std::string &s)
{
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
namespace Utilities
{
/**
- * A namespace for utility functions that
- * abstract certain operations using the
- * Message Passing Interface (MPI) or
- * provide fallback operations in
- * case deal.II is configured not to use
- * MPI at all.
+ * A namespace for utility functions that abstract certain operations using
+ * the Message Passing Interface (MPI) or provide fallback operations in
+ * case deal.II is configured not to use MPI at all.
*
* @ingroup utilities
*/
namespace MPI
{
/**
- * Return the number of MPI processes
- * there exist in the given communicator
- * object. If this is a sequential job,
- * it returns 1.
+ * Return the number of MPI processes there exist in the given
+ * communicator object. If this is a sequential job, it returns 1.
*/
unsigned int n_mpi_processes (const MPI_Comm &mpi_communicator);
/**
- * Return the number of the present MPI
- * process in the space of processes
- * described by the given
- * communicator. This will be a unique
- * value for each process between zero
- * and (less than) the number of all
- * processes (given by
- * get_n_mpi_processes()).
+ * Return the number of the present MPI process in the space of processes
+ * described by the given communicator. This will be a unique value for
+ * each process between zero and (less than) the number of all processes
+ * (given by get_n_mpi_processes()).
*/
unsigned int this_mpi_process (const MPI_Comm &mpi_communicator);
/**
- * Consider an unstructured
- * communication pattern where
- * every process in an MPI
- * universe wants to send some
- * data to a subset of the other
- * processors. To do that, the
- * other processors need to know
- * who to expect messages
- * from. This function computes
- * this information.
+ * Consider an unstructured communication pattern where every process in
+ * an MPI universe wants to send some data to a subset of the other
+ * processors. To do that, the other processors need to know who to expect
+ * messages from. This function computes this information.
*
- * @param mpi_comm A communicator
- * that describes the processors
- * that are going to communicate
- * with each other.
+ * @param mpi_comm A communicator that describes the processors that are
+ * going to communicate with each other.
*
- * @param destinations The list
- * of processors the current
- * process wants to send
- * information to. This list need
- * not be sorted in any way. If
- * it contains duplicate entries
- * that means that multiple
- * messages are intended for a
- * given destination.
+ * @param destinations The list of processors the current process wants to
+ * send information to. This list need not be sorted in any way. If it
+ * contains duplicate entries that means that multiple messages are
+ * intended for a given destination.
*
- * @return A list of processors
- * that have indicated that they
- * want to send something to the
- * current processor. The
- * resulting list is not
- * sorted. It may contain
- * duplicate entries if
- * processors enter the same
- * destination more than once in
- * their destinations list.
+ * @return A list of processors that have indicated that they want to send
+ * something to the current processor. The resulting list is not sorted.
+ * It may contain duplicate entries if processors enter the same
+ * destination more than once in their destinations list.
*/
std::vector<unsigned int>
compute_point_to_point_communication_pattern (const MPI_Comm &mpi_comm,
const std::vector<unsigned int> &destinations);
/**
- * Given a communicator, generate a new
- * communicator that contains the same
- * set of processors but that has a
- * different, unique identifier.
+ * Given a communicator, generate a new communicator that contains the
+ * same set of processors but that has a different, unique identifier.
*
- * This functionality can be used to
- * ensure that different objects, such as
- * distributed matrices, each have unique
- * communicators over which they can
- * interact without interfering with each
- * other.
+ * This functionality can be used to ensure that different objects, such
+ * as distributed matrices, each have unique communicators over which they
+ * can interact without interfering with each other.
*
- * When no longer needed, the
- * communicator created here needs to
- * be destroyed using
- * <code>MPI_Comm_free</code>.
+ * When no longer needed, the communicator created here needs to be
+ * destroyed using <code>MPI_Comm_free</code>.
*/
MPI_Comm duplicate_communicator (const MPI_Comm &mpi_communicator);
/**
- * Return the sum over all processors of the value @p t. This function
- * is collective over all processors given in the communicator. If
- * deal.II is not configured for use of MPI, this function simply
- * returns the value of @p t. This function corresponds to the
- * <code>MPI_Allreduce</code> function, i.e. all processors receive
- * the result of this operation.
+ * Return the sum over all processors of the value @p t. This function is
+ * collective over all processors given in the communicator. If deal.II is
+ * not configured for use of MPI, this function simply returns the value
+ * of @p t. This function corresponds to the <code>MPI_Allreduce</code>
+ * function, i.e. all processors receive the result of this operation.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*
- * @note This function is only implemented for certain template
- * arguments <code>T</code>, namely <code>float, double, int,
- * unsigned int</code>.
+ * @note This function is only implemented for certain template arguments
+ * <code>T</code>, namely <code>float, double, int, unsigned int</code>.
*/
template <typename T>
T sum (const T &t,
const MPI_Comm &mpi_communicator);
/**
- * Like the previous function,
- * but take the sums over the
- * elements of an array
- * of length N. In other words,
- * the i-th element of the
- * results array is the sum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the sums over the elements of an
+ * array of length N. In other words, the i-th element of the results
+ * array is the sum over the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T, unsigned int N>
inline
T (&sums)[N]);
/**
- * Like the previous function,
- * but take the sums over the
- * elements of a std::vector. In other words,
- * the i-th element of the
- * results array is the sum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the sums over the elements of a
+ * std::vector. In other words, the i-th element of the results array is
+ * the sum over the i-th entries of the input arrays from each processor.
*/
template <typename T>
inline
/**
* Return the maximum over all processors of the value @p t. This function
- * is collective over all processors given in the communicator. If
- * deal.II is not configured for use of MPI, this function simply
- * returns the value of @p t. This function corresponds to the
- * <code>MPI_Allreduce</code> function, i.e. all processors receive
- * the result of this operation.
+ * is collective over all processors given in the communicator. If deal.II
+ * is not configured for use of MPI, this function simply returns the
+ * value of @p t. This function corresponds to the
+ * <code>MPI_Allreduce</code> function, i.e. all processors receive the
+ * result of this operation.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*
- * @note This function is only implemented for certain template
- * arguments <code>T</code>, namely <code>float, double, int,
- * unsigned int</code>.
+ * @note This function is only implemented for certain template arguments
+ * <code>T</code>, namely <code>float, double, int, unsigned int</code>.
*/
template <typename T>
T max (const T &t,
const MPI_Comm &mpi_communicator);
/**
- * Like the previous function,
- * but take the maxima over the
- * elements of an array
- * of length N. In other words,
- * the i-th element of the
- * results array is the maximum of
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the maxima over the elements of an
+ * array of length N. In other words, the i-th element of the results
+ * array is the maximum of the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T, unsigned int N>
inline
T (&maxima)[N]);
/**
- * Like the previous function,
- * but take the maximum over the
- * elements of a std::vector. In other words,
- * the i-th element of the
- * results array is the maximum over
- * the i-th entries of the input
- * arrays from each processor.
+ * Like the previous function, but take the maximum over the elements of a
+ * std::vector. In other words, the i-th element of the results array is
+ * the maximum over the i-th entries of the input arrays from each
+ * processor.
*/
template <typename T>
inline
std::vector<T> &maxima);
/**
- * Data structure to store the result of
- * min_max_avg().
+ * Data structure to store the result of min_max_avg().
*/
struct MinMaxAvg
{
};
/**
- * Returns sum, average, minimum,
- * maximum, processor id of minimum and
- * maximum as a collective operation of
- * on the given MPI communicator @p
- * mpi_communicator . Each processor's
- * value is given in @p my_value and
- * the result will be returned.
- * The result is available on all
- * machines.
+ * Returns sum, average, minimum, maximum, processor id of minimum and
+ * maximum as a collective operation of on the given MPI communicator @p
+ * mpi_communicator . Each processor's value is given in @p my_value and
+ * the result will be returned. The result is available on all machines.
*
- * @note Sometimes, not all processors need a results and in that case
- * one would call the <code>MPI_Reduce</code> function instead of the
+ * @note Sometimes, not all processors need a results and in that case one
+ * would call the <code>MPI_Reduce</code> function instead of the
* <code>MPI_Allreduce</code> function. The latter is at most twice as
* expensive, so if you are concerned about performance, it may be
- * worthwhile investigating whether your algorithm indeed needs the
- * result everywhere or whether you could get away with calling the
- * current function and getting the result everywhere.
+ * worthwhile investigating whether your algorithm indeed needs the result
+ * everywhere or whether you could get away with calling the current
+ * function and getting the result everywhere.
*/
MinMaxAvg
min_max_avg (const double my_value,
/**
- * A class that is used to initialize the
- * MPI system at the beginning of a
- * program and to shut it down again at
- * the end. It also allows you to control
- * the number threads used in each MPI
- * task.
+ * A class that is used to initialize the MPI system at the beginning of a
+ * program and to shut it down again at the end. It also allows you to
+ * control the number threads used in each MPI task.
*
- * If deal.II is configured with PETSc,
- * the library will also be initialized
- * in the beginning and destructed at the
- * end automatically (internally by calling
- * PetscInitialize() and PetscFinalize()).
+ * If deal.II is configured with PETSc, the library will also be
+ * initialized in the beginning and destructed at the end automatically
+ * (internally by calling PetscInitialize() and PetscFinalize()).
*
- * If a program uses MPI one would
- * typically just create an object of
- * this type at the beginning of
- * <code>main()</code>. The constructor
- * of this class then runs
- * <code>MPI_Init()</code> with the given
- * arguments. At the end of the program,
- * the compiler will invoke the
- * destructor of this object which in
- * turns calls <code>MPI_Finalize</code>
- * to shut down the MPI system.
+ * If a program uses MPI one would typically just create an object of this
+ * type at the beginning of <code>main()</code>. The constructor of this
+ * class then runs <code>MPI_Init()</code> with the given arguments. At
+ * the end of the program, the compiler will invoke the destructor of this
+ * object which in turns calls <code>MPI_Finalize</code> to shut down the
+ * MPI system.
*
* This class is used in step-32, for example.
*/
{
public:
/**
- * Constructor. Takes the arguments
- * from the command line (in case of
- * MPI, the number of processes is
- * specified there), and sets up a
- * respective communicator by calling
- * <tt>MPI_Init()</tt>. This
- * constructor can only be called once
- * in a program, since MPI cannot be
+ * Constructor. Takes the arguments from the command line (in case of
+ * MPI, the number of processes is specified there), and sets up a
+ * respective communicator by calling <tt>MPI_Init()</tt>. This
+ * constructor can only be called once in a program, since MPI cannot be
* initialized twice.
*
- * This constructor sets max_num_threads
- * to 1 (see other constructor).
+ * This constructor sets max_num_threads to 1 (see other constructor).
*/
MPI_InitFinalize (int &argc,
char ** &argv) /*DEAL_II_DEPRECATED*/;
/**
- * Initialize MPI (and optionally PETSc)
- * and set the number of threads used by deal.II (and TBB) to the given
- * parameter. If set to numbers::invalid_unsigned_int, the number
- * of threads is determined by TBB. When in doubt, set this value
- * to 1.
+ * Initialize MPI (and optionally PETSc) and set the number of threads
+ * used by deal.II (and TBB) to the given parameter. If set to
+ * numbers::invalid_unsigned_int, the number of threads is determined by
+ * TBB. When in doubt, set this value to 1 since MPI jobs are typically
+ * run in a way where one has one MPI process per available processor
+ * core and there will be little CPU resources left to support multithreaded
+ * processes.
+ *
+ * This function calls MultithreadInfo::set_thread_limit()
+ * unconditionally with @p max_num_threads . That function in turn also
+ * evaluates the environment variable DEAL_II_NUM_THREADS and the number
+ * of threads to be used will be the minimum of the argument passed here
+ * and the environment (if both are set).
*/
MPI_InitFinalize (int &argc,
char ** &argv,
- unsigned int max_num_threads);
+ const unsigned int max_num_threads);
/**
- * Destructor. Calls
- * <tt>MPI_Finalize()</tt> in
- * case this class owns the MPI
- * process.
+ * Destructor. Calls <tt>MPI_Finalize()</tt> in case this class owns the
+ * MPI process.
*/
~MPI_InitFinalize();
private:
/**
- * This flag tells the class
- * whether it owns the MPI
- * process (i.e., it has been
- * constructed using the
- * argc/argv input, or it has
- * been copied). In the former
- * case, the command
- * <tt>MPI_Finalize()</tt> will
+ * This flag tells the class whether it owns the MPI process (i.e., it
+ * has been constructed using the argc/argv input, or it has been
+ * copied). In the former case, the command <tt>MPI_Finalize()</tt> will
* be called at destruction.
*/
const bool owns_mpi;
*/
void do_init(int &argc,
char ** &argv,
- unsigned int max_num_threads);
+ const unsigned int max_num_threads);
};
namespace internal
{
#ifdef DEAL_II_WITH_MPI
/**
- * Return the corresponding MPI data
- * type id for the argument given.
+ * Return the corresponding MPI data type id for the argument given.
*/
inline MPI_Datatype mpi_type_id (const int *)
{
*/
unsigned int n_default_threads DEAL_II_DEPRECATED;
- /*
+ /**
* Returns the number of threads to use. This is governed by the number
* of cores the system has (n_cpus) and can be further restricted by
* set_thread_limit().
DEAL_II_NAMESPACE_OPEN
+class AnyData;
/**
+ * @deprecated The use of this class is deprecated and AnyData should
+ * be used instead. It is not only more flexible, the way constness
+ * was assured in this class never worked the way it was
+ * intended. Therefore, the according checks have been disabled.
+ *
* This class is a collection of DATA objects. Each of the pointers
* has a name associated, enabling identification by this name rather
* than the index in the vector only.
template <typename DATA>
void initialize(const NamedData<DATA> &data);
+ /**
+ * Create the index vector
+ * pointing into the AnyData
+ * object.
+ */
+ void initialize(const AnyData &data);
+
/**
* The number of names in this
* object. This function may be
void
NamedData<DATA>::add(DATA &v, const std::string &n)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
names.push_back(n);
data.push_back(v);
}
void
NamedData<DATA>::add(const DATA &v, const std::string &n)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
DATA &aux = const_cast<DATA &>(v);
data.push_back(aux);
names.push_back(n);
void
NamedData<DATA>::merge(NamedData<DATA2> &other)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
for (unsigned int i=0; i<other.size(); ++i)
{
void
NamedData<DATA>::merge(const NamedData<DATA2> &other)
{
- Assert(!is_constant, ExcConstantObject());
+ // see operator() below
+
+ // Assert(!is_constant, ExcConstantObject());
for (unsigned int i=0; i<other.size(); ++i)
{
names.push_back(other.name(i));
DATA &
NamedData<DATA>::operator() (unsigned int i)
{
- Assert(!is_constant, ExcConstantObject());
+ // Remove this assertion, since is_const() does not really assert
+ // what we would like to. This can only be fixed by using constness
+ // in AnyData.
+
+ // Assert(!is_constant, ExcConstantObject());
AssertIndexRange(i, size());
return data[i];
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// warnings about unused arguments
(void) grainsize;
+# ifndef DEAL_II_BIND_NO_CONST_OP_PARENTHESES
f (begin, end);
+# else
+ // work around a problem with MS VC++ where there is no const
+ // operator() in 'Function' if 'Function' is the result of std::bind
+ Function ff = f;
+ ff (begin, end);
+# endif
#else
tbb::parallel_for (tbb::blocked_range<RangeType>
(begin, end, grainsize),
// warnings about unused arguments
(void) grainsize;
- return f(begin,end);
+# ifndef DEAL_II_BIND_NO_CONST_OP_PARENTHESES
+ return f (begin, end);
+# else
+ // work around a problem with MS VC++ where there is no const
+ // operator() in 'Function' if 'Function' is the result of std::bind
+ Function ff = f;
+ return ff (begin, end);
+# endif
#else
internal::ReductionOnSubranges<ResultType,Function>
reductor (f, std::plus<ResultType>(), 0);
<< "Global index " << arg1
<< " neither owned nor ghost on proc " << arg2);
- private: /**
- * The global size of the vector over all
- * processors
- */
+ private:
+ /**
+ * The global size of the vector over all processors
+ */
const types::global_dof_index global_size;
/**
* @code
* #include <deal.II/base/path_search.h>
*
- DEAL_II_NAMESPACE_OPEN
- * PathSearch search("MESH");
+ * dealii::PathSearch search("MESH");
* std::string full_name = search.find("grid");
* std::ifstream in(full_name.c_str());
* ...
+/**
+ * Sorted Quadrature. Given an arbitrary quadrature formula, this
+ * class generates a quadrature formula where the quadrature points
+ * are ordered according the weights, from those with smaller
+ * corresponding weight, to those with higher corresponding weights.
+ * This might be necessary, for example, when integrating high order
+ * polynomials, since in these cases you might sum very big numbers
+ * with very small numbers, and summation is not stable if the numbers
+ * to sum are not close to each other.
+ */
+template <int dim>
+class QSorted : public Quadrature<dim>
+{
+public:
+ /** The constructor takes an arbitrary quadrature formula. */
+ QSorted (const Quadrature<dim>);
+
+ /** A rule to reorder pairs of points and weights.*/
+ bool operator()(const std::pair<double, Point<dim> > &a,
+ const std::pair<double, Point<dim> > &b);
+};
+
+
/*@}*/
/* -------------- declaration of explicit specializations ------------- */
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/subscriptor.h>
#include <deal.II/base/table_indices.h>
#include <deal.II/base/memory_consumption.h>
+#include <deal.II/base/aligned_vector.h>
#include <cstddef>
#include <algorithm>
typedef const T value_type;
typedef const TableBase<N,T> TableType;
- typedef typename std::vector<T>::const_iterator iterator;
- typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename AlignedVector<T>::const_iterator iterator;
+ typedef typename AlignedVector<T>::const_iterator const_iterator;
- typedef typename std::vector<T>::const_reference reference;
- typedef typename std::vector<T>::const_reference const_reference;
+ typedef typename AlignedVector<T>::const_reference reference;
+ typedef typename AlignedVector<T>::const_reference const_reference;
};
/**
typedef T value_type;
typedef TableBase<N,T> TableType;
- typedef typename std::vector<T>::iterator iterator;
- typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename AlignedVector<T>::iterator iterator;
+ typedef typename AlignedVector<T>::const_iterator const_iterator;
- typedef typename std::vector<T>::reference reference;
- typedef typename std::vector<T>::const_reference const_reference;
+ typedef typename AlignedVector<T>::reference reference;
+ typedef typename AlignedVector<T>::const_reference const_reference;
};
* Return a read-write reference
* to the indicated element.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<N> &indices);
/**
* don't know here whether
* copying is expensive or not.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<N> &indices) const;
/**
* used internally and in
* functions already checked.
*/
- typename std::vector<T>::reference el (const TableIndices<N> &indices);
+ typename AlignedVector<T>::reference el (const TableIndices<N> &indices);
/**
* Return the value of the
* don't know here whether
* copying is expensive or not.
*/
- typename std::vector<T>::const_reference el (const TableIndices<N> &indices) const;
+ typename AlignedVector<T>::const_reference el (const TableIndices<N> &indices) const;
/**
* @deprecated This function
* cast from const), otherwise,
* keep away!
*/
- typename std::vector<T>::const_pointer data () const DEAL_II_DEPRECATED;
+ typename AlignedVector<T>::const_pointer data () const DEAL_II_DEPRECATED;
protected:
/**
* Component-array.
*/
- std::vector<T> values;
+ AlignedVector<T> values;
/**
* Size in each direction of the
* data element. Returns a
* read-only reference.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator [] (const unsigned int i) const;
/**
* data element. Returns a
* read-write reference.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator [] (const unsigned int i);
/**
* data element. Returns a
* read-only reference.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const unsigned int i) const;
/**
* data element. Returns a
* read-write reference.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const unsigned int i);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<1> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<1> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const unsigned int i,
const unsigned int j) const;
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const unsigned int i,
const unsigned int j);
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<2> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<2> &indices) const;
* table classes for 2d arrays,
* then called <tt>vector2d</tt>.
*/
- typename std::vector<T>::reference el (const unsigned int i,
- const unsigned int j);
+ typename AlignedVector<T>::reference el (const unsigned int i,
+ const unsigned int j);
/**
* Return the value of the
* table classes for 2d arrays,
* then called <tt>vector2d</tt>.
*/
- typename std::vector<T>::const_reference el (const unsigned int i,
- const unsigned int j) const;
+ typename AlignedVector<T>::const_reference el (const unsigned int i,
+ const unsigned int j) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k) const;
/**
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::reference operator () (const TableIndices<3> &indices);
+ typename AlignedVector<T>::reference operator () (const TableIndices<3> &indices);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference operator () (const TableIndices<3> &indices) const;
+ typename AlignedVector<T>::const_reference operator () (const TableIndices<3> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l) const;
/**
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<4> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<4> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m) const;
/**
* Direct access to one element
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<5> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<5> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m,
- const unsigned int n) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m,
+ const unsigned int n) const;
/**
* Direct access to one element
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m,
- const unsigned int n);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m,
+ const unsigned int n);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<6> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<6> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m,
- const unsigned int n,
- const unsigned int o) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m,
+ const unsigned int n,
+ const unsigned int o) const;
/**
* Direct access to one element
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j,
- const unsigned int k,
- const unsigned int l,
- const unsigned int m,
- const unsigned int n,
- const unsigned int o);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j,
+ const unsigned int k,
+ const unsigned int l,
+ const unsigned int m,
+ const unsigned int n,
+ const unsigned int o);
/**
* Make the corresponding
* base class available also in
* this class.
*/
- typename std::vector<T>::reference
+ typename AlignedVector<T>::reference
operator () (const TableIndices<7> &indices);
/**
* base class available also in
* this class.
*/
- typename std::vector<T>::const_reference
+ typename AlignedVector<T>::const_reference
operator () (const TableIndices<7> &indices) const;
};
* This version of the function
* only allows read access.
*/
- typename std::vector<T>::const_reference operator () (const unsigned int i,
- const unsigned int j) const;
+ typename AlignedVector<T>::const_reference operator () (const unsigned int i,
+ const unsigned int j) const;
/**
* Direct access to one element
* This version of the function
* allows read-write access.
*/
- typename std::vector<T>::reference operator () (const unsigned int i,
- const unsigned int j);
+ typename AlignedVector<T>::reference operator () (const unsigned int i,
+ const unsigned int j);
/**
* Number of rows. This function
* table classes for 2d arrays,
* then called <tt>vector2d</tt>.
*/
- typename std::vector<T>::reference el (const unsigned int i,
+ typename AlignedVector<T>::reference el (const unsigned int i,
const unsigned int j);
/**
* table classes for 2d arrays,
* then called <tt>vector2d</tt>.
*/
- typename std::vector<T>::const_reference el (const unsigned int i,
+ typename AlignedVector<T>::const_reference el (const unsigned int i,
const unsigned int j) const;
};
:
Subscriptor ()
{
- reinit (src.table_size);
- if (src.n_elements() != 0)
- std::copy (src.values.begin(), src.values.end(), values.begin());
+ values = src.values;
+ reinit (src.table_size, true);
}
TableBase<N,T> &
TableBase<N,T>::operator = (const TableBase<N,T> &m)
{
- reinit (m.size());
- if (!empty())
- std::copy (m.values.begin(), m.values.end(), values.begin());
+ if (!m.empty())
+ values = m.values;
+ reinit (m.size(), true);
return *this;
}
TableBase<N,T> &
TableBase<N,T>::operator = (const TableBase<N,T2> &m)
{
- reinit (m.size());
+ reinit (m.size(), true);
if (!empty())
std::copy (m.values.begin(), m.values.begin() + n_elements(),
values.begin());
void
TableBase<N,T>::reset_values ()
{
+ // use parallel set operation
if (n_elements() != 0)
- std::fill (values.begin(), values.end(), T());
+ values.fill(T());
}
TableBase<N,T>::fill (const T &value)
{
if (n_elements() != 0)
- std::fill (values.begin(), values.end(), value);
+ values.fill(value);
}
const unsigned int new_size = n_elements();
- // if zero size was given: free all
- // memory
+ // if zero size was given: free all memory
if (new_size == 0)
{
values.resize (0);
return;
}
- // if new size is nonzero:
- // if necessary allocate
- // additional memory
- values.resize (new_size);
-
- // reinitialize contents of old or
- // new memory. note that we
- // actually need to do this here,
- // even in the case that we
- // reallocated memory, since per
- // C++ standard, clause 5.3.4/15
- // the newly allocated objects are
- // only default initialized by
- // operator new[] if they are
- // non-POD type. In other words, if
- // we have a table of doubles, then
- // their values after calling 'new
- // double[val_size]' is
- // indetermined.
- if (fast == false)
- reset_values ();
+ // if new size is nonzero: if necessary allocate additional memory, and if
+ // not fast resize, zero out all values)
+ values.resize_fast (new_size);
+ if (!fast)
+ values.fill(T());
}
ExcMessage("Trying to fill an empty matrix."));
if (C_style_indexing)
- for (typename std::vector<T>::iterator p = values.begin();
+ for (typename AlignedVector<T>::iterator p = values.begin();
p != values.end(); ++p)
*p = *entries++;
else
template <int N, typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
TableBase<N,T>::operator () (const TableIndices<N> &indices) const
{
for (unsigned int n=0; n<N; ++n)
template <int N, typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
TableBase<N,T>::operator () (const TableIndices<N> &indices)
{
for (unsigned int n=0; n<N; ++n)
template <int N, typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
TableBase<N,T>::el (const TableIndices<N> &indices) const
{
return values[position(indices)];
template <int N, typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
TableBase<N,T>::el (const TableIndices<N> &indices)
{
Assert (position(indices) < values.size(),
template <int N, typename T>
inline
-typename std::vector<T>::const_pointer
+typename AlignedVector<T>::const_pointer
TableBase<N,T>::data () const
{
if (values.size() == 0)
- return typename std::vector<T>::const_pointer();
+ return typename AlignedVector<T>::const_pointer();
else
return &values[0];
}
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<1,T>::operator [] (const unsigned int i) const
{
Assert (i < this->table_size[0],
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<1,T>::operator [] (const unsigned int i)
{
Assert (i < this->table_size[0],
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<1,T>::operator () (const unsigned int i) const
{
Assert (i < this->table_size[0],
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<1,T>::operator () (const unsigned int i)
{
Assert (i < this->table_size[0],
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<1,T>::operator () (const TableIndices<1> &indices) const
{
return TableBase<1,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<1,T>::operator () (const TableIndices<1> &indices)
{
return TableBase<1,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<2,T>::operator () (const unsigned int i,
const unsigned int j) const
{
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<2,T>::operator () (const unsigned int i,
const unsigned int j)
{
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<2,T>::operator () (const TableIndices<2> &indices) const
{
return TableBase<2,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<2,T>::operator () (const TableIndices<2> &indices)
{
return TableBase<2,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<2,T>::el (const unsigned int i,
const unsigned int j) const
{
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<2,T>::el (const unsigned int i,
const unsigned int j)
{
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
TransposeTable<T>::operator () (const unsigned int i,
const unsigned int j) const
{
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
TransposeTable<T>::operator () (const unsigned int i,
const unsigned int j)
{
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
TransposeTable<T>::el (const unsigned int i,
const unsigned int j) const
{
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
TransposeTable<T>::el (const unsigned int i,
const unsigned int j)
{
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<3,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k) const
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<3,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k)
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<3,T>::operator () (const TableIndices<3> &indices) const
{
return TableBase<3,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<3,T>::operator () (const TableIndices<3> &indices)
{
return TableBase<3,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<4,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<4,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<4,T>::operator () (const TableIndices<4> &indices) const
{
return TableBase<4,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<4,T>::operator () (const TableIndices<4> &indices)
{
return TableBase<4,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<5,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<5,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<5,T>::operator () (const TableIndices<5> &indices) const
{
return TableBase<5,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<5,T>::operator () (const TableIndices<5> &indices)
{
return TableBase<5,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<6,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<6,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<6,T>::operator () (const TableIndices<6> &indices) const
{
return TableBase<6,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<6,T>::operator () (const TableIndices<6> &indices)
{
return TableBase<6,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<7,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<7,T>::operator () (const unsigned int i,
const unsigned int j,
const unsigned int k,
template <typename T>
inline
-typename std::vector<T>::const_reference
+typename AlignedVector<T>::const_reference
Table<7,T>::operator () (const TableIndices<7> &indices) const
{
return TableBase<7,T>::operator () (indices);
template <typename T>
inline
-typename std::vector<T>::reference
+typename AlignedVector<T>::reference
Table<7,T>::operator () (const TableIndices<7> &indices)
{
return TableBase<7,T>::operator () (indices);
return tt;
}
+
+
+/**
+ * Multiplication of a tensor of general rank by a scalar
+ * complex<double> from the left.
+ *
+ * @relates Tensor
+ */
+template <int rank, int dim>
+ inline
+ Tensor<rank,dim,std::complex<double> >
+ operator * (const std::complex<double> factor,
+ const Tensor<rank,dim> &t)
+{
+ Tensor<rank,dim,std::complex<double> > tt;
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = factor * t[d];
+ return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of general rank by a scalar
+ * complex<double> from the right.
+ *
+ * @relates Tensor
+ */
+template <int rank, int dim>
+ inline
+ Tensor<rank,dim,std::complex<double> >
+ operator * (const Tensor<rank,dim> &t,
+ const std::complex<double> factor)
+{
+ Tensor<rank,dim,std::complex<double> > tt;
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
}
+
+/**
+ * Multiplication of a tensor of rank 1 by a scalar complex<double>
+ * from the right.
+ *
+ * @relates Tensor<1,dim,Number>
+ */
+template <int dim>
+inline
+Tensor<1,dim,std::complex<double> >
+ operator * (const Tensor<1,dim> &t,
+ const std::complex<double> factor)
+{
+ Tensor<1,dim,std::complex<double> > tt (false);
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
+/**
+ * Multiplication of a tensor of rank 1 by a scalar complex<double>
+ * from the left.
+ *
+ * @relates Tensor<1,dim,Number>
+ */
+template <int dim>
+inline
+Tensor<1,dim,std::complex<double> >
+ operator * (const std::complex<double> factor,
+ const Tensor<1,dim> &t)
+{
+ Tensor<1,dim,std::complex<double> > tt (false);
+ for (unsigned int d=0; d<dim; ++d)
+ tt[d] = t[d] * factor;
+ return tt;
+}
+
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.h 32217 2014-01-15 16:34:36Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__time_stepping_h
+#define __deal2__time_stepping_h
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/std_cxx1x/function.h>
+
+#include <vector>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * Namespace containing the time stepping methods.
+ *
+ * @author Bruno Turcksin
+ * @date 2014
+ */
+
+namespace TimeStepping
+{
+ /**
+ * Runge-Kutta methods available:
+ * - Explicit methods:
+ * - FORWARD_EULER: first order
+ * - RK_THIRD_ORDER: third order Runge-Kutta
+ * - RK_CLASSIC_FOURTH_ORDER: classical fourth order Runge-Kutta
+ * - Implicit methods:
+ * - BACKWARD_EULER: first order
+ * - IMPLICIT_MIDPOINT: second order
+ * - CRANK_NICOLSON: second order
+ * - SDIRK_TWO_STAGES: second order
+ * - Embedded explicit methods:
+ * - HEUN_EULER: second order
+ * - BOGACKI_SHAMPINE: third order
+ * - DOPRI: Dormand-Prince fifth order (method used by ode45 in MATLAB)
+ * - FEHLBERG: fifth order
+ * - CASH_KARP: firth order
+ */
+ enum runge_kutta_method { FORWARD_EULER, RK_THIRD_ORDER, RK_CLASSIC_FOURTH_ORDER,
+ BACKWARD_EULER, IMPLICIT_MIDPOINT, CRANK_NICOLSON,
+ SDIRK_TWO_STAGES, HEUN_EULER, BOGACKI_SHAMPINE, DOPRI,
+ FEHLBERG, CASH_KARP
+ };
+
+
+
+ /**
+ * Reason for exiting evolve_one_time_step when using an embedded
+ * method: DELTA_T (the time step is in the valid range), MIN_DELTA_T (the
+ * time step was increased to the minimum acceptable time step), MAX_DELTA_T
+ * (the time step was reduced to the maximum acceptable time step).
+ */
+ enum embedded_runge_kutta_time_step { DELTA_T, MIN_DELTA_T, MAX_DELTA_T };
+
+
+
+ /**
+ * Abstract class for time stepping methods. These methods assume that the
+ * equation has the form: \f$ \frac{\partial y}{\partial t} = f(t,y) \f$.
+ */
+ template <typename VECTOR>
+ class TimeStepping
+ {
+ public:
+ /**
+ * Purely virtual function. This function is used to advance from time @p
+ * t to t+ @p delta_t. @p F is a vector of functions \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p J_inverse is a vector
+ * functions that compute the inverse of the Jacobians associated to the
+ * implicit problems. The input parameters are the
+ * time, \f$ \tau \f$, and a vector. The output is the value of function
+ * at this point. This function returns the time at the end of the
+ * time step.
+ */
+ virtual double evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y) = 0;
+
+ /**
+ * Empty structure used to store informations.
+ */
+ struct Status {};
+
+ /**
+ * Purely virtual function that return Status.
+ */
+ virtual const Status &get_status() const = 0;
+ };
+
+
+
+ /**
+ * Base class for the Runge-Kutta method
+ *
+ * @author Damien Lebrun-Grandie, Bruno Turcksin
+ * @date 2014
+ */
+ template <typename VECTOR>
+ class RungeKutta : public TimeStepping<VECTOR>
+ {
+ public:
+ /**
+ * Purely virtual method used to initialize the Runge-Kutta method.
+ */
+ virtual void initialize(runge_kutta_method method) = 0;
+ /**
+ * This function is used to advance from time @p
+ * t to t+ @p delta_t. @p F is a vector of functions \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p J_inverse is a vector
+ * functions that compute the inverse of the Jacobians associated to the
+ * implicit problems. The input parameters are the
+ * time, \f$ \tau \f$, and a vector. The output is the value of function
+ * at this point. This function returns the time at the end of the
+ * time step. When using Runge-Kutta methods, @p F and @ J_inverse can
+ * only contain one element.
+ */
+ double evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Purely virtual function. This function is used to advance from time @p t
+ * to t+ @p delta_t. @p f is the function \f$ f(t,y) \f$ that should be
+ * integrated, the input parameters are the time t and the vector y and the
+ * output is value of f at this point. @p id_minus_tau_J_inverse is a function
+ * that computes \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix,
+ * \f$ \tau \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ virtual double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y) = 0;
+
+ protected:
+ /**
+ * Number of stages of the Runge-Kutta method.
+ */
+ unsigned int n_stages;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> c;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<std::vector<double> > a;
+ };
+
+
+
+ /**
+ * ExplicitRungeKutta is derived from RungeKutta and implement the explicit methods.
+ */
+ template <typename VECTOR>
+ class ExplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) needs to be called
+ * before the object can be used.
+ */
+ ExplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method).
+ */
+ ExplicitRungeKutta(runge_kutta_method method);
+
+ /**
+ * Initialize the explicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameter are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t.
+ * This function is similar to the one derived from RungeKutta, but
+ * does not required id_minus_tau_J_inverse because it is not used for
+ * explicit methods. evolve_one_time_step returns the time at the end of the
+ * time step.
+ */
+ double evolve_one_time_step(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This structure stores the name of the method used.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages) const;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+
+
+
+ /**
+ * This class is derived from RungeKutta and implement the implicit
+ * methods. This class works only for Diagonal Implicit Runge-Kutta
+ * (DIRK) methods.
+ */
+ template <typename VECTOR>
+ class ImplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) and
+ * set_newton_solver_parameters(unsigned int,double)
+ * need to be called before the object can be used.
+ */
+ ImplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method) and
+ * initialize the maximum number of iterations and the tolerance of the
+ * Newton solver.
+ */
+ ImplicitRungeKutta(runge_kutta_method method, unsigned int max_it=100, double tolerance=1e-6);
+
+ /**
+ * Initialize the implicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Set the maximum number of iterations and the tolerance used by the
+ * Newton solver.
+ */
+ void set_newton_solver_parameters(unsigned int max_it, double tolerance);
+
+ /**
+ * Structure that stores the name of the method, the number of
+ * Newton iterations and the norm of the residual when exiting the
+ * Newton solver.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ unsigned int n_iterations;
+ double norm_residual;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y,
+ std::vector<VECTOR> &f_stages);
+
+ /**
+ * Newton solver used for the implicit stages.
+ */
+ void newton_solve(std_cxx1x::function<void (const VECTOR &,VECTOR &)> get_residual,
+ std_cxx1x::function<VECTOR (const VECTOR &)> id_minus_tau_J_inverse,
+ VECTOR &y);
+
+ /**
+ * Compute the residual needed by the Newton solver.
+ */
+ void compute_residual(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ const VECTOR &old_y,
+ const VECTOR &y,
+ VECTOR &tendency,
+ VECTOR &residual) const;
+
+ /**
+ * When using SDIRK, there is no need to compute the linear combination
+ * of the stages. Thus, when this flag is true, the linear combination
+ * is skipped.
+ */
+ bool skip_linear_combi;
+
+ /**
+ * Maximum number of iterations of the Newton solver.
+ */
+ unsigned int max_it;
+
+ /**
+ * Tolerance of the Newton solver.
+ */
+ double tolerance;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+
+
+
+ /**
+ * This is class is derived from RungeKutta and implement embedded explicit
+ * methods.
+ */
+ template <typename VECTOR>
+ class EmbeddedExplicitRungeKutta : public RungeKutta<VECTOR>
+ {
+ public:
+ using RungeKutta<VECTOR>::evolve_one_time_step;
+
+ /**
+ * Default constructor. initialize(runge_kutta_method) and
+ * set_time_adaptation_parameters(double, double, double, double, double, double)
+ * need to be called before the object can be used.
+ */
+ EmbeddedExplicitRungeKutta() {};
+
+ /**
+ * Constructor. This function calls initialize(runge_kutta_method) and
+ * initialize the parameters needed for time adaptation.
+ */
+ EmbeddedExplicitRungeKutta(runge_kutta_method method,
+ double coarsen_param = 1.2,
+ double refine_param = 0.8,
+ double min_delta = 1e-14,
+ double max_delta = 1e100,
+ double refine_tol = 1e-8,
+ double coarsen_tol = 1e-12);
+
+ /**
+ * Destructor.
+ */
+ ~EmbeddedExplicitRungeKutta()
+ {
+ free_memory();
+ }
+
+ /**
+ * If necessary, deallocate memory allocated by the object.
+ */
+ void free_memory();
+
+ /**
+ * Initialize the embedded explicit Runge-Kutta method.
+ */
+ void initialize(runge_kutta_method method);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t. @p f
+ * is the function \f$ f(t,y) \f$ that should be integrated, the input
+ * parameters are the time t and the vector y and the output is value of
+ * f at this point. @p id_minus_tau_J_inverse is a function that computes
+ * \f$ inv(I-\tau J)\f$ where \f$ I \f$ is the identity matrix, \f$ \tau
+ * \f$ is given, and \f$ J \f$ is the Jacobian \f$ \frac{\partial
+ * J}{\partial y} \f$. The input parameters are the time, \f$ \tau \f$, and
+ * a vector. The output is the value of function at this point.
+ * evolve_one_time_step returns the time at the end of the time step.
+ */
+ double evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * This function is used to advance from time @p t to t+ @p delta_t.
+ * This function is similar to the one derived from TimeStepping, but
+ * does not required id_minus_tau_J_inverse because it is not used for
+ * explicit methods. evolve_one_time_step returns the time at the end of the
+ * time step.
+ */
+ double evolve_one_time_step(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y);
+
+ /**
+ * Set the parameters necessary for the time adaptation.
+ */
+ void set_time_adaptation_parameters(double coarsen_param,
+ double refine_param,
+ double min_delta,
+ double max_delta,
+ double refine_tol,
+ double coarsen_tol);
+
+ /**
+ * Structure that stores the name of the method, the reason to exit
+ * evolve_one_time_step, the number of iteration inside n_iterations, a guess
+ * of what the next time step should be, and an estimate of the norm of
+ * the error.
+ */
+ struct Status : public TimeStepping<VECTOR>::Status
+ {
+ runge_kutta_method method;
+ embedded_runge_kutta_time_step exit_delta_t;
+ unsigned int n_iterations;
+ double delta_t_guess;
+ double error_norm;
+ };
+
+ /**
+ * Return the status of the current object.
+ */
+ const Status &get_status() const;
+
+ private:
+ /**
+ * Compute the different stages needed.
+ */
+ void compute_stages(std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages);
+
+ /**
+ * This parameter is the factor (>1) by which the time step is
+ * multiplied when the time stepping can be coarsen.
+ */
+ double coarsen_param;
+
+ /**
+ * This parameter is the factor (<1) by which the time step is
+ * multiplied when the time stepping must be refined.
+ */
+ double refine_param;
+
+ /**
+ * Smallest time step allowed.
+ */
+ double min_delta_t;
+
+ /**
+ * Largest time step allowed.
+ */
+ double max_delta_t;
+
+ /**
+ * Refinement tolerance: if the error estimate is larger than
+ * refine_tol, the time step is refined.
+ */
+ double refine_tol;
+
+ /**
+ * Coarsening tolerance: if the error estimate is smaller than
+ * coarse_tol, the time step is coarsen.
+ */
+ double coarsen_tol;
+
+ /**
+ * If the flag is true, the last stage is the same as the first stage
+ * and one evaluation of f can be saved.
+ */
+ bool last_same_as_first;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b1;
+
+ /**
+ * Butcher tableau coefficients.
+ */
+ std::vector<double> b2;
+
+ /**
+ * If the last_same_as_first flag is set to true, the last stage is
+ * saved and reused as the first stage of the next time step.
+ */
+ VECTOR *last_stage;
+
+ /**
+ * Status structure of the object.
+ */
+ Status status;
+ };
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.h 32217 2014-01-15 16:34:36Z bangerth $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__time_stepping_templates_h
+#define __deal2__time_stepping_templates_h
+
+#include <deal.II/base/std_cxx1x/bind.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/time_stepping.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace TimeStepping
+{
+ // ----------------------------------------------------------------------
+ // RungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ double RungeKutta<VECTOR>::evolve_one_time_step(
+ std::vector<std_cxx1x::function<VECTOR (const double, const VECTOR &)> > &F,
+ std::vector<std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> > & J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ AssertThrow(F.size()==0,
+ ExcMessage("RungeKutta methods cannot handle more that one function to integate."));
+ AssertThrow(J_inverse.size()==0,
+ ExcMessage("RungeKutta methods cannot handle more that one function to integate."));
+
+ return evolve_one_time_step(F[0],J_inverse[0],t,delta_t,y);
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // ExplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ ExplicitRungeKutta<VECTOR>::ExplicitRungeKutta(runge_kutta_method method)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void ExplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (FORWARD_EULER) :
+ {
+ this->n_stages = 1;
+ this->b.push_back(1.0);
+ this->c.push_back(0.0);
+
+ break;
+ }
+ case (RK_THIRD_ORDER) :
+ {
+ this->n_stages = 3;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ this->b.push_back(1.0/6.0);
+ this->b.push_back(2.0/3.0);
+ this->b.push_back(1.0/6.0);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(1.0);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = -1.0;
+ tmp[1] = 2.0;
+ this->a.push_back(tmp);
+
+ break;
+ }
+ case (RK_CLASSIC_FOURTH_ORDER) :
+ {
+ this->n_stages = 4;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.0;
+ tmp[1] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[1] = 0.0;
+ tmp[2] = 1.0;
+ this->a.push_back(tmp);
+ this->b.push_back(1.0/6.0);
+ this->b.push_back(1.0/3.0);
+ this->b.push_back(1.0/3.0);
+ this->b.push_back(1.0/6.0);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(0.5);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented explicit Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ double ExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ return evolve_one_time_step(f,t,delta_t,y);
+ }
+
+
+
+ template <typename VECTOR>
+ double ExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+ // Compute the different stages needed.
+ compute_stages(f,t,delta_t,y,f_stages);
+
+ // Linear combinations of the stages.
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ y.sadd(1.,delta_t*this->b[i],f_stages[i]);
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ const typename ExplicitRungeKutta<VECTOR>::Status &ExplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+
+ template <typename VECTOR>
+ void ExplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages) const
+ {
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ VECTOR Y(y);
+ for (unsigned int j=0; j<i; ++j)
+ Y.sadd(1.,delta_t*this->a[i][j],f_stages[j]);
+ // Evaluate the function f at the point (t+c[i]*delta_t,Y).
+ f_stages[i] = f(t+this->c[i]*delta_t,Y);
+ }
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // ImplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ ImplicitRungeKutta<VECTOR>::ImplicitRungeKutta(runge_kutta_method method,
+ unsigned int max_it,
+ double tolerance)
+ :
+ RungeKutta<VECTOR> (),
+ skip_linear_combi(false),
+ max_it(max_it),
+ tolerance(tolerance)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (BACKWARD_EULER) :
+ {
+ this->n_stages = 1;
+ this->a.push_back(std::vector<double>(1, 1.0));
+ this->b.push_back(1.0);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ case (IMPLICIT_MIDPOINT) :
+ {
+ this->a.push_back(std::vector<double>(1, 0.5));
+ this->b.push_back(1.0);
+ this->c.push_back(0.5);
+ this->n_stages = 1;
+
+ break;
+ }
+ case (CRANK_NICOLSON) :
+ {
+ this->n_stages = 2;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ this->a.push_back(std::vector<double>(1, 0.0));
+ this->a.push_back(std::vector<double>(2, 0.5));
+ this->b.push_back(0.5);
+ this->b.push_back(0.5);
+ this->c.push_back(0.0);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ case (SDIRK_TWO_STAGES) :
+ {
+ this->n_stages = 2;
+ this->b.reserve(this->n_stages);
+ this->c.reserve(this->n_stages);
+ double const gamma = 1.0 - 1.0 / std::sqrt(2.0);
+ this->b.push_back(1.0 - gamma);
+ this->b.push_back(gamma);
+ this->a.push_back(std::vector<double>(1, gamma));
+ this->a.push_back(this->b);
+ this->c.push_back(gamma);
+ this->c.push_back(1.0);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented implicit Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ double ImplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ VECTOR old_y(y);
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+ // Compute the different stages needed.
+ compute_stages(f,id_minus_tau_J_inverse,t,delta_t,y,f_stages);
+
+ // If necessary, compute the linear combinations of the stages.
+ if (skip_linear_combi==false)
+ {
+ y = old_y;
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ y.sadd(1.,delta_t*this->b[i],f_stages[i]);
+ }
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::set_newton_solver_parameters(unsigned int max_it_, double tolerance_)
+ {
+ max_it = max_it_;
+ tolerance = tolerance_;
+ }
+
+
+
+ template <typename VECTOR>
+ const typename ImplicitRungeKutta<VECTOR>::Status &ImplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y,
+ std::vector<VECTOR> &f_stages)
+ {
+ VECTOR z(y);
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ VECTOR old_y(z);
+ for (unsigned int j=0; j<i; ++j)
+ old_y.sadd(1.,delta_t*this->a[i][j],f_stages[j]);
+
+ // Solve the nonlinear system using Newton's method
+ const double new_t = t+this->c[i]*delta_t;
+ const double new_delta_t = this->a[i][i]*delta_t;
+ newton_solve(std_cxx1x::bind(&ImplicitRungeKutta<VECTOR>::compute_residual,this,f,new_t,new_delta_t,
+ std_cxx1x::cref(old_y),std_cxx1x::_1,std_cxx1x::ref(f_stages[i]),std_cxx1x::_2),
+ std_cxx1x::bind(id_minus_tau_J_inverse,new_t,new_delta_t,std_cxx1x::_1),y);
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::newton_solve(
+ std_cxx1x::function<void (const VECTOR &,VECTOR &)> get_residual,
+ std_cxx1x::function<VECTOR (const VECTOR &)> id_minus_tau_J_inverse,
+ VECTOR &y)
+ {
+ VECTOR residual(y);
+ get_residual(y,residual);
+ unsigned int i=0;
+ const double initial_residual_norm = residual.l2_norm();
+ double norm_residual = initial_residual_norm;
+ while (i<max_it)
+ {
+ y.sadd(1.0,-1.0,id_minus_tau_J_inverse(residual));
+ get_residual(y,residual);
+ norm_residual = residual.l2_norm();
+ if (norm_residual < tolerance)
+ break;
+ ++i;
+ }
+ status.n_iterations = i+1;
+ status.norm_residual = norm_residual;
+ }
+
+
+
+ template <typename VECTOR>
+ void ImplicitRungeKutta<VECTOR>::compute_residual(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t,
+ double delta_t,
+ const VECTOR &old_y,
+ const VECTOR &y,
+ VECTOR &tendency,
+ VECTOR &residual) const
+ {
+ // The tendency is stored to save one evaluation of f.
+ tendency = f(t,y);
+ residual = tendency;
+ residual.sadd(delta_t,1.0,old_y);
+ residual.sadd(-1.0,1.,y);
+ }
+
+
+
+ // ----------------------------------------------------------------------
+ // EmbeddedExplicitRungeKutta
+ // ----------------------------------------------------------------------
+
+ template <typename VECTOR>
+ EmbeddedExplicitRungeKutta<VECTOR>::EmbeddedExplicitRungeKutta(runge_kutta_method method,
+ double coarsen_param,
+ double refine_param,
+ double min_delta,
+ double max_delta,
+ double refine_tol,
+ double coarsen_tol)
+ :
+ coarsen_param(coarsen_param),
+ refine_param(refine_param),
+ min_delta_t(min_delta),
+ max_delta_t(max_delta),
+ refine_tol(refine_tol),
+ coarsen_tol(coarsen_tol),
+ last_same_as_first(false),
+ last_stage(NULL)
+ {
+ initialize(method);
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::initialize(runge_kutta_method method)
+ {
+ status.method = method;
+
+ switch (method)
+ {
+ case (HEUN_EULER) :
+ {
+ this->n_stages = 2;
+ this->a.push_back(std::vector<double>());
+ this->a.push_back(std::vector<double>(1, 1.0));
+ this->c.push_back(0.0);
+ this->c.push_back(1.0);
+ b1.push_back(0.5);
+ b1.push_back(0.5);
+ b2.push_back(1.0);
+ b2.push_back(0.0);
+
+ break;
+ }
+ case (BOGACKI_SHAMPINE) :
+ {
+ last_same_as_first = true;
+ this->n_stages = 4;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.5;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.0;
+ tmp[1] = 0.75;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 2.0/9.0;
+ tmp[1] = 1.0/3.0;
+ tmp[2] = 4.0/9.0;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.5);
+ this->c.push_back(0.75);
+ this->c.push_back(1.0);
+ this->b1.push_back(2.0/9.0);
+ this->b1.push_back(1.0/3.0);
+ this->b1.push_back(4.0/9.0);
+ this->b1.push_back(0.0);
+ this->b2.push_back(7.0/24.0);
+ this->b2.push_back(0.25);
+ this->b2.push_back(1.0/3.0);
+ this->b2.push_back(0.125);
+
+ break;
+ }
+ case (DOPRI) :
+ {
+ last_same_as_first = true;
+ this->n_stages = 7;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 1./5.;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 3./40.;
+ tmp[1] = 9./40.;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 44./45.;
+ tmp[1] = -56./15.;
+ tmp[2] = 32./9.;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = 19372./6561.;
+ tmp[1] = -25360./2187.;
+ tmp[2] = 64448./6561.;
+ tmp[3] = -212./729.;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = 9017./3168.;
+ tmp[1] = -355./33.;
+ tmp[2] = 46732./5247.;
+ tmp[3] = 49./176.;
+ tmp[4] = -5103./18656;
+ this->a.push_back(tmp);
+ tmp.resize(6);
+ tmp[0] = 35./384.;
+ tmp[1] = 0.;
+ tmp[2] = 500./1113.;
+ tmp[3] = 125./192.;
+ tmp[4] = -2187./6784.;
+ tmp[5] = 11./84.;
+ this->a.push_back(tmp);
+ this->c.push_back(0.);
+ this->c.push_back(1./5.);
+ this->c.push_back(3./10.);
+ this->c.push_back(4./5.);
+ this->c.push_back(8./9.);
+ this->c.push_back(1.);
+ this->c.push_back(1.);
+ this->b1.push_back(35./384.);
+ this->b1.push_back(0.);
+ this->b1.push_back(500./1113.);
+ this->b1.push_back(125./192.);
+ this->b1.push_back(-2187./6784.);
+ this->b1.push_back(11./84.);
+ this->b1.push_back(0.);
+ this->b2.push_back(5179./57600.);
+ this->b2.push_back(0.);
+ this->b2.push_back(7571./16695.);
+ this->b2.push_back(393./640.);
+ this->b2.push_back(-92097./339200.);
+ this->b2.push_back(187./2100.);
+ this->b2.push_back(1./40.);
+
+ break;
+ }
+ case (FEHLBERG) :
+ {
+ this->n_stages = 6;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.25;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.09375;
+ tmp[1] = 0.28125;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 1932.0/2197.0;
+ tmp[1] = -7200.0/2197.0;
+ tmp[2] = 7296.0/2197.0;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = 439.0/216.0;
+ tmp[1] = -8.0;
+ tmp[2] = 3680.0/513.0;
+ tmp[3] = -845.0/4104.0;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = -8.0/27.0;
+ tmp[1] = 2.0;
+ tmp[2] = -3544.0/2565.0;
+ tmp[3] = 1859.0/4104.0;
+ tmp[4] = -0.275;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.25);
+ this->c.push_back(0.375);
+ this->c.push_back(12.0/13.0);
+ this->c.push_back(1.0);
+ this->c.push_back(0.5);
+ this->b1.push_back(16.0/135.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(6656.0/12825.0);
+ this->b1.push_back(28561.0/56430.0);
+ this->b1.push_back(-0.18);
+ this->b1.push_back(2.0/55.0);
+ this->b2.push_back(25.0/216.0);
+ this->b2.push_back(0.0);
+ this->b2.push_back(1408.0/2565.0);
+ this->b2.push_back(2197.0/4104.0);
+ this->b2.push_back(-0.2);
+ this->b2.push_back(0.0);
+
+ break;
+ }
+ case (CASH_KARP) :
+ {
+ this->n_stages = 6;
+ this->c.reserve(this->n_stages);
+ this->b1.reserve(this->n_stages);
+ this->b2.reserve(this->n_stages);
+ std::vector<double> tmp;
+ this->a.push_back(tmp);
+ tmp.resize(1);
+ tmp[0] = 0.2;
+ this->a.push_back(tmp);
+ tmp.resize(2);
+ tmp[0] = 0.075;
+ tmp[1] = 0.225;
+ this->a.push_back(tmp);
+ tmp.resize(3);
+ tmp[0] = 0.3;
+ tmp[1] = -0.9;
+ tmp[2] = 1.2;
+ this->a.push_back(tmp);
+ tmp.resize(4);
+ tmp[0] = -11.0/54.0;
+ tmp[1] = 2.5;
+ tmp[2] = -70.0/27.0;
+ tmp[3] = 35.0/27.0;
+ this->a.push_back(tmp);
+ tmp.resize(5);
+ tmp[0] = 1631.0/55296.0;
+ tmp[1] = 175.0/512.0;
+ tmp[2] = 575.0/13824.0;
+ tmp[3] = 44275.0/110592.0;
+ tmp[4] = 253.0/4096.0;
+ this->a.push_back(tmp);
+ this->c.push_back(0.0);
+ this->c.push_back(0.2);
+ this->c.push_back(0.3);
+ this->c.push_back(0.6);
+ this->c.push_back(1.0);
+ this->c.push_back(0.875);
+ this->b1.push_back(37.0/378.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(250.0/621.0);
+ this->b1.push_back(125.0/594.0);
+ this->b1.push_back(0.0);
+ this->b1.push_back(512.0/1771.0);
+ this->b2.push_back(2825.0/27648.0);
+ this->b2.push_back(0.0);
+ this->b2.push_back(18575.0/48384.0);
+ this->b2.push_back(13525.0/55296.0);
+ this->b2.push_back(277.0/14336.0);
+ this->b2.push_back(0.25);
+
+ break;
+ }
+ default :
+ {
+ AssertThrow(false,ExcMessage("Unimplemented Embedded Runge-Kutta method."));
+ }
+ }
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::free_memory()
+ {
+ if (last_stage!=NULL)
+ delete last_stage;
+
+ last_stage = NULL;
+ }
+
+
+
+ template <typename VECTOR>
+ double EmbeddedExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ std_cxx1x::function<VECTOR (const double, const double, const VECTOR &)> id_minus_tau_J_inverse,
+ double t,
+ double delta_t,
+ VECTOR &y)
+ {
+ return evolve_one_time_step(f,t,delta_t,y);
+ }
+
+
+
+ template <typename VECTOR>
+ double EmbeddedExplicitRungeKutta<VECTOR>::evolve_one_time_step(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ double t, double delta_t, VECTOR &y)
+ {
+ bool done = false;
+ unsigned int count = 0;
+ double error_norm = 0.;
+ VECTOR old_y(y);
+ VECTOR error(y);
+ std::vector<VECTOR> f_stages(this->n_stages,y);
+
+ while (!done)
+ {
+ error = 0.;
+ y = old_y;
+ // Compute the different stages needed.
+ compute_stages(f,t,delta_t,y,f_stages);
+
+ for (unsigned int i=0; i<this->n_stages; ++i)
+ {
+ y.sadd(1.,delta_t*this->b1[i],f_stages[i]);
+ error.sadd(1.,delta_t*(b2[i]-b1[i]),f_stages[i]);
+ }
+
+ error_norm = error.l2_norm();
+ // Check if the norm of error is less than the coarsening tolerance
+ if (error_norm<coarsen_tol)
+ {
+ done = true;
+ // Increase the guessed time step
+ double new_delta_t = delta_t*coarsen_param;
+ // Check that the guessed time step is smaller than the maximum time
+ // step allowed.
+ if (new_delta_t>max_delta_t)
+ {
+ status.exit_delta_t = MAX_DELTA_T;
+ status.delta_t_guess = max_delta_t;
+ }
+ else
+ {
+ status.exit_delta_t = DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ }
+ // Check if the norm of error is less than the refining tolerance
+ else if (error_norm<refine_tol)
+ {
+ done = true;
+ status.exit_delta_t = DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ else
+ {
+ // If the time step is already the smallest acceptable, exit.
+ if (delta_t==min_delta_t)
+ {
+ done = true;
+ status.exit_delta_t = MIN_DELTA_T;
+ status.delta_t_guess = delta_t;
+ }
+ // Reduce the time step.
+ else
+ {
+ delta_t *= refine_param;
+ if (delta_t<min_delta_t)
+ delta_t = min_delta_t;
+ }
+ }
+
+ ++count;
+ }
+
+ // Save the last stage if necessary
+ if (last_same_as_first==true)
+ {
+ if (last_stage==NULL)
+ last_stage = new VECTOR(f_stages.back());
+ else
+ *last_stage = f_stages.back();
+ }
+
+ status.n_iterations = count;
+ status.error_norm = error_norm;
+
+ return (t+delta_t);
+ }
+
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::set_time_adaptation_parameters(double coarsen_param_,
+ double refine_param_,
+ double min_delta_,
+ double max_delta_,
+ double refine_tol_,
+ double coarsen_tol_)
+ {
+ coarsen_param = coarsen_param_;
+ refine_param = refine_param_;
+ min_delta_t = min_delta_;
+ max_delta_t = max_delta_;
+ refine_tol = refine_tol_;
+ coarsen_tol = coarsen_tol_;
+ }
+
+
+
+ template <typename VECTOR>
+ const typename EmbeddedExplicitRungeKutta<VECTOR>::Status &EmbeddedExplicitRungeKutta<VECTOR>::get_status() const
+ {
+ return status;
+ }
+
+
+ template <typename VECTOR>
+ void EmbeddedExplicitRungeKutta<VECTOR>::compute_stages(
+ std_cxx1x::function<VECTOR (const double, const VECTOR &)> f,
+ const double t,
+ const double delta_t,
+ const VECTOR &y,
+ std::vector<VECTOR> &f_stages)
+ {
+ VECTOR Y(y);
+ unsigned int i = 0;
+
+ // If the last stage is the same as the first, we can skip the evaluation
+ // of the first stage.
+ if (last_same_as_first==true)
+ {
+ if (last_stage!=NULL)
+ {
+ f_stages[0] = *last_stage;
+ i = 1;
+ }
+ }
+
+ for (; i<this->n_stages; ++i)
+ {
+ Y = y;
+ for (unsigned int j = 0; j < i; ++j)
+ Y.sadd(1.0,delta_t*this->a[i][j],f_stages[j]);
+ f_stages[i] = f(t+this->c[i]*delta_t,Y);
+ }
+ }
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
};
/**
- * Sets whether to generate output every
- * time we exit a section, just in the
- * end, both, or never.
+ * An enumeration data type that describes whether to generate output every
+ * time we exit a section, just in the end, both, or never.
*/
- enum OutputFrequency {every_call, summary, every_call_and_summary, never}
- output_frequency;
+ enum OutputFrequency
+ {
+ every_call,
+ summary,
+ every_call_and_summary,
+ never
+ };
/**
- * Sets whether to show CPU times, wall
- * times, or both CPU and wall times.
+ * An enumeration data type that describes whether to show CPU times, wall
+ * times, or both CPU and wall times whenever we generate output.
*/
- enum OutputType {cpu_times, wall_times, cpu_and_wall_times}
- output_type;
+ enum OutputType
+ {
+ cpu_times,
+ wall_times,
+ cpu_and_wall_times
+ };
/**
- * Constructor that takes std::cout as
- * output stream.
+ * Constructor.
+ *
+ * @param stream The stream (of type std::ostream) to which output is written.
+ * @param output_frequency A variable indicating when output is to be written
+ * to the given stream.
+ * @param output_type A variable indicating what kind of timing the output
+ * should represent (CPU or wall time).
*/
TimerOutput (std::ostream &stream,
const enum OutputFrequency output_frequency,
const enum OutputType output_type);
/**
- * Constructor that takes a
- * ConditionalOStream to write output to.
+ * Constructor.
+ *
+ * @param stream The stream (of type ConditionalOstream) to which output is written.
+ * @param output_frequency A variable indicating when output is to be written
+ * to the given stream.
+ * @param output_type A variable indicating what kind of timing the output
+ * should represent (CPU or wall time).
*/
TimerOutput (ConditionalOStream &stream,
const enum OutputFrequency output_frequency,
* MPI network for calculating the CPU
* time.
*
- * Meant for using std::cout as output
- * stream.
+ * @param mpi_comm An MPI communicator across which we should accumulate or
+ * otherwise synchronize the timing information we produce on every MPI process.
+ * @param stream The stream (of type std::ostream) to which output is written.
+ * @param output_frequency A variable indicating when output is to be written
+ * to the given stream.
+ * @param output_type A variable indicating what kind of timing the output
+ * should represent (CPU or wall time).
*/
TimerOutput (MPI_Comm mpi_comm,
std::ostream &stream,
* MPI network for calculating the CPU
* time.
*
- * Constructor that takes a
- * ConditionalOStream to write output to.
+ * @param mpi_comm An MPI communicator across which we should accumulate or
+ * otherwise synchronize the timing information we produce on every MPI process.
+ * @param stream The stream (of type ConditionalOstream) to which output is written.
+ * @param output_frequency A variable indicating when output is to be written
+ * to the given stream.
+ * @param output_type A variable indicating what kind of timing the output
+ * should represent (CPU or wall time).
*/
TimerOutput (MPI_Comm mpi_comm,
ConditionalOStream &stream,
void reset ();
private:
+ /**
+ * When to output information to the output stream.
+ */
+ OutputFrequency output_frequency;
+
+ /**
+ * Whether to show CPU times, wall
+ * times, or both CPU and wall times.
+ */
+ OutputType output_type;
+
+
/**
* A timer object for the overall
* run time. If we are using MPI,
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2009 - 2013 by the deal.II authors
+// Copyright (C) 2009 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
- typedef unsigned char manifold_id;
+ typedef unsigned int manifold_id;
/**
/**
- * Fills the @param stats structure with
+ * Fills the @p stats structure with
* information about the memory
* consumption of this process. This is
* only implemented on Linux.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#define __deal2__vectorization_h
#include <deal.II/base/config.h>
-#include <deal.II/base/std_cxx1x/type_traits.h>
#include <deal.II/base/exceptions.h>
-#include <deal.II/base/memory_consumption.h>
-#include <deal.II/base/parallel.h>
#include <cmath>
-#include <cstring>
// Note:
// The flag DEAL_II_COMPILER_VECTORIZATION_LEVEL is essentially constructed
// according to the following scheme
+// #ifdef __AVX512F__
+// #define DEAL_II_COMPILER_VECTORIZATION_LEVEL 3
// #ifdef __AVX__
// #define DEAL_II_COMPILER_VECTORIZATION_LEVEL 2
// #elif defined (__SSE2__)
// In addition to checking the flags __AVX__ and __SSE2__, a configure test
// ensures that these feature are not only present but also working properly.
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 // AVX
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL >= 2 // AVX, AVX-512
#include <immintrin.h>
-#include <mm_malloc.h>
#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL == 1 // SSE2
#include <emmintrin.h>
-#include <mm_malloc.h>
#endif
DEAL_II_NAMESPACE_OPEN
-// for safety, also check that __AVX__ is defined in case the user manually
+// for safety, also check that __AVX512F__ is defined in case the user manually
// set some conflicting compile flags which prevent compilation
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 && defined(__AVX__)
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL == 3 && defined(__AVX512F__)
+
+/**
+ * Specialization of VectorizedArray class for double and AVX-512.
+ */
+template <>
+class VectorizedArray<double>
+{
+public:
+ /**
+ * This gives the number of vectors collected in this class.
+ */
+ static const unsigned int n_array_elements = 8;
+
+ /**
+ * This function can be used to set all data fields to a given scalar.
+ */
+ VectorizedArray &
+ operator = (const double x)
+ {
+ data = _mm512_set_pd(x, x, x, x, x, x, x, x);
+ return *this;
+ }
+
+ /**
+ * Access operator.
+ */
+ double &
+ operator [] (const unsigned int comp)
+ {
+ AssertIndexRange (comp, 8);
+ return *(reinterpret_cast<double *>(&data)+comp);
+ }
+
+ /**
+ * Constant access operator.
+ */
+ const double &
+ operator [] (const unsigned int comp) const
+ {
+ AssertIndexRange (comp, 8);
+ return *(reinterpret_cast<const double *>(&data)+comp);
+ }
+
+ /**
+ * Addition.
+ */
+ VectorizedArray &
+ operator += (const VectorizedArray &vec)
+ {
+ // if the compiler supports vector arithmetics, we can simply use +=
+ // operator on the given data type. Otherwise, we need to use the built-in
+ // intrinsic command for __m512d
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data += vec.data;
+#else
+ data = _mm512_add_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Subtraction.
+ */
+ VectorizedArray &
+ operator -= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data -= vec.data;
+#else
+ data = _mm512_sub_pd(data,vec.data);
+#endif
+ return *this;
+ }
+ /**
+ * Multiplication.
+ */
+ VectorizedArray &
+ operator *= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data *= vec.data;
+#else
+ data = _mm512_mul_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Division.
+ */
+ VectorizedArray &
+ operator /= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data /= vec.data;
+#else
+ data = _mm512_div_pd(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 64 bytes, as opposed
+ * to casting a double address to VectorizedArray<double>*.
+ */
+ void load (const double* ptr)
+ {
+ data = _mm512_loadu_pd (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 64 bytes, as opposed to casting a double address to
+ * VectorizedArray<double>*.
+ */
+ void store (double* ptr) const
+ {
+ _mm512_storeu_pd (ptr, data);
+ }
+
+ /**
+ * Actual data field. Since this class represents a POD data type, it
+ * remains public.
+ */
+ __m512d data;
+
+private:
+ /**
+ * Returns the square root of this field. Not for use in user code. Use
+ * sqrt(x) instead.
+ */
+ VectorizedArray
+ get_sqrt () const
+ {
+ VectorizedArray res;
+ res.data = _mm512_sqrt_pd(data);
+ return res;
+ }
+
+ /**
+ * Returns the absolute value of this field. Not for use in user code. Use
+ * abs(x) instead.
+ */
+ VectorizedArray
+ get_abs () const
+ {
+ // to compute the absolute value, perform bitwise andnot with -0. This
+ // will leave all value and exponent bits unchanged but force the sign
+ // value to +.
+ __m256d mask = _mm512_set_pd (-0., -0., -0., -0., -0., -0., -0., -0.);
+ VectorizedArray res;
+ res.data = _mm512_andnot_pd(mask, data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise maximum of this field and another one. Not for
+ * use in user code. Use max(x,y) instead.
+ */
+ VectorizedArray
+ get_max (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_max_pd (data, other.data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise minimum of this field and another one. Not for
+ * use in user code. Use min(x,y) instead.
+ */
+ VectorizedArray
+ get_min (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_min_pd (data, other.data);
+ return res;
+ }
+
+ /**
+ * Make a few functions friends.
+ */
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::sqrt (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::abs (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::max (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::min (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+};
+
+
+
+/**
+ * Specialization for float and AVX.
+ */
+template<>
+class VectorizedArray<float>
+{
+public:
+ /**
+ * This gives the number of vectors collected in this class.
+ */
+ static const unsigned int n_array_elements = 16;
+
+ /**
+ * This function can be used to set all data fields to a given scalar.
+ */
+ VectorizedArray &
+ operator = (const float x)
+ {
+ data = _mm512_set_ps(x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x);
+ return *this;
+ }
+
+ /**
+ * Access operator.
+ */
+ float &
+ operator [] (const unsigned int comp)
+ {
+ AssertIndexRange (comp, 16);
+ return *(reinterpret_cast<float *>(&data)+comp);
+ }
+
+ /**
+ * Constant access operator.
+ */
+ const float &
+ operator [] (const unsigned int comp) const
+ {
+ AssertIndexRange (comp, 16);
+ return *(reinterpret_cast<const float *>(&data)+comp);
+ }
+
+ /**
+ * Addition.
+ */
+ VectorizedArray &
+ operator += (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data += vec.data;
+#else
+ data = _mm512_add_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Subtraction.
+ */
+ VectorizedArray &
+ operator -= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data -= vec.data;
+#else
+ data = _mm512_sub_ps(data,vec.data);
+#endif
+ return *this;
+ }
+ /**
+ * Multiplication.
+ */
+ VectorizedArray &
+ operator *= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data *= vec.data;
+#else
+ data = _mm512_mul_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Division.
+ */
+ VectorizedArray &
+ operator /= (const VectorizedArray &vec)
+ {
+#ifdef DEAL_II_COMPILER_USE_VECTOR_ARITHMETICS
+ data /= vec.data;
+#else
+ data = _mm512_div_ps(data,vec.data);
+#endif
+ return *this;
+ }
+
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 64 bytes, as opposed
+ * to casting a float address to VectorizedArray<float>*.
+ */
+ void load (const float* ptr)
+ {
+ data = _mm512_loadu_ps (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 64 bytes, as opposed to casting a float address to
+ * VectorizedArray<float>*.
+ */
+ void store (float* ptr) const
+ {
+ _mm512_storeu_ps (ptr, data);
+ }
+
+ /**
+ * Actual data field. Since this class represents a POD data type, it
+ * remains public.
+ */
+ __m512 data;
+
+private:
+
+ /**
+ * Returns the square root of this field. Not for use in user code. Use
+ * sqrt(x) instead.
+ */
+ VectorizedArray
+ get_sqrt () const
+ {
+ VectorizedArray res;
+ res.data = _mm512_sqrt_ps(data);
+ return res;
+ }
+
+ /**
+ * Returns the absolute value of this field. Not for use in user code. Use
+ * abs(x) instead.
+ */
+ VectorizedArray
+ get_abs () const
+ {
+ // to compute the absolute value, perform
+ // bitwise andnot with -0. This will leave all
+ // value and exponent bits unchanged but force
+ // the sign value to +.
+ __m256 mask = _mm512_setzero_ps (-0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f,
+ -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f, -0.f);
+ VectorizedArray res;
+ res.data = _mm512_andnot_ps(mask, data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise maximum of this field and another one. Not for
+ * use in user code. Use max(x,y) instead.
+ */
+ VectorizedArray
+ get_max (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_max_ps (data, other.data);
+ return res;
+ }
+
+ /**
+ * Returns the component-wise minimum of this field and another one. Not for
+ * use in user code. Use min(x,y) instead.
+ */
+ VectorizedArray
+ get_min (const VectorizedArray &other) const
+ {
+ VectorizedArray res;
+ res.data = _mm512_min_ps (data, other.data);
+ return res;
+ }
+
+ /**
+ * Make a few functions friends.
+ */
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::sqrt (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::abs (const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::max (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+ template <typename Number2> friend VectorizedArray<Number2>
+ std::min (const VectorizedArray<Number2> &, const VectorizedArray<Number2> &);
+};
+
+
+
+#elif DEAL_II_COMPILER_VECTORIZATION_LEVEL == 2 && defined(__AVX__)
/**
* Specialization of VectorizedArray class for double and AVX.
return *this;
}
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 32 bytes, as opposed
+ * to casting a double address to VectorizedArray<double>*.
+ */
+ void load (const double* ptr)
+ {
+ data = _mm256_loadu_pd (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 32 bytes, as opposed to casting a double address to
+ * VectorizedArray<double>*.
+ */
+ void store (double* ptr) const
+ {
+ _mm256_storeu_pd (ptr, data);
+ }
+
/**
* Actual data field. Since this class
* represents a POD data type, it remains
return *this;
}
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 32 bytes, as opposed
+ * to casting a float address to VectorizedArray<float>*.
+ */
+ void load (const float* ptr)
+ {
+ data = _mm256_loadu_ps (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 32 bytes, as opposed to casting a float address to
+ * VectorizedArray<float>*.
+ */
+ void store (float* ptr) const
+ {
+ _mm256_storeu_ps (ptr, data);
+ }
+
/**
* Actual data field. Since this class
* represents a POD data type, it remains
return *this;
}
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 16 bytes, as opposed
+ * to casting a double address to VectorizedArray<double>*.
+ */
+ void load (const double* ptr)
+ {
+ data = _mm_loadu_pd (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 16 bytes, as opposed to casting a double address to
+ * VectorizedArray<double>*.
+ */
+ void store (double* ptr) const
+ {
+ _mm_storeu_pd (ptr, data);
+ }
+
/**
* Actual data field. Since this class
* represents a POD data type, it remains
return *this;
}
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by 16 bytes, as opposed
+ * to casting a float address to VectorizedArray<float>*.
+ */
+ void load (const float* ptr)
+ {
+ data = _mm_loadu_ps (ptr);
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * 16 bytes, as opposed to casting a float address to
+ * VectorizedArray<float>*.
+ */
+ void store (float* ptr) const
+ {
+ _mm_storeu_ps (ptr, data);
+ }
+
/**
* Actual data field. Since this class
* represents a POD data type, it remains
return *this;
}
+ /**
+ * Loads @p n_array_elements from memory into the calling class, starting at
+ * the given address. The memory need not be aligned by the amount of bytes
+ * in the vectorized array, as opposed to casting a double address to
+ * VectorizedArray<double>*.
+ */
+ void load (const Number* ptr)
+ {
+ data = *ptr;
+ }
+
+ /**
+ * Writes the content of the calling class into memory in form of @p
+ * n_array_elements to the given address. The memory need not be aligned by
+ * the amount of bytes in the vectorized array, as opposed to casting a
+ * double address to VectorizedArray<double>*.
+ */
+ void store (Number* ptr) const
+ {
+ *ptr = data;
+ }
+
/**
* Actual data field. Since this class
* represents a POD data type, it is declared
-/**
- * This namespace defines the copy and set functions used in
- * AlignedVector. These functions operate in parallel when there are enough
- * elements in the vector.
- */
-namespace internal
-{
- /**
- * Move and class that actually issues the copy commands in
- * AlignedVector. This class is based on the specialized for loop base class
- * ParallelForLoop in parallel.h whose purpose is the following: When
- * calling a parallel for loop on AlignedVector with apply_to_subranges, it
- * generates different code for every different argument we might choose (as
- * it is templated). This gives a lot of code (e.g. it triples the memory
- * required for compiling the file matrix_free.cc and the final object size
- * is several times larger) which is completely useless. Therefore, this
- * class channels all copy commands through one call to apply_to_subrange
- * for all possible types, which makes the copy operation much cleaner
- * (thanks to a virtual function, whose cost is negligible in this context).
- *
- * @relates AlignedVector
- */
- template <typename T>
- class AlignedVectorMove : private parallel::ParallelForInteger
- {
- static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
- public:
- /**
- * Constructor. Issues a parallel call if
- * there are sufficiently many elements,
- * otherwise work in serial. Copies the data
- * from source to destination and then calls
- * destructor on the source. If the optional
- * argument is set to true, the source is left
- * untouched instead.
- */
- AlignedVectorMove (T *source_begin,
- T *source_end,
- T *destination,
- bool copy_only = false)
- :
- source_ (source_begin),
- destination_ (destination),
- copy_only_ (copy_only)
- {
- Assert (source_end >= source_begin, ExcInternalError());
- const std::size_t size = source_end - source_begin;
- if (size < minimum_parallel_grain_size)
- apply_to_subrange (0, size);
- else
- apply_parallel (0, size, minimum_parallel_grain_size);
- }
-
- /**
- * This method moves elements from the source
- * to the destination given in the constructor
- * on a subrange given by two integers.
- */
- virtual void apply_to_subrange (const std::size_t begin,
- const std::size_t end) const
- {
- // for classes trivial assignment can use
- // memcpy
- if (std_cxx1x::is_trivial<T>::value == true)
- std::memcpy (destination_+begin, source_+begin, (end-begin)*sizeof(T));
- else if (copy_only_ == false)
- for (std::size_t i=begin; i<end; ++i)
- {
- // initialize memory, copy, and destruct
- new (&destination_[i]) T;
- destination_[i] = source_[i];
- source_[i].~T();
- }
- else
- for (std::size_t i=begin; i<end; ++i)
- {
- new (&destination_[i]) T;
- destination_[i] = source_[i];
- }
- }
-
- private:
- T *source_;
- T *destination_;
- const bool copy_only_;
- };
-
- /**
- * Class that issues the set commands for AlignedVector.
- *
- * @relates AlignedVector
- */
- template <typename T>
- class AlignedVectorSet : private parallel::ParallelForInteger
- {
- static const std::size_t minimum_parallel_grain_size = 160000/sizeof(T)+1;
- public:
- /**
- * Constructor. Issues a parallel call if
- * there are sufficiently many elements,
- * otherwise work in serial.
- */
- AlignedVectorSet (const std::size_t size,
- const T &element,
- T *destination)
- :
- element_ (element),
- destination_ (destination),
- trivial_element (false)
- {
- if (size == 0)
- return;
-
- if (std_cxx1x::is_trivial<T>::value == true)
- {
- const unsigned char zero [sizeof(T)] = {};
- if (std::memcmp(zero, &element, sizeof(T)) == 0)
- trivial_element = true;
- }
- if (size < minimum_parallel_grain_size)
- apply_to_subrange (0, size);
- else
- apply_parallel (0, size, minimum_parallel_grain_size);
- }
-
- private:
-
- /**
- * This sets elements on a subrange given by
- * two integers.
- */
- virtual void apply_to_subrange (const std::size_t begin,
- const std::size_t end) const
- {
- // for classes with trivial assignment of zero
- // can use memset
- if (std_cxx1x::is_trivial<T>::value == true && trivial_element)
- std::memset (destination_+begin, 0, (end-begin)*sizeof(T));
- else
- for (std::size_t i=begin; i<end; ++i)
- {
- // initialize memory and set
- new (&destination_[i]) T;
- destination_[i] = element_;
- }
- }
-
- const T &element_;
- mutable T *destination_;
- bool trivial_element;
- };
-} // end of namespace internal
-
-
-/**
- * This is a replacement class for std::vector to be used in combination with
- * VectorizedArray and derived data types. It allocates memory aligned to
- * addresses of a vectorized data type (for SSE, this is necessary in order to
- * avoid segfaults, and for AVX it considerably increases performance). This
- * could also be achieved by proving std::vector with a user-defined
- * allocator. On the other hand, writing an own small vector class lets us
- * insert assertions more easily, and cut some unnecessary functionality. Note
- * that this vector is a bit more memory-consuming than std::vector because of
- * alignment, so it is recommended to only use this vector on long vectors.
- *
- * @p author Katharina Kormann, Martin Kronbichler, 2011
- */
-template < class T >
-class AlignedVector
-{
-public:
- /**
- * Declare standard types used in all
- * containers. These types parallel those
- * in the <tt>C++</tt> standard libraries
- * <tt>vector<...></tt> class.
- */
- typedef T value_type;
- typedef value_type *pointer;
- typedef const value_type *const_pointer;
- typedef value_type *iterator;
- typedef const value_type *const_iterator;
- typedef value_type &reference;
- typedef const value_type &const_reference;
- typedef std::size_t size_type;
-
- /**
- * Empty constructor. Sets the vector size to
- * zero.
- */
- AlignedVector ()
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {};
-
- /**
- * Sets the vector size to the given size and
- * initializes all elements with T().
- */
- AlignedVector (const size_type size)
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {
- if (size > 0)
- resize (size);
- }
-
- /**
- * Destructor.
- */
- ~AlignedVector ()
- {
- clear();
- }
-
- /**
- * Copy constructor.
- */
- AlignedVector (const AlignedVector<T> &vec)
- :
- _data (0),
- _end_data (0),
- _end_allocated (0)
- {
- // do not invalidate old data
- resize_fast (vec._end_data - vec._data);
- internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
- }
-
- /**
- * Assignment to the input vector @p vec.
- */
- AlignedVector &
- operator = (const AlignedVector<T> &vec)
- {
- clear();
- resize_fast (vec._end_data - vec._data);
- internal::AlignedVectorMove<T> (vec._data, vec._end_data, _data, true);
- return *this;
- }
-
- /**
- * Change the size of the vector. It keeps old
- * elements previously available but does not
- * initialize the newly allocated memory,
- * leaving it in an undefined state.
- */
- void resize_fast (const size_type size)
- {
- reserve (size);
- _end_data = _data + size;
- }
-
- /**
- * Change the size of the vector. It keeps old
- * elements previously available, and
- * initializes each element with the specified
- * data. If the new vector size is shorter
- * than the old one, the memory is not
- * released unless the new size is zero.
- */
- void resize (const size_type size_in,
- const T &init = T())
- {
- const size_type old_size = size();
- if (std_cxx1x::is_trivial<T>::value == false && size_in < old_size)
- {
- // call destructor on fields that are released
- while (_end_data != _data+size_in)
- (--_end_data)->~T();
- }
-
- resize_fast (size_in);
- // now _size is set correctly, need to set the
- // values
- if (size_in > old_size)
- internal::AlignedVectorSet<T> (size_in-old_size, init,
- _data+old_size);
- }
-
- /**
- * Reserve memory space for @p size
- * elements. If the argument @p size is set to
- * zero, all previously allocated memory is
- * released.
- *
- * In order to avoid too frequent reallocation
- * (which involves copy of the data), this
- * function doubles the amount of memory
- * occupied when the given size is larger than
- * the previously allocated size.
- */
- void reserve (const size_type size_alloc)
- {
- const size_type old_size = _end_data - _data;
- const size_type allocated_size = _end_allocated - _data;
- if (size_alloc > allocated_size)
- {
- // if we continuously increase the size of the
- // vector, we might be reallocating a lot of
- // times. therefore, try to increase the size
- // more aggressively
- size_type new_size = size_alloc;
- if (size_alloc < (2 * allocated_size))
- new_size = 2 * allocated_size;
-
- const size_type size_actual_allocate = new_size * sizeof(T);
-
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
-
- // allocate and align along boundaries of the
- // size of VectorizedArray<double>, which is
- // 16 bytes for SSE and 32 bytes for AVX
- T *new_data = static_cast<T *>(_mm_malloc (size_actual_allocate,
- sizeof(VectorizedArray<double>)));
-#else
- T *new_data = static_cast<T *>(malloc (size_actual_allocate));
-#endif
- if (new_data == 0)
- throw std::bad_alloc();
-
- // copy data in case there was some content
- // before and release the old memory with the
- // function corresponding to the one used for
- // allocating
- std::swap (_data, new_data);
- _end_data = _data + old_size;
- _end_allocated = _data + new_size;
- if (_end_data != _data)
- {
- internal::AlignedVectorMove<T>(new_data, new_data + old_size,
- _data);
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
- _mm_free(new_data);
-#else
- free(new_data);
-#endif
- }
- }
- else if (size_alloc == 0)
- clear();
- }
-
- /**
- * Releases all previously allocated memory
- * and leaves the vector in a state equivalent
- * to the state after the default constructor
- * has been called.
- */
- void clear ()
- {
- if (_data != 0)
- {
- if (std_cxx1x::is_trivial<T>::value == false)
- while (_end_data != _data)
- (--_end_data)->~T();
-
-#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
- _mm_free(_data);
-#else
- free(_data);
-#endif
- }
- _data = 0;
- _end_data = 0;
- _end_allocated = 0;
- };
-
- /**
- * Inserts an element at the end of the
- * vector, increasing the vector size by
- * one. Note that the allocated size will
- * double whenever the previous space is not
- * enough to hold the new element.
- */
- void push_back (const T in_data)
- {
- Assert (_end_data <= _end_allocated, ExcInternalError());
- if (_end_data == _end_allocated)
- reserve (std::max(2*capacity(),static_cast<size_type>(16)));
- if (std_cxx1x::is_trivial<T>::value == false)
- new (_end_data) T;
- *_end_data++ = in_data;
- }
-
- /**
- * Returns the last element of the vector
- * (read and write access).
- */
- reference back ()
- {
- AssertIndexRange (0, size());
- T *field = _end_data - 1;
- return *field;
- }
-
- /**
- * Returns the last element of the vector
- * (read-only access).
- */
- const_reference back () const
- {
- AssertIndexRange (0, size());
- const T *field = _end_data - 1;
- return *field;
- }
-
- /**
- * Inserts several elements at the end of the
- * vector given by a range of elements.
- */
- template <typename ForwardIterator>
- void insert_back (ForwardIterator begin,
- ForwardIterator end)
- {
- const unsigned int old_size = size();
- reserve (old_size + (end-begin));
- for ( ; begin != end; ++begin, ++_end_data)
- {
- if (std_cxx1x::is_trivial<T>::value == false)
- new (_end_data) T;
- *_end_data = *begin;
- }
- }
-
- /**
- * Swaps the given vector with the calling
- * vector.
- */
- void swap (AlignedVector<T> &vec)
- {
- std::swap (_data, vec._data);
- std::swap (_end_data, vec._end_data);
- std::swap (_end_allocated, vec._end_allocated);
- }
-
- /**
- * Returns the size of the vector.
- */
- size_type size () const
- {
- return _end_data - _data;
- }
-
- /**
- * Returns the capacity of the vector, i.e.,
- * the size this vector can hold without
- * reallocation. Note that capacity() >=
- * size().
- */
- size_type capacity () const
- {
- return _end_allocated - _data;
- }
-
- /**
- * Read-write access to entry @p index in the
- * vector.
- */
- reference
- operator [] (const size_type index)
- {
- AssertIndexRange (index, size());
- return _data[index];
- };
-
- /**
- * Read-only access to entry @p index in the
- * vector.
- */
- const_reference operator [] (const size_type index) const
- {
- AssertIndexRange (index, size());
- return _data[index];
- };
-
- /**
- * Returns a read and write pointer to the
- * beginning of the data array.
- */
- iterator begin ()
- {
- return _data;
- }
-
- /**
- * Returns a read and write pointer to the
- * end of the data array.
- */
- iterator end ()
- {
- return _end_data;
- }
-
- /**
- * Returns a read-only pointer to the
- * beginning of the data array.
- */
- const_iterator begin () const
- {
- return _data;
- }
-
- /**
- * Returns a read-only pointer to the
- * end of the data array.
- */
- const_iterator end () const
- {
- return _end_data;
- }
-
- /**
- * Returns the memory consumption of the
- * allocated memory in this class. If the
- * underlying type @p T allocates memory by
- * itself, this memory is not counted.
- */
- size_type memory_consumption () const
- {
- size_type memory = sizeof(this);
- memory += sizeof(T) * capacity();
- return memory;
- }
-
-private:
-
- /**
- * Pointer to actual class data.
- */
- T *_data;
-
- /**
- * Pointer to the end of valid data fields.
- */
- T *_end_data;
-
- /**
- * Pointer to the end of the allocated memory.
- */
- T *_end_allocated;
-};
-
-
DEAL_II_NAMESPACE_CLOSE
namespace std
{
/**
- * Computes the sine of a vectorized data field. The result is return as
+ * Computes the sine of a vectorized data field. The result is returned as
* vectorized array in the form <tt>{sin(x[0]), sin(x[1]), ...,
* sin(x[n_array_elements-1])}</tt>.
*
::dealii::VectorizedArray<Number>
sin (const ::dealii::VectorizedArray<Number> &x)
{
- ::dealii::VectorizedArray<Number> sin_val;
+ // put values in an array and later read in that array with an unaligned
+ // read. This should safe some instructions as compared to directly
+ // setting the individual elements and also circumvents a compiler
+ // optimization bug in gcc-4.6 (see also deal.II developers list from
+ // April 2014, topic "matrix_free/step-48 Test").
+ Number values[::dealii::VectorizedArray<Number>::n_array_elements];
for (unsigned int i=0; i<dealii::VectorizedArray<Number>::n_array_elements; ++i)
- sin_val[i] = std::sin(x[i]);
- return sin_val;
+ values[i] = std::sin(x[i]);
+ ::dealii::VectorizedArray<Number> out;
+ out.load(&values[0]);
+ return out;
}
/**
- * Computes the tangent of a vectorized data field. The result is return as
- * vectorized array in the form <tt>{tan(x[0]), tan(x[1]), ...,
- * tan(x[n_array_elements-1])}</tt>.
+ * Computes the cosine of a vectorized data field. The result is returned as
+ * vectorized array in the form <tt>{cos(x[0]), cos(x[1]), ...,
+ * cos(x[n_array_elements-1])}</tt>.
*
* @relates VectorizedArray
*/
template <typename Number>
inline
::dealii::VectorizedArray<Number>
- tan (const ::dealii::VectorizedArray<Number> &x)
+ cos (const ::dealii::VectorizedArray<Number> &x)
{
- ::dealii::VectorizedArray<Number> tan_val;
+ Number values[::dealii::VectorizedArray<Number>::n_array_elements];
for (unsigned int i=0; i<dealii::VectorizedArray<Number>::n_array_elements; ++i)
- tan_val[i] = std::tan(x[i]);
- return tan_val;
+ values[i] = std::cos(x[i]);
+ ::dealii::VectorizedArray<Number> out;
+ out.load(&values[0]);
+ return out;
}
+
/**
- * Computes the cosine of a vectorized data field. The result is return as
- * vectorized array in the form <tt>{cos(x[0]), cos(x[1]), ...,
- * cos(x[n_array_elements-1])}</tt>.
+ * Computes the tangent of a vectorized data field. The result is returned as
+ * vectorized array in the form <tt>{tan(x[0]), tan(x[1]), ...,
+ * tan(x[n_array_elements-1])}</tt>.
*
* @relates VectorizedArray
*/
template <typename Number>
inline
::dealii::VectorizedArray<Number>
- cos (const ::dealii::VectorizedArray<Number> &x)
+ tan (const ::dealii::VectorizedArray<Number> &x)
{
- ::dealii::VectorizedArray<Number> cos_val;
+ Number values[::dealii::VectorizedArray<Number>::n_array_elements];
for (unsigned int i=0; i<dealii::VectorizedArray<Number>::n_array_elements; ++i)
- cos_val[i] = std::cos(x[i]);
- return cos_val;
+ values[i] = std::tan(x[i]);
+ ::dealii::VectorizedArray<Number> out;
+ out.load(&values[0]);
+ return out;
}
+
/**
- * Computes the exponential of a vectorized data field. The result is return
+ * Computes the exponential of a vectorized data field. The result is returned
* as vectorized array in the form <tt>{exp(x[0]), exp(x[1]), ...,
* exp(x[n_array_elements-1])}</tt>.
*
::dealii::VectorizedArray<Number>
exp (const ::dealii::VectorizedArray<Number> &x)
{
- ::dealii::VectorizedArray<Number> exp_val;
+ Number values[::dealii::VectorizedArray<Number>::n_array_elements];
for (unsigned int i=0; i<dealii::VectorizedArray<Number>::n_array_elements; ++i)
- exp_val[i] = std::exp(x[i]);
- return exp_val;
+ values[i] = std::exp(x[i]);
+ ::dealii::VectorizedArray<Number> out;
+ out.load(&values[0]);
+ return out;
}
+
/**
* Computes the natural logarithm of a vectorized data field. The result is
- * return as vectorized array in the form <tt>{log(x[0]), log(x[1]), ...,
+ * returned as vectorized array in the form <tt>{log(x[0]), log(x[1]), ...,
* log(x[n_array_elements-1])}</tt>.
*
* @relates VectorizedArray
::dealii::VectorizedArray<Number>
log (const ::dealii::VectorizedArray<Number> &x)
{
- ::dealii::VectorizedArray<Number> log_val;
+ Number values[::dealii::VectorizedArray<Number>::n_array_elements];
for (unsigned int i=0; i<dealii::VectorizedArray<Number>::n_array_elements; ++i)
- log_val[i] = std::log(x[i]);
- return log_val;
+ values[i] = std::log(x[i]);
+ ::dealii::VectorizedArray<Number> out;
+ out.load(&values[0]);
+ return out;
}
/**
- * Computes the square root of a vectorized data field. The result is return
+ * Computes the square root of a vectorized data field. The result is returned
* as vectorized array in the form <tt>{sqrt(x[0]), sqrt(x[1]), ...,
* sqrt(x[n_array_elements-1])}</tt>.
*
/**
* Computes the absolute value (modulus) of a vectorized data field. The
- * result is return as vectorized array in the form <tt>{abs(x[0]),
+ * result is returned as vectorized array in the form <tt>{abs(x[0]),
* abs(x[1]), ..., abs(x[n_array_elements-1])}</tt>.
*
* @relates VectorizedArray
/**
* Computes the componentwise maximum of two vectorized data fields. The
- * result is return as vectorized array in the form <tt>{max(x[0],y[0]),
+ * result is returned as vectorized array in the form <tt>{max(x[0],y[0]),
* max(x[1],y[1]), ...}</tt>.
*
* @relates VectorizedArray
/**
* Computes the componentwise minimum of two vectorized data fields. The
- * result is return as vectorized array in the form <tt>{min(x[0],y[0]),
+ * result is returned as vectorized array in the form <tt>{min(x[0],y[0]),
* min(x[1],y[1]), ...}</tt>.
*
* @relates VectorizedArray
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2009 - 2013 by the deal.II authors
+// Copyright (C) 2009 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
parallel::distributed::SolutionTransfer<dim,VECTOR> sol_trans(dof_handler);
sol_trans.deserialize (distributed_vector);
@endcode
+ *
+ *
+ * <h3>Interaction with hanging nodes</h3>
+ *
+ * In essence, this class implements the same steps as does
+ * dealii::SolutionTransfer (though the implementation is entirely
+ * separate). Consequently, the same issue with hanging nodes and
+ * coarsening can happen with this class as happens with
+ * dealii::SolutionTransfer. See there for an extended discussion.
*
* @ingroup distributed
* @author Timo Heister, 2009-2011
void prepare_for_coarsening_and_refinement (const VECTOR &in);
/**
- *
+ * Interpolate the data previously stored in this object before
+ * the mesh was refined or coarsened onto the current set of
+ * cells. Do so for each of the vectors provided to
+ * prepare_for_coarsening_and_refinement() and write the result into
+ * the given set of vectors.
*/
void interpolate (std::vector<VECTOR *> &all_out);
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
class Triangulation : public dealii::Triangulation<dim,spacedim>
{
public:
+ /**
+ * A typedef that is used to to identify cell iterators. The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies cells in a triangulation. You
+ * can find the exact type it refers to in the base class's own
+ * typedef, but it should be TriaIterator<CellAccessor<dim,spacedim> >. The
+ * TriaIterator class works like a pointer that when you
+ * dereference it yields an object of type CellAccessor.
+ * CellAccessor is a class that identifies properties that
+ * are specific to cells in a triangulation, but it is derived
+ * (and consequently inherits) from TriaAccessor that describes
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation.
+ *
+ * @ingroup Iterators
+ */
+ typedef typename dealii::Triangulation<dim,spacedim>::cell_iterator cell_iterator;
+
/**
- * Import the various
- * iterator typedefs from the
- * base class.
+ * A typedef that is used to to identify
+ * @ref GlossActive "active cell iterators". The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies active cells in a triangulation. You
+ * can find the exact type it refers to in the base class's own
+ * typedef, but it should be TriaActiveIterator<CellAccessor<dim,spacedim> >. The
+ * TriaActiveIterator class works like a pointer to active objects that when you
+ * dereference it yields an object of type CellAccessor.
+ * CellAccessor is a class that identifies properties that
+ * are specific to cells in a triangulation, but it is derived
+ * (and consequently inherits) from TriaAccessor that describes
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation.
+ *
+ * @ingroup Iterators
*/
typedef typename dealii::Triangulation<dim,spacedim>::active_cell_iterator active_cell_iterator;
- typedef typename dealii::Triangulation<dim,spacedim>::cell_iterator cell_iterator;
/**
* Generic settings for distributed Triangulations. If
* cells owned by each processor. This equals the overall number
* of active cells in the distributed triangulation.
*/
- types::global_dof_index n_global_active_cells () const;
+ virtual types::global_dof_index n_global_active_cells () const;
/**
- * Returns the global maximum level. This may be bigger than n_levels.
+ * Returns the global maximum level. This may be bigger than
+ * the number dealii::Triangulation::n_levels() (a function in this
+ * class's base class) returns if the current processor only stores
+ * cells in parts of the domain that are not very refined, but
+ * if other processors store cells in more deeply refined parts of
+ * the domain.
*/
virtual unsigned int n_global_levels () const;
+ /**
+ * Returns true if the triangulation has hanging nodes.
+ *
+ * In the context of parallel distributed triangulations, every
+ * processor stores only that part of the triangulation it
+ * locally owns. However, it also stores the entire coarse
+ * mesh, and to guarantee the 2:1 relationship between cells,
+ * this may mean that there are hanging nodes between cells that
+ * are not locally owned or ghost cells (i.e., between ghost cells
+ * and artificial cells, or between artificial and artificial cells;
+ * see @ref GlossArtificialCell "the glossary").
+ * One is not typically interested in this case, so the function
+ * returns whether there are hanging nodes between any two cells
+ * of the "global" mesh, i.e., the union of locally owned cells
+ * on all processors.
+ */
+ virtual
+ bool has_hanging_nodes() const;
+
/**
* Return the number of active cells owned by each of the MPI
* processes that contribute to this triangulation. The element
void save(const char *filename) const;
/**
- * Load the refinement information saved with save() back in. The mesh
- * must contain the same coarse mesh that was used in save() before calling
- * this function. You do not
- * need to load with the same number of MPI processes that you saved
- * with. Rather, if a mesh is loaded with a different number of MPI
- * processes than used at the time of saving, the mesh is repartitioned
- * appropriately. Cell-based data that was saved with register_data_attach()
- * can be read in with notify_ready_to_unpack() after calling load().
- */
- void load(const char *filename);
+ * Load the refinement information saved with save() back in. The
+ * mesh must contain the same coarse mesh that was used in save()
+ * before calling this function.
+ *
+ * You do not need to load with the same number of MPI processes that
+ * you saved with. Rather, if a mesh is loaded with a different
+ * number of MPI processes than used at the time of saving, the mesh
+ * is repartitioned appropriately. Cell-based data that was saved
+ * with register_data_attach() can be read in with
+ * notify_ready_to_unpack() after calling load().
+ *
+ * If you use p4est version > 0.3.4.2 the @p autopartition flag tells
+ * p4est to ignore the partitioning that the triangulation had when
+ * it was saved and make it uniform upon loading. If @p autopartition
+ * is set to false, the triangulation is only repartitioned if needed
+ * (i.e. if a different number of MPI processes is encountered).
+ */
+ void load(const char *filename,
+ const bool autopartition = true);
/**
* Used to inform in the callbacks of register_data_attach() and
*/
static bool is_level_cell();
- /**
- * Return an iterator pointing to the the parent.
- */
- TriaIterator<DoFAccessor<structdim,DH, level_dof_access> >
- parent () const;
-
/**
* @name Accessing sub-objects
*/
*/
void copy_from (const TriaAccessorBase<0, 1, spacedim> &da);
- /**
- * Return an iterator pointing to the the parent.
- */
- TriaIterator<DoFAccessor<0,DH<1,spacedim>, level_dof_access> >
- parent () const;
-
/**
* @name Accessing sub-objects
*/
*/
/**
- * Return the parent as a DoF cell iterator. This function is needed
- * since the parent function of the base class returns a cell
- * accessor without access to the DoF data.
+ * Return the parent of this cell as a DoF cell iterator.
+ * If the parent does not exist (i.e., if the object is at the coarsest level of
+ * the mesh hierarchy), an exception is generated.
+ *
+ * This function is needed
+ * since the parent function of the base class CellAccessor returns a triangulation
+ * cell accessor without access to the DoF data.
*/
TriaIterator<DoFCellAccessor<DH, level_dof_access> >
parent () const;
}
-template <int structdim, class DH, bool level_dof_access>
-inline
-TriaIterator<DoFAccessor<structdim,DH,level_dof_access> >
-DoFAccessor<structdim,DH,level_dof_access>::parent () const
-{
- Assert (static_cast<unsigned int>(this->level()) < this->dof_handler->levels.size(),
- ExcMessage ("DoFHandler not initialized"));
- Assert (this->level () > 0,
- ExcMessage ("Cell is at coarsest level."));
-
- int previous_level;
-
- if (DH::dimension==structdim)
- previous_level = this->level () - 1;
-
- else
- previous_level = 0;
-
- TriaIterator<DoFAccessor<structdim,DH,level_dof_access> > q (this->tria,
- previous_level,
- this->parent_index (),
- this->dof_handler);
-
- return q;
-}
-
-
-
namespace internal
{
namespace DoFAccessor
const unsigned int n_dofs = local_source_end - local_source_begin;
-//TODO[WB/MK]: This function could me made more efficient because it allocates memory, which could be avoided by passing in another argument as a scratch array. This should be fixed eventually
+//TODO[WB/MK]: This function could me made more efficient because it allocates memory, which could be avoided by passing in another argument as a scratch array. This should be fixed eventually. another option would be to let the surrounding class have a (static, mutable) scratch array that is thread-local
// get indices of dofs
std::vector<types::global_dof_index> dofs (n_dofs);
typedef typename ActiveSelector::hex_iterator hex_iterator;
typedef typename ActiveSelector::active_hex_iterator active_hex_iterator;
+ /**
+ * A typedef that is used to to identify
+ * @ref GlossActive "active cell iterators". The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies active cells in a DoFHandler object.
+ * While the actual data type of the typedef is hidden behind a few layers
+ * of (unfortunately necessary) indirections, it is in essence
+ * TriaActiveIterator<DoFCellAccessor>. The TriaActiveIterator
+ * class works like a pointer to active objects that when you
+ * dereference it yields an object of type DoFCellAccessor.
+ * DoFCellAccessor is a class that identifies properties that
+ * are specific to cells in a DoFHandler, but it is derived
+ * (and consequently inherits) from both DoFAccessor, TriaCellAccessor
+ * and TriaAccessor that describe
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation and DoFHandler objects.
+ *
+ * @ingroup Iterators
+ */
typedef typename ActiveSelector::active_cell_iterator active_cell_iterator;
+ /**
+ * A typedef that is used to to identify cell iterators. The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies cells in a DoFHandler object. Some
+ * of these cells may in fact be active (see @ref GlossActive "active cell iterators")
+ * in which case they can in fact be asked for the degrees of freedom
+ * that live on them. On the other hand, if the cell is not active,
+ * any such query will result in an error. Note that this is what distinguishes
+ * this typedef from the level_cell_iterator typedef.
+ *
+ * While the actual data type of the typedef is hidden behind a few layers
+ * of (unfortunately necessary) indirections, it is in essence
+ * TriaIterator<DoFCellAccessor>. The TriaIterator
+ * class works like a pointer to objects that when you
+ * dereference it yields an object of type DoFCellAccessor.
+ * DoFCellAccessor is a class that identifies properties that
+ * are specific to cells in a DoFHandler, but it is derived
+ * (and consequently inherits) from both DoFAccessor, TriaCellAccessor
+ * and TriaAccessor that describe
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation and DoFHandler objects.
+ *
+ * @ingroup Iterators
+ */
+ typedef typename ActiveSelector::cell_iterator cell_iterator;
+
typedef typename ActiveSelector::face_iterator face_iterator;
typedef typename ActiveSelector::active_face_iterator active_face_iterator;
typedef typename LevelSelector::cell_iterator level_cell_iterator;
typedef typename LevelSelector::face_iterator level_face_iterator;
- typedef typename ActiveSelector::cell_iterator cell_iterator;
/**
* Alias the @p FunctionMap type
/**
* Renumber the degrees of freedom according to the Cuthill-McKee method,
- * eventually using the reverse numbering scheme.
+ * possibly using the reverse numbering scheme.
*
* See the general documentation of this class for details on the different
* methods.
* As an example of the results of this algorithm, take a look at the
* comparison of various algorithms in the documentation of the
* DoFRenumbering namespace.
+ *
+ * If the given DoFHandler uses a distributed triangulation (i.e., if
+ * dof_handler.locally_owned() is not the complete index set), the
+ * renumbering is performed on each processor's degrees of freedom
+ * individually.
*/
template <class DH>
void
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* works on algebraic properties of the respective matrix, it has no
* chance to detect whether the matrix comes from a scalar or a
* vector valued problem. However, a near null space supplies
- * exactly the needed information about these components. The null
- * space will consist of as many vectors as there are true arguments
- * in <tt>component_mask</tt> (see @ref GlossComponentMask), each of
- * which will be one in one vector component and zero in all
- * others. We store this object in a vector of vectors, where the
- * outer vector is of the size of the number of selected components,
- * and each inner vector has as many components as there are
- * (locally owned) degrees of freedom in the selected
- * components. Note that any matrix associated with this null space
+ * exactly the needed information about the components placement of vector
+ * components within the matrix. The null space (or rather, the constant
+ * modes) is provided by the finite element underlying the given DoFHandler
+ * and for most elements, the null space will consist of as many vectors as
+ * there are true arguments in <tt>component_mask</tt> (see @ref
+ * GlossComponentMask), each of which will be one in one vector component
+ * and zero in all others. However, the representation of the constant
+ * function for e.g. FE_DGP is different (the first component on each
+ * element one, all other components zero), and some scalar elements may
+ * even have two constant modes (FE_Q_DG0). Therefore, we store this object
+ * in a vector of vectors, where the outer vector contains the collection of
+ * the actual constant modes on the DoFHandler. Each inner vector has as
+ * many components as there are (locally owned) degrees of freedom in the
+ * selected components. Note that any matrix associated with this null space
* must have been constructed using the same <tt>component_mask</tt>
- * argument, since the numbering of DoFs is done relative to the
- * selected dofs, not to all dofs.
+ * argument, since the numbering of DoFs is done relative to the selected
+ * dofs, not to all dofs.
*
* The main reason for this program is the use of the null space
* with the AMG preconditioner.
* This function generates a matrix such that when a vector of data
* with as many elements as there are degrees of freedom of this
* component on the coarse grid is multiplied to this matrix, we
- * obtain a vector with as many elements are there are global
+ * obtain a vector with as many elements as there are global
* degrees of freedom on the fine grid. All the elements of the
* other components of the finite element fields on the fine grid
* are not touched.
/**
- * Declare a data type which denotes a mapping between a boundary indicator
- * and the function denoting the boundary values on this part of the
- * boundary. This type is required in many functions where depending on the
- * boundary indicator, different functions are used. An example is boundary
- * value interpolation.
+ * This class declares a local typedef that denotes a mapping between a boundary indicator
+ * (see @ref GlossBoundaryIndicator) that is used to describe what kind of boundary
+ * condition holds on a particular piece of the boundary,
+ * and the function describing the actual function that provides the boundary
+ * values on this part of the boundary. This type is required in many functions
+ * in the library where, for example, we need to know about the functions $h_i(\mathbf x)$
+ * used in boundary conditions
+ * @f{align*}
+ * \mathbf n \cdot \nabla u = h_i \qquad \qquad \text{on}\ \Gamma_i\subset\partial\Omega.
+ * @f}
+ * An example is the function KellyErrorEstimator::estimate() that allows us
+ * to provide a set of functions $h_i$ for all those boundary indicators $i$ for
+ * which the boundary condition is supposed to be of Neumann type. Of course,
+ * the same kind of principle can be applied to cases where we care about
+ * Dirichlet values, where one needs to provide a map from boundary indicator $i$
+ * to Dirichlet function $h_i$ if the boundary conditions are given as
+ * @f{align*}
+ * u = h_i \qquad \qquad \text{on}\ \Gamma_i\subset\partial\Omega.
+ * @f}
+ * This is, for example, the case for the VectorTools::interpolate() functions.
+ *
+ * Tutorial programs step-6, step-7 and step-8 show examples of how to use
+ * function arguments of this type in situations where we actually have an empty
+ * map (i.e., we want to describe that <i>no</i> part of the boundary is a
+ * Neumann boundary). step-16 actually uses it in a case where one of the
+ * parts of the boundary uses a boundary indicator for which we want to use
+ * a function object.
*
* It seems odd at first to declare this typedef inside a class, rather than
* declaring a typedef at global scope. The reason is that C++ does not allow
* to define templated typedefs, where here in fact we want a typdef that
- * depends on the space dimension.
+ * depends on the space dimension. (Defining templated typedefs is something that
+ * is possible starting with the C++11 standard, but that wasn't possible within
+ * the C++98 standard in place when this programming pattern was conceived.)
*
* @ingroup functions
* @author Wolfgang Bangerth, Ralf Hartmann, 2001
ComponentMask (const unsigned int n_components,
const bool initializer);
+ /**
+ * Set a particular entry in the mask to a value.
+ */
+ void set (const unsigned int index, const bool value);
+
/**
* If this component mask has been initialized with a mask of
* size greater than zero, then return the size of the mask
}
+inline
+void
+ComponentMask::set(const unsigned int index, const bool value)
+{
+ AssertIndexRange(index, component_mask.size());
+ component_mask[index] = value;
+}
+
+
inline
bool
ComponentMask::operator [](const unsigned int component_index) const
{
// otherwise check the validity of the index and
// return whatever is appropriate
- Assert (component_index < component_mask.size(),
- ExcIndexRange (component_index, 0, component_mask.size()));
+ AssertIndexRange (component_index, component_mask.size());
return component_mask[component_index];
}
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/fe/fe_values_extractors.h>
#include <deal.II/fe/component_mask.h>
#include <deal.II/fe/block_mask.h>
-
+#include <deal.II/fe/mapping.h>
DEAL_II_NAMESPACE_OPEN
const Point<dim> &p,
const unsigned int component) const;
/**
- * Check for non-zero values on a face in order to optimize out matrix
- * elements.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
+ * non-zero function values somewhere on the face @p face_index. The
+ * function is typically used to determine whether some matrix elements
+ * resulting from face integrals can be assumed to be zero and may therefore
+ * be omitted from integration.
*
- * A default implementation is provided in this basis class which always
+ * A default implementation is provided in this basa class which always
* returns @p true. This is the safe way to go.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
block_mask (const ComponentMask &component_mask) const;
/**
- * Returns a list of constant modes of the element. The returns table has as
- * many rows as there are components in the element and dofs_per_cell
- * columns. To each component of the finite element, the row in the returned
- * table contains a basis representation of the constant function 1 on the
- * element.
+ * Returns a list of constant modes of the element. The number of rows in
+ * the resulting table depends on the elements in use. For standard
+ * elements, the table has as many rows as there are components in the
+ * element and dofs_per_cell columns. To each component of the finite
+ * element, the row in the returned table contains a basis representation of
+ * the constant function 1 on the element. However, there are some scalar
+ * elements where there is more than one constant mode, e.g. the element
+ * FE_Q_DG0.
+ *
+ * In order to match the constant modes to the actual components in the
+ * element, the returned data structure also returns a vector with as many
+ * components as there are constant modes on the element that contains the
+ * component number.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>,std::vector<unsigned int> >
+ get_constant_modes () const;
//@}
* requirement that they be one at a certain point and zero at all the
* points associated with the other shape functions.
*
- * In composed elements (i.e. for the FESystem class, the result will be
- * true if all all the base elements have defined support points.
+ * In composed elements (i.e. for the FESystem class), the result will be
+ * true if all all the base elements have defined support points. FE_Nothing
+ * is a special case in FESystems, because it has 0 support points and
+ * has_support_points() is false, but an FESystem containing an FE_Nothing
+ * among other elements will return true.
*/
bool has_support_points () const;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2003 - 2013 by the deal.II authors
+// Copyright (C) 2003 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
virtual std::string get_name () const;
/**
- * Check whether a shape function
- * may be non-zero on a face.
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*
- * Right now, this is only
- * implemented for RT0 in
- * 1D. Otherwise, returns always
- * @p true.
+ * Right now, this is only implemented for RT0 in 1D. Otherwise, returns
+ * always @p true.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
#include <deal.II/base/vector_slice.h>
#include <deal.II/base/geometry_info.h>
#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/block_indices.h>
#include <deal.II/fe/fe_update_flags.h>
-#include <deal.II/fe/mapping.h>
#include <string>
#include <vector>
*
* @param dofs_per_object Number of dofs on geometrical objects for each
* dimension. In this vector, entry 0 refers to dofs on vertices, entry 1 on
- * lines and so on. Its length must be <i>dim+1</i>. @param n_components
- * Number of vector components of the element. @param degree Maximal
- * polynomial degree in a single direction. @param conformity The finite
- * element space has continuity of this Sobolev space. @param n_blocks
- * obsolete and ignored.
+ * lines and so on. Its length must be <i>dim+1</i>.
+ *
+ * @param n_components Number of vector components of the element.
+ *
+ * @param degree Maximal polynomial degree in a single direction.
+ *
+ * @param conformity The finite element space has continuity of this Sobolev
+ * space.
+ *
+ * @param n_blocks obsolete and ignored.
*/
FiniteElementData (const std::vector<unsigned int> &dofs_per_object,
const unsigned int n_components,
*
* @todo This is for 2D only.
*
- * @todo Transformation works only for uniform, Cartesian meshes.
+ * @todo Restriction matrices are missing.
*
* The matching pressure space for FE_BDM of order <i>k</i> is the
* element FE_DGP of order <i>k</i>.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2010 - 2013 by the deal.II authors
+// Copyright (C) 2010 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * Check whether a shape function
- * may be non-zero on a face.
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*
- * Returns always
- * @p true.
+ * For this element, we always return @p true.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2006 - 2013 by the deal.II authors
+// Copyright (C) 2006 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
template <class POLY, int dim, int spacedim>
bool
-FE_DGVector<POLY,dim,spacedim>::has_support_on_face (
- const unsigned int,
- const unsigned int) const
+FE_DGVector<POLY,dim,spacedim>::has_support_on_face (const unsigned int,
+ const unsigned int) const
{
return true;
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
FullMatrix<double> &matrix) const;
/**
- * Check for non-zero values on a face.
- *
- * This function returns
- * @p true, if the shape
- * function @p shape_index has
- * non-zero values on the face
- * @p face_index.
- *
- * Implementation of the
- * interface in
- * FiniteElement
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* Returns a list of constant modes of the element. For this element, the
* first entry is true, all other are false.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
protected:
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2004 - 2013 by the deal.II authors
+// Copyright (C) 2004 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
FullMatrix<double> &matrix) const;
/**
- * Check for non-zero values on a face.
- *
- * This function returns
- * @p true, if the shape
- * function @p shape_index has
- * non-zero values on the face
- * @p face_index.
- *
- * Implementation of the
- * interface in
- * FiniteElement
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*/
/**
- * Check for non-zero values on a face.
- *
- * This function returns
- * @p true, if the shape
- * function @p shape_index has
- * non-zero values on the face
- * @p face_index.
- *
- * Implementation of the
- * interface in
- * FiniteElement
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2001 - 2013 by the deal.II authors
+// Copyright (C) 2001 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/config.h>
#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/base/thread_management.h>
#include <deal.II/fe/fe_poly.h>
DEAL_II_NAMESPACE_OPEN
const unsigned int subface,
FullMatrix<double> &matrix) const;
+ /**
+ * Projection from a fine grid space onto a coarse grid space. Overrides the
+ * respective method in FiniteElement, implementing lazy evaluation
+ * (initialize when requested).
+ *
+ * If this projection operator is associated with a matrix @p P, then the
+ * restriction of this matrix @p P_i to a single child cell is returned
+ * here.
+ *
+ * The matrix @p P is the concatenation or the sum of the cell matrices @p
+ * P_i, depending on the #restriction_is_additive_flags. This distinguishes
+ * interpolation (concatenation) and projection with respect to scalar
+ * products (summation).
+ *
+ * Row and column indices are related to coarse grid and fine grid spaces,
+ * respectively, consistent with the definition of the associated operator.
+ */
+ virtual const FullMatrix<double> &
+ get_restriction_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case=RefinementCase<dim>::isotropic_refinement) const;
+
+ /**
+ * Embedding matrix between grids. Overrides the respective method in
+ * FiniteElement, implementing lazy evaluation (initialize when queried).
+ *
+ * The identity operator from a coarse grid space into a fine grid space is
+ * associated with a matrix @p P. The restriction of this matrix @p P_i to a
+ * single child cell is returned here.
+ *
+ * The matrix @p P is the concatenation, not the sum of the cell matrices @p
+ * P_i. That is, if the same non-zero entry <tt>j,k</tt> exists in in two
+ * different child matrices @p P_i, the value should be the same in both
+ * matrices and it is copied into the matrix @p P only once.
+ *
+ * Row and column indices are related to fine grid and coarse grid spaces,
+ * respectively, consistent with the definition of the associated operator.
+ *
+ * These matrices are used by routines assembling the prolongation matrix
+ * for multi-level methods. Upon assembling the transfer matrix between
+ * cells using this matrix array, zero elements in the prolongation matrix
+ * are discarded and will not fill up the transfer matrix.
+ */
+ virtual const FullMatrix<double> &
+ get_prolongation_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case=RefinementCase<dim>::isotropic_refinement) const;
+
/**
* @name Functions to support hp
* @{
*/
/**
- * Check for non-zero values on a face.
- *
- * This function returns
- * @p true, if the shape
- * function @p shape_index has
- * non-zero values on the face
- * @p face_index.
- *
- * Implementation of the
- * interface in
- * FiniteElement
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* Returns a list of constant modes of the element. For this element, it
* simply returns one row with all entries set to true.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
/**
* Determine an estimate for the
void rotate_indices (std::vector<unsigned int> &indices,
const char direction) const;
+ /*
+ * Mutex for protecting initialization of restriction and embedding matrix.
+ */
+ mutable Threads::Mutex mutex;
+
/**
* Allow access from other dimensions.
*/
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2009 - 2013 by the deal.II authors
+// Copyright (C) 2009 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
FullMatrix<double> &matrix) const;
/**
- * Check for non-zero values on a face.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
- *
- * Implementation of the interface in FiniteElement
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
FiniteElementDomination::Domination
compare_for_face_domination (const FiniteElement<dim,spacedim> &fe_other) const;
-
/**
* Returns a list of constant modes of the element. For this element, it
* simply returns one row with all entries set to true.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
private:
/**
+/**
+ * Specialization of FE_FaceQ for 1D. In that case, the finite element only
+ * consists of one degree of freedom in each of the two faces (= vertices) of
+ * a cell, irrespective of the degree. However, this element still accepts a
+ * degree in its constructor and also returns that degree. This way,
+ * dimension-independent programming with trace elements is also possible in
+ * 1D (even though there is no computational benefit at all from it in 1D).
+ *
+ * @ingroup fe
+ * @author Guido Kanschat, Martin Kronbichler
+ * @date 2014
+ */
+template <int spacedim>
+class FE_FaceQ<1,spacedim> : public FiniteElement<1,spacedim>
+{
+public:
+ /**
+ * Constructor.
+ */
+ FE_FaceQ (const unsigned int p);
+
+ /**
+ * Clone method.
+ */
+ virtual FiniteElement<1,spacedim> *clone() const;
+
+ /**
+ * Return a string that uniquely identifies a finite element. This class
+ * returns <tt>FE_FaceQ<dim>(degree)</tt>, with <tt>dim</tt> and
+ * <tt>degree</tt> replaced by appropriate values.
+ */
+ virtual std::string get_name () const;
+
+ /**
+ * Return the matrix interpolating from a face of of one element to the face
+ * of the neighboring element. The size of the matrix is then
+ * <tt>source.dofs_per_face</tt> times <tt>this->dofs_per_face</tt>. This
+ * element only provides interpolation matrices for elements of the same
+ * type and FE_Nothing. For all other elements, an exception of type
+ * FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented is thrown.
+ */
+ virtual void
+ get_face_interpolation_matrix (const FiniteElement<1,spacedim> &source,
+ FullMatrix<double> &matrix) const;
+
+ /**
+ * Return the matrix interpolating from a face of of one element to the face
+ * of the neighboring element. The size of the matrix is then
+ * <tt>source.dofs_per_face</tt> times <tt>this->dofs_per_face</tt>. This
+ * element only provides interpolation matrices for elements of the same
+ * type and FE_Nothing. For all other elements, an exception of type
+ * FiniteElement<dim,spacedim>::ExcInterpolationNotImplemented is thrown.
+ */
+ virtual void
+ get_subface_interpolation_matrix (const FiniteElement<1,spacedim> &source,
+ const unsigned int subface,
+ FullMatrix<double> &matrix) const;
+
+ /**
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
+ */
+ virtual bool has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const;
+
+ /**
+ * Return whether this element implements its hanging node constraints in
+ * the new way, which has to be used to make elements "hp compatible".
+ */
+ virtual bool hp_constraints_are_implemented () const;
+
+ /**
+ * Return whether this element dominates the one given as argument when they
+ * meet at a common face, whether it is the other way around, whether
+ * neither dominates, or if either could dominate.
+ *
+ * For a definition of domination, see FiniteElementBase::Domination and in
+ * particular the @ref hp_paper "hp paper".
+ */
+ virtual
+ FiniteElementDomination::Domination
+ compare_for_face_domination (const FiniteElement<1,spacedim> &fe_other) const;
+
+ /**
+ * Returns a list of constant modes of the element. For this element, it
+ * simply returns one row with all entries set to true.
+ */
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
+
+protected:
+ virtual
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<1> &quadrature) const ;
+
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_face_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const ;
+
+ typename Mapping<1,spacedim>::InternalDataBase *
+ get_subface_data (const UpdateFlags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const ;
+
+ virtual void
+ fill_fe_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const Quadrature<1> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data,
+ CellSimilarity::Similarity &cell_similarity) const;
+
+ virtual void
+ fill_fe_face_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const unsigned int face_no,
+ const Quadrature<0> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data) const ;
+
+ virtual void
+ fill_fe_subface_values (const Mapping<1,spacedim> &mapping,
+ const typename Triangulation<1,spacedim>::cell_iterator &cell,
+ const unsigned int face_no,
+ const unsigned int sub_no,
+ const Quadrature<0> &quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &mapping_internal,
+ typename Mapping<1,spacedim>::InternalDataBase &fe_internal,
+ FEValuesData<1,spacedim> &data) const ;
+
+
+ /**
+ * Determine the values that need to be computed on the unit cell to be able
+ * to compute all values required by <tt>flags</tt>.
+ *
+ * For the purpuse of this function, refer to the documentation in
+ * FiniteElement.
+ *
+ * This class assumes that shape functions of this FiniteElement do
+ * <em>not</em> depend on the actual shape of the cells in real
+ * space. Therefore, the effect in this element is as follows: if
+ * <tt>update_values</tt> is set in <tt>flags</tt>, copy it to the
+ * result. All other flags of the result are cleared, since everything else
+ * must be computed for each cell.
+ */
+ virtual UpdateFlags update_once (const UpdateFlags flags) const;
+
+ /**
+ * Determine the values that need to be computed on every cell to be able to
+ * compute all values required by <tt>flags</tt>.
+ *
+ * For the purpuse of this function, refer to the documentation in
+ * FiniteElement.
+ *
+ * This class assumes that shape functions of this FiniteElement do
+ * <em>not</em> depend on the actual shape of the cells in real space.
+ *
+ * The effect in this element is as follows:
+ * <ul>
+ *
+ * <li> if <tt>update_gradients</tt> is set, the result will contain
+ * <tt>update_gradients</tt> and <tt>update_covariant_transformation</tt>.
+ * The latter is required to transform the gradient on the unit cell to the
+ * real cell. Remark, that the action required by
+ * <tt>update_covariant_transformation</tt> is actually performed by the
+ * Mapping object used in conjunction with this finite element.
+ *
+ * <li> if <tt>update_hessians</tt> is set, the result will contain
+ * <tt>update_hessians</tt> and <tt>update_covariant_transformation</tt>.
+ * The rationale is the same as above and no higher derivatives of the
+ * transformation are required, since we use difference quotients for the
+ * actual computation.
+ *
+ * </ul>
+ */
+ virtual UpdateFlags update_each (const UpdateFlags flags) const;
+
+private:
+ /**
+ * Return vector with dofs per vertex, line, quad, hex.
+ */
+ static std::vector<unsigned int> get_dpo_vector (const unsigned int deg);
+};
+
+
/**
* A finite element, which is a Legendre element of complete polynomials on
FullMatrix<double> &matrix) const;
/**
- * Check for non-zero values on a face.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
- *
- * Implementation of the interface in FiniteElement
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* Returns a list of constant modes of the element. For this element, the
* first entry on each face is true, all other are false (as the constant
* function is represented by the first base function of Legendre
- * polynomials.
+ * polynomials).
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
private:
/**
};
+
+/**
+ * FE_FaceP in 1D, i.e., with degrees of freedom on the element vertices.
+ */
+template <int spacedim>
+class FE_FaceP<1,spacedim> : public FE_FaceQ<1,spacedim>
+{
+public:
+ /**
+ * Constructor.
+ */
+ FE_FaceP (const unsigned int p);
+
+ /**
+ * Returns the name of the element
+ */
+ std::string get_name() const;
+};
+
+
DEAL_II_NAMESPACE_CLOSE
#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * Check whether a shape function
- * may be non-zero on a face.
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
/**
* Returns a list of constant modes of the element.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
virtual std::size_t memory_consumption () const;
virtual FiniteElement<dim> *clone() const;
#include <deal.II/base/qprojector.h>
#include <deal.II/base/polynomial_space.h>
#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/base/tensor_product_polynomials_const.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_poly.h>
{
return poly.get_numbering_inverse();
}
+
+ template <int dim>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering (const TensorProductPolynomialsConst<dim> &poly)
+ {
+ return poly.get_numbering();
+ }
+
+ template <int dim>
+ inline
+ std::vector<unsigned int>
+ get_poly_space_numbering_inverse (const TensorProductPolynomialsConst<dim> &poly)
+ {
+ return poly.get_numbering_inverse();
+ }
}
* The effect in this element is
* as follows:
* <ul>
-
- * <li> if
- * <tt>update_gradients</tt> is
- * set, the result will contain
- * <tt>update_gradients</tt> and
- * <tt>update_covariant_transformation</tt>.
- * The latter is required to
- * transform the gradient on the
- * unit cell to the real
- * cell. Remark, that the action
- * required by
- * <tt>update_covariant_transformation</tt>
- * is actually performed by the
- * Mapping object used in
- * conjunction with this finite
- * element. <li> if
- * <tt>update_hessians</tt>
- * is set, the result will
- * contain
- * <tt>update_hessians</tt>
- * and
- * <tt>update_covariant_transformation</tt>.
- * The rationale is the same as
- * above and no higher
- * derivatives of the
- * transformation are required,
- * since we use difference
- * quotients for the actual
- * computation.
+ *
+ * <li> if <tt>update_gradients</tt> is set, the result will contain
+ * <tt>update_gradients</tt> and <tt>update_covariant_transformation</tt>.
+ * The latter is required to transform the gradient on the unit cell to the
+ * real cell. Remark, that the action required by
+ * <tt>update_covariant_transformation</tt> is actually performed by the
+ * Mapping object used in conjunction with this finite element.
+ *
+ * <li> if <tt>update_hessians</tt> is set, the result will contain
+ * <tt>update_hessians</tt> and <tt>update_covariant_transformation</tt>.
+ * The rationale is the same as above and no higher derivatives of the
+ * transformation are required, since we use difference quotients for the
+ * actual computation.
*
* </ul>
*/
UpdateFlags
FE_PolyFace<POLY,dim,spacedim>::update_once (const UpdateFlags) const
{
- // for this kind of elements, only
- // the values can be precomputed
- // once and for all. set this flag
- // if the values are requested at
- // all
+ // for this kind of elements, only the values can be precomputed once and
+ // for all. set this flag if the values are requested at all
return update_default;
}
const UpdateFlags flags(fe_data.update_once | fe_data.update_each);
- const unsigned int foffset = fe_data.shape_values.size() * face;
if (flags & update_values)
for (unsigned int i=0; i<quadrature.size(); ++i)
{
- for (unsigned int k=0; k<this->dofs_per_cell; ++k)
+ for (unsigned int k=0; k<this->dofs_per_cell; ++k)
data.shape_values(k,i) = 0.;
- for (unsigned int k=0; k<fe_data.shape_values.size(); ++k)
- data.shape_values(foffset+k,i) = fe_data.shape_values[k][i];
+ switch (dim)
+ {
+ case 3:
+ {
+ // Fill data for quad shape functions
+ if (this->dofs_per_quad !=0)
+ {
+ const unsigned int foffset = this->first_quad_index + this->dofs_per_quad * face;
+ for (unsigned int k=0; k<this->dofs_per_quad; ++k)
+ data.shape_values(foffset+k,i) = fe_data.shape_values[k+this->first_face_quad_index][i];
+ }
+ }
+ case 2:
+ {
+ // Fill data for line shape functions
+ if (this->dofs_per_line != 0)
+ {
+ const unsigned int foffset = this->first_line_index;
+ for (unsigned int line=0; line<GeometryInfo<dim>::lines_per_face; ++line)
+ {
+ for (unsigned int k=0; k<this->dofs_per_line; ++k)
+ data.shape_values(foffset+GeometryInfo<dim>::face_to_cell_lines(face, line)*this->dofs_per_line+k,i) = fe_data.shape_values[k+(line*this->dofs_per_line)+this->first_face_line_index][i];
+ }
+ }
+ }
+ case 1:
+ {
+ // Fill data for vertex shape functions
+ if (this->dofs_per_vertex != 0)
+ for (unsigned int lvertex=0; lvertex<GeometryInfo<dim>::vertices_per_face; ++lvertex)
+ data.shape_values(GeometryInfo<dim>::face_to_cell_vertices(face, lvertex),i) = fe_data.shape_values[lvertex][i];
+ break;
+ }
+ }
}
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
FullMatrix<double> &matrix) const;
/**
- * Check for non-zero values on a face.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
- *
- * Implementation of the interface in FiniteElement
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* Returns a list of constant modes of the element. For this element, the
* list consists of true arguments for all components.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
/**
* @name Functions to support hp
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2012 - 2013 by the deal.II authors
+// Copyright (C) 2012 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * Check for non-zero values on a face.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
- *
- * Implementation of the interface in FiniteElement
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
+ /**
+ * Returns a list of constant modes of the element. For this element, there
+ * are two constant modes despite the element is scalar: The first constant
+ * mode is all ones for the usual FE_Q basis and the second one only using
+ * the discontinuous part.
+ */
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
+
protected:
/**
* @p clone function instead of a copy constructor.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
virtual std::string get_name () const;
/**
- * Check for non-zero values on a face.
- *
- * This function returns
- * @p true, if the shape
- * function @p shape_index has
- * non-zero values on the face
- * @p face_index.
- *
- * Implementation of the
- * interface in
- * FiniteElement
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* list consists of true arguments for the first vertex shape functions and
* false for the remaining ones.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
protected:
/**
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2003 - 2013 by the deal.II authors
+// Copyright (C) 2003 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * Check whether a shape function
- * may be non-zero on a face.
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*
- * Right now, this is only
- * implemented for RT0 in
- * 1D. Otherwise, returns always
- * @p true.
+ * Right now, this is only implemented for RT0 in 1D. Otherwise, returns
+ * always @p true.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
const VectorSlice<const std::vector<std::vector<double> > > &values) const;
/**
- * Returns a list of constant modes of the element. For this element, the
- * list consists of true arguments for all components.
+ * Returns a list of constant modes of the element. This method is currently
+ * not correctly implemented because it returns ones for all components.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
virtual std::size_t memory_consumption () const;
virtual FiniteElement<dim> *clone() const;
*/
static std::vector<bool>
get_ria_vector (const unsigned int degree);
+
/**
- * Check whether a shape function
- * may be non-zero on a face.
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
*
* Right now, this is only
* implemented for RT0 in
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
* Same as above but for any number of base elements. Pointers to the base
* elements and their multiplicities are passed as vectors to this
- * constructor. The length of these vectors is assumed to be equal.
+ * constructor. The lengths of these vectors are assumed to be equal.
*/
FESystem (const std::vector<const FiniteElement<dim,spacedim>*> &fes,
base_element (const unsigned int index) const;
/**
- * Check for non-zero values on a face.
- *
* This function returns @p true, if the shape function @p shape_index has
- * non-zero values on the face @p face_index.
- *
- * Implementation of the interface in FiniteElement
+ * non-zero function values somewhere on the face @p face_index.
*/
virtual bool has_support_on_face (const unsigned int shape_index,
const unsigned int face_index) const;
* table contains a basis representation of the constant function 1 on the
* element. Concatenates the constant modes of each base element.
*/
- virtual Table<2,bool> get_constant_modes () const;
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
/**
* @name Functions to support hp
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
* Compute the embedding matrices on faces needed for constraint matrices.
*
- * @param fe The finite element for which to compute these matrices. @param
- * matrices An array of <i>GeometryInfo<dim>::subfaces_per_face =
+ * @param fe The finite element for which to compute these matrices.
+ *
+ * @param matrices An array of <i>GeometryInfo<dim>::subfaces_per_face =
* 2<sup>dim-1</sup></i> FullMatrix objects,holding the embedding matrix for
- * each subface. @param face_coarse The number of the face on the coarse
- * side of the face for which this is computed. @param face_fine The number
- * of the face on the refined side of the face for which this is computed.
+ * each subface.
+ *
+ * @param face_coarse The number of the face on the coarse side of the face
+ * for which this is computed.
+ *
+ * @param face_fine The number of the face on the refined side of the face
+ * for which this is computed.
*
* @warning This function will be used in computing constraint matrices. It
* is not sufficiently tested yet.
/**
* Gives the patchwise extrapolation of a @p dof1 function @p z1 to a @p
- * dof2 function @p z2. @p dof1 and @p dof2 need to be DoFHandler based on
- * the same triangulation.
- *
- * This function is interesting for e.g. extrapolating patchwise a piecewise
- * linear solution to a piecewise quadratic solution.
- *
- * Note that the resulting field does not satisfy continuity requirements of
- * the given finite elements.
- *
+ * dof2 function @p z2. @p dof1 and @p dof2 need to be DoFHandler objects
+ * based on the same triangulation. This function is used, for example, for
+ * extrapolating patchwise a piecewise linear solution to a piecewise
+ * quadratic solution.
+ *
+ * The function's name is historical and probably not particularly well
+ * chosen. The function performs the following operations, one after the
+ * other:
+ *
+ * - It interpolates directly from every cell of @p dof1 to the
+ * corresponding cell of @dof2 using the interpolation matrix of the
+ * finite element spaces used on these cells and provided by
+ * the finite element objects involved. This step is done using the
+ * FETools::interpolate() function.
+ * - It then performs a loop over all non-active cells of @dof2. If
+ * such a non-active cell has at least one active child, then we
+ * call the children of this cell a "patch". We then interpolate
+ * from the children of this patch to the patch, using the finite
+ * element space associated with @p dof2 and immediately interpolate
+ * back to the children. In essence, this information throws away
+ * all information in the solution vector that lives on a scale
+ * smaller than the patch cell.
+ * - Since we traverse non-active cells from the coarsest to the
+ * finest levels, we may find patches that correspond to child
+ * cells of previously treated patches if the mesh had been
+ * refined adaptively (this cannot happen if the mesh has been
+ * refined globally because there the children of a patch are
+ * all active). We also perform the operation described above
+ * on these patches, but it is easy to see that on patches that
+ * are children of previously treated patches, the operation is
+ * now the identity operation (since it interpolates from the
+ * children of the current patch a function that had previously
+ * been interpolated to these children from an even coarser patch).
+ * Consequently, this does not alter the solution vector any more.
+ *
+ * The name of the function originates from the fact that it can be
+ * used to construct a representation of a function of higher polynomial
+ * degree on a once coarser mesh. For example, if you imagine that you
+ * start with a $Q_1$ function on globally refined mesh, and that @p dof2
+ * is associated with a $Q_2$ element, then this function computes the
+ * equivalent of the operator $I_{2h}^{(2)}$ interpolating the original
+ * piecewise linear function onto a quadratic function on a once coarser
+ * mesh with mesh size $2h$ (but representing this function on the original
+ * mesh with size $h$). If the exact solution is sufficiently smooth,
+ * then $u^\ast=I_{2h}^{(2)}u_h$ is typically a better approximation to
+ * the exact solution $u$ of the PDE than $u_h$ is. In other words, this
+ * function provides a postprocessing step that improves the solution in
+ * a similar way one often obtains by extrapolating a sequence of solutions,
+ * explaining the origin of the function's name.
+ *
+ * @note The resulting field does not satisfy continuity requirements of
+ * the given finite elements if the algorithm outlined above is used.
* When you use continuous elements on grids with hanging nodes, please use
* the @p extrapolate function with an additional ConstraintMatrix argument,
* see below.
*
- * Since this function operates on patches of cells, it is required that the
- * underlying grid is refined at least once for every coarse grid cell. If
+ * @note Since this function operates on patches of cells, it requires that
+ * the underlying grid is refined at least once for every coarse grid cell. If
* this is not the case, an exception will be raised.
*/
template <int dim, class InVector, class OutVector, int spacedim>
/**
* Gives the patchwise extrapolation of a @p dof1 function @p z1 to a @p
- * dof2 function @p z2. @p dof1 and @p dof2 need to be DoFHandler based on
+ * dof2 function @p z2. @p dof1 and @p dof2 need to be DoFHandler objects based on
* the same triangulation. @p constraints is a hanging node constraints
- * object corresponding to @p dof2. This object is particular important when
+ * object corresponding to @p dof2. This object is necessary when
* interpolating onto continuous elements on grids with hanging nodes
* (locally refined grids).
*
- * Otherwise, the same holds as for the other @p extrapolate function.
+ * Otherwise, the function does the same as the other @p extrapolate
+ * function above (for which the documentation provides an extensive
+ * description of its operation).
*/
template <int dim, class InVector, class OutVector, int spacedim>
void extrapolate (const DoFHandler<dim,spacedim> &dof1,
* correct size, which is equal to the number of degrees of freedom in the
* finite element.
*/
+
+ template <int dim>
+ void
+ hierarchic_to_lexicographic_numbering (unsigned int degree,
+ std::vector<unsigned int> &h2l);
+
template <int dim>
void
hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe_data,
* accordingly.
*
* The name must be in the form which is returned by the
- * FiniteElement::get_name function, where a few modifications are allowed:
- *
- * <ul><li> Dimension template parameters <2> etc. can be
+ * FiniteElement::get_name function, where dimension template parameters <2> etc. can be
* omitted. Alternatively, the explicit number can be replaced by
* <tt>dim</tt> or <tt>d</tt>. If a number is given, it <b>must</b> match
* the template parameter of this function.
*
- * <li> The powers used for FESystem may either be numbers or can be
- * replaced by <tt>dim</tt> or <tt>d</tt>. </ul>
+ * The names of FESystem elements follow the pattern <code>FESystem[FE_Base1^p1-FE_Base2^p2]</code>
+ * The powers <code>p1</code> etc. may either be numbers or can be
+ * replaced by <tt>dim</tt> or <tt>d</tt>.
+ *
*
* If no finite element can be reconstructed from this string, an exception
* of type @p FETools::ExcInvalidFEName is thrown.
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#ifndef __deal2__fe_trace_h
+#define __deal2__fe_trace_h
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/fe/fe_poly_face.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+/**
+ * A finite element, which is the trace of FE_Q elements, that is
+ * a tensor product of polynomials on the faces,
+ * undefined in the interior of the cells and continuous. The basis functions on
+ * the faces are from Polynomials::LagrangeEquidistant
+ *
+ * This finite element is the trace space of FE_Q on the
+ * faces.
+ *
+ * @note Since these are only finite elements on faces, only
+ * FEFaceValues and FESubfaceValues will be able to extract reasonable
+ * values from any face polynomial. In order to make the use of
+ * FESystem simpler, FEValues objects will not fail using this finite
+ * element space, but all shape function values extracted will equal
+ * to zero.
+ *
+ * @todo Polynomials::LagrangeEquidistant should be and will be
+ * replaced by Polynomials::LagrangeGaussLobatto as soon as such a
+ * polynomial set exists.
+ * @todo so far, hanging nodes are not implemented
+ *
+ */
+
+template <int dim, int spacedim=dim>
+class FE_TraceQ : public FE_PolyFace<TensorProductPolynomials<dim-1>, dim, spacedim>
+{
+public:
+ /**
+ * Constructor for tensor product
+ * polynomials of degree
+ * <tt>p</tt>. The shape
+ * functions created using this
+ * constructor correspond to
+ * Legendre polynomials in each
+ * coordinate direction.
+ */
+ FE_TraceQ(unsigned int p);
+
+ virtual FiniteElement<dim,spacedim> *clone() const;
+
+ /**
+ * Return a string that uniquely
+ * identifies a finite
+ * element. This class returns
+ * <tt>FE_DGQ<dim>(degree)</tt>, with
+ * <tt>dim</tt> and <tt>degree</tt>
+ * replaced by appropriate
+ * values.
+ */
+ virtual std::string get_name () const;
+
+ /**
+ * This function returns @p true, if the shape function @p shape_index has
+ * non-zero function values somewhere on the face @p face_index.
+ */
+ virtual bool has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const;
+
+ /**
+ * Returns a list of constant modes of the element. For this element, it
+ * simply returns one row with all entries set to true.
+ */
+ virtual std::pair<Table<2,bool>, std::vector<unsigned int> >
+ get_constant_modes () const;
+
+private:
+ /**
+ * Return vector with dofs per
+ * vertex, line, quad, hex.
+ */
+ static std::vector<unsigned int> get_dpo_vector (const unsigned int deg);
+};
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* in the case of an FEFaceValues or FESubfaceValues object.
*
* @param q_point Number of the quadrature point at which function is to
- * be evaluated
+ * be evaluated.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
value_type
value (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
gradient_type
gradient (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
hessian_type
hessian (const unsigned int shape_function,
* This function is the equivalent of the
* FEValuesBase::get_function_values function but it only works on the
* selected scalar component.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector>
void get_function_values (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_gradients function but it only works on the
* selected scalar component.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_hessians function but it only works on the
* selected scalar component.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void get_function_hessians (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_laplacians function but it only works on the
* selected scalar component.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void get_function_laplacians (const InputVector &fe_function,
* in the case of an FEFaceValues or FESubfaceValues object.
*
* @param q_point Number of the quadrature point at which function is to
- * be evaluated
+ * be evaluated.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
value_type
value (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
gradient_type
gradient (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
symmetric_gradient_type
symmetric_gradient (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
divergence_type
divergence (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
curl_type
curl (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
hessian_type
hessian (const unsigned int shape_function,
* This function is the equivalent of the
* FEValuesBase::get_function_values function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector>
void get_function_values (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_gradients function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
* FEValuesBase::get_function_symmetric_gradients in the FEValues classes
* but the information can be obtained from
* FEValuesBase::get_function_gradients, of course.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void
* FEValuesBase::get_function_divergences in the FEValues classes but the
* information can be obtained from FEValuesBase::get_function_gradients,
* of course.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_divergences (const InputVector &fe_function,
* FEValuesBase::get_function_curls in the FEValues classes but the
* information can be obtained from FEValuesBase::get_function_gradients,
* of course.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_curls (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_hessians function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void get_function_hessians (const InputVector &fe_function,
* This function is the equivalent of the
* FEValuesBase::get_function_laplacians function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void get_function_laplacians (const InputVector &fe_function,
* in the case of an FEFaceValues or FESubfaceValues object.
*
* @param q_point Number of the quadrature point at which function is to
- * be evaluated
+ * be evaluated.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
value_type
value (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
divergence_type
divergence (const unsigned int shape_function,
* This function is the equivalent of the
* FEValuesBase::get_function_values function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector>
void get_function_values (const InputVector &fe_function,
*
* See the general discussion of this class for a definition of the
* divergence.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_divergences (const InputVector &fe_function,
* in the case of an FEFaceValues or FESubfaceValues object.
*
* @param q_point Number of the quadrature point at which function is to
- * be evaluated
+ * be evaluated.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
value_type
value (const unsigned int shape_function,
*
* @note The meaning of the arguments is as documented for the value()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
divergence_type
divergence (const unsigned int shape_function,
* This function is the equivalent of the
* FEValuesBase::get_function_values function but it only works on the
* selected vector components.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector>
void get_function_values (const InputVector &fe_function,
*
* See the general discussion of this class for a definition of the
* divergence.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_divergences (const InputVector &fe_function,
*
* @param point_no Number of the quadrature point at which function is to be
* evaluated
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
const double &shape_value (const unsigned int function_no,
const unsigned int point_no) const;
* shape function is not primitive, but then it is necessary since the other
* function cannot be used.
*
- * @param function_no Number of the shape function to be evaluated
+ * @param function_no Number of the shape function to be evaluated.
*
* @param point_no Number of the quadrature point at which function is to be
- * evaluated
+ * evaluated.
+ *
+ * @param component vector component to be evaluated.
*
- * @param component vector component to be evaluated
+ * @dealiiRequiresUpdateFlags{update_values}
*/
double shape_value_component (const unsigned int function_no,
const unsigned int point_no,
*
* The same holds for the arguments of this function as for the
* shape_value() function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
const Tensor<1,spacedim> &
shape_grad (const unsigned int function_no,
*
* The same holds for the arguments of this function as for the
* shape_value_component() function.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
Tensor<1,spacedim>
shape_grad_component (const unsigned int function_no,
*
* The same holds for the arguments of this function as for the
* shape_value() function.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
const Tensor<2,spacedim> &
shape_hessian (const unsigned int function_no,
*
* The same holds for the arguments of this function as for the
* shape_value_component() function.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
Tensor<2,spacedim>
shape_hessian_component (const unsigned int function_no,
* object was last initialized. Alternatively, if the vector argument is of
* type IndexSet, then the function is represented as one that is either
* zero or one, depending on whether a DoF index is in the set or not.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector, typename number>
void get_function_values (const InputVector &fe_function,
* accessed by <code>values[q]</code> equals the number of components of the
* finite element, i.e. <code>values[q](c)</code> returns the value of the
* $c$th vector component at the $q$th quadrature point.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector, typename number>
void get_function_values (const InputVector &fe_function,
* You may want to use this function, if you want to access just a single
* block from a BlockVector, if you have a multi-level vector or if you
* already have a local representation of your finite element data.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector, typename number>
void get_function_values (const InputVector &fe_function,
*
* Since this function allows for fairly general combinations of argument
* sizes, be aware that the checks on the arguments may not detect errors.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector, typename number>
void get_function_values (const InputVector &fe_function,
*
* Since this function allows for fairly general combinations of argument
* sizes, be aware that the checks on the arguments may not detect errors.
+ *
+ * @dealiiRequiresUpdateFlags{update_values}
*/
template <class InputVector>
void get_function_values (const InputVector &fe_function,
* object was last initialized. Alternatively, if the vector argument is of
* type IndexSet, then the function is represented as one that is either
* zero or one, depending on whether a DoF index is in the set or not.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
* quadrature point. Consequently, <code>gradients[q][c][d]</code> is the
* derivative in coordinate direction $d$ of the $c$th vector component of
* the vector field at quadrature point $q$ of the current cell.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
std::vector<std::vector<Tensor<1,spacedim> > > &gradients) const;
/**
- * Function gradient access with more flexibility. see get_function_values()
+ * Function gradient access with more flexibility. See get_function_values()
* with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
std::vector<Tensor<1,spacedim> > &gradients) const;
/**
- * Function gradient access with more flexibility. see get_function_values()
+ * Function gradient access with more flexibility. See get_function_values()
* with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_gradients}
*/
template <class InputVector>
void get_function_gradients (const InputVector &fe_function,
*
* @post <code>hessians[q]</code> will contain the Hessian of the field
* described by fe_function at the $q$th quadrature
- * point. <code>gradients[q][i][j]</code> represents the $(i,j)$th component
+ * point. <code>hessians[q][i][j]</code> represents the $(i,j)$th component
* of the matrix of second derivatives at quadrature point $q$.
*
* @note The actual data type of the input vector may be either a
* object was last initialized. Alternatively, if the vector argument is of
* type IndexSet, then the function is represented as one that is either
* zero or one, depending on whether a DoF index is in the set or not.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void
* vector accessed by <code>hessians[q]</code> equals the number of
* components of the finite element, i.e. <code>hessians[q][c]</code>
* returns the Hessian of the $c$th vector component at the $q$th quadrature
- * point. Consequently, <code>values[q][c][i][j]</code> is the $(i,j)$th
+ * point. Consequently, <code>hessians[q][c][i][j]</code> is the $(i,j)$th
* component of the matrix of second derivatives of the $c$th vector
* component of the vector field at quadrature point $q$ of the current
* cell.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void
bool quadrature_points_fastest = false) const;
/**
- * Access to the second derivatives of a function with more flexibility. see
+ * Access to the second derivatives of a function with more flexibility. See
* get_function_values() with corresponding arguments.
*/
template <class InputVector>
std::vector<Tensor<2,spacedim> > &hessians) const;
/**
- * Access to the second derivatives of a function with more flexibility. see
+ * Access to the second derivatives of a function with more flexibility. See
* get_function_values() with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector>
void get_function_hessians (
* object was last initialized. Alternatively, if the vector argument is of
* type IndexSet, then the function is represented as one that is either
* zero or one, depending on whether a DoF index is in the set or not.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector, typename number>
void
* <code>laplacians[q][c]=trace(hessians[q][c])</code>, where
* <tt>hessians</tt> would be the output of the get_function_hessians()
* function.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector, typename number>
void
std::vector<Vector<number> > &laplacians) const;
/**
- * Access to the second derivatives of a function with more flexibility. see
+ * Access to the second derivatives of a function with more flexibility. See
* get_function_values() with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector, typename number>
void get_function_laplacians (
std::vector<number> &laplacians) const;
/**
- * Access to the second derivatives of a function with more flexibility. see
+ * Access to the second derivatives of a function with more flexibility. See
* get_function_values() with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector, typename number>
void get_function_laplacians (
std::vector<Vector<number> > &laplacians) const;
/**
- * Access to the second derivatives of a function with more flexibility. see
+ * Access to the second derivatives of a function with more flexibility. See
* get_function_values() with corresponding arguments.
+ *
+ * @dealiiRequiresUpdateFlags{update_hessians}
*/
template <class InputVector, typename number>
void get_function_laplacians (
//@{
/**
- * Position of the <tt>i</tt>th quadrature point in real space.
+ * Position of the <tt>q</tt>th quadrature point in real space.
+ *
+ * @dealiiRequiresUpdateFlags{update_quadrature_points}
*/
- const Point<spacedim> &quadrature_point (const unsigned int i) const;
+ const Point<spacedim> &
+ quadrature_point (const unsigned int q) const;
/**
- * Return a pointer to the vector of quadrature points in real space.
+ * Return a reference to the vector of quadrature points in real space.
+ *
+ * @dealiiRequiresUpdateFlags{update_quadrature_points}
*/
const std::vector<Point<spacedim> > &get_quadrature_points () const;
* You can think of the quantity returned by this function as the volume or
* surface element $dx, ds$ in the integral that we implement here by
* quadrature.
+ *
+ * @dealiiRequiresUpdateFlags{update_JxW_values}
*/
double JxW (const unsigned int quadrature_point) const;
/**
- * Pointer to the array holding the values returned by JxW().
+ * Return a reference to the array holding the values returned by JxW().
*/
const std::vector<double> &get_JxW_values () const;
/**
* Return the Jacobian of the transformation at the specified quadrature
* point, i.e. $J_{ij}=dx_i/d\hat x_j$
+ *
+ * @dealiiRequiresUpdateFlags{update_jacobians}
*/
const DerivativeForm<1,dim,spacedim> &jacobian (const unsigned int quadrature_point) const;
/**
- * Pointer to the array holding the values returned by jacobian().
+ * Return a reference to the array holding the values returned by jacobian().
+ *
+ * @dealiiRequiresUpdateFlags{update_jacobians}
*/
const std::vector<DerivativeForm<1,dim,spacedim> > &get_jacobians () const;
* Return the second derivative of the transformation from unit to real
* cell, i.e. the first derivative of the Jacobian, at the specified
* quadrature point, i.e. $G_{ijk}=dJ_{jk}/d\hat x_i$.
+ *
+ * @dealiiRequiresUpdateFlags{update_jacobian_grads}
*/
const DerivativeForm<2,dim,spacedim> &jacobian_grad (const unsigned int quadrature_point) const;
/**
- * Pointer to the array holding the values returned by jacobian_grads().
+ * Return a reference to the array holding the values returned by jacobian_grads().
+ *
+ * @dealiiRequiresUpdateFlags{update_jacobian_grads}
*/
const std::vector<DerivativeForm<2,dim,spacedim> > &get_jacobian_grads () const;
/**
* Return the inverse Jacobian of the transformation at the specified
* quadrature point, i.e. $J_{ij}=d\hat x_i/dx_j$
+ *
+ * @dealiiRequiresUpdateFlags{update_inverse_jacobians}
*/
const DerivativeForm<1,spacedim,dim> &inverse_jacobian (const unsigned int quadrature_point) const;
/**
- * Pointer to the array holding the values returned by inverse_jacobian().
+ * Return a reference to the array holding the values returned by inverse_jacobian().
+ *
+ * @dealiiRequiresUpdateFlags{update_inverse_jacobians}
*/
const std::vector<DerivativeForm<1,spacedim,dim> > &get_inverse_jacobians () const;
+
/**
* For a face, return the outward normal vector to the cell at the
* <tt>i</tt>th quadrature point.
* specified by the numbering of the vertices.
*
* The length of the vector is normalized to one.
+ *
+ * @dealiiRequiresUpdateFlags{update_normal_vectors}
*/
const Point<spacedim> &normal_vector (const unsigned int i) const;
* Return the normal vectors at the quadrature points. For a face, these are
* the outward normal vectors to the cell. For a cell of codimension one,
* the orientation is given by the numbering of vertices.
+ *
+ * @dealiiRequiresUpdateFlags{update_normal_vectors}
*/
const std::vector<Point<spacedim> > &get_normal_vectors () const;
/**
* Boundary form of the transformation of the cell at the <tt>i</tt>th
* quadrature point. See @ref GlossBoundaryForm .
+ *
+ * @dealiiRequiresUpdateFlags{update_boundary_forms}
*/
const Tensor<1,spacedim> &boundary_form (const unsigned int i) const;
/**
* Return the list of outward normal vectors times the Jacobian of the
* surface mapping.
+ *
+ * @dealiiRequiresUpdateFlags{update_boundary_forms}
*/
const std::vector<Tensor<1,spacedim> > &get_boundary_forms () const;
// an adaptation of the FEValuesBase::shape_value_component function
// except that here we know the component as fixed and we have
- // pre-computed and cached a bunch of information. see the comments there
+ // pre-computed and cached a bunch of information. See the comments there.
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
return fe_values.shape_values(shape_function_data[shape_function]
.row_index,
// function except that here we know the
// component as fixed and we have
// pre-computed and cached a bunch of
- // information. see the comments there
+ // information. See the comments there.
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
return fe_values.shape_gradients[shape_function_data[shape_function]
.row_index][q_point];
// function except that here we know the
// component as fixed and we have
// pre-computed and cached a bunch of
- // information. see the comments there
+ // information. See the comments there.
if (shape_function_data[shape_function].is_nonzero_shape_function_component)
return fe_values.shape_hessians[shape_function_data[shape_function].row_index][q_point];
else
#include <deal.II/base/derivative_form.h>
#include <deal.II/base/vector_slice.h>
#include <deal.II/grid/tria.h>
-#include <deal.II/dofs/dof_handler.h>
#include <deal.II/fe/fe_update_flags.h>
#include <cmath>
*/
mapping_piola = 0x0100,
/**
- transformation for the gradient of
- for a vector field
- correspoing to a mapping_piola
- transformation (see Mapping::transform() for details).
+ transformation for the gradient of a vector field corresponding to a
+ mapping_piola transformation (see Mapping::transform() for details).
*/
mapping_piola_gradient = 0x0101,
* <h3>References</h3>
*
* A general publication on differential geometry and finite elements
- * is the survey <ul><li>Douglas N. Arnold, Richard S. Falk, and
+ * is the survey
+ * <ul>
+ * <li>Douglas N. Arnold, Richard S. Falk, and
* Ragnar Winther. <i>Finite element exterior calculus: from
* Hodge theory to numerical stability.</i>
* Bull. Amer. Math. Soc. (N.S.), 47:281-354, 2010. <a
* href="http://dx.doi.org/10.1090/S0273-0979-10-01278-4">DOI:
- * 10.1090/S0273-0979-10-01278-4</a>.</ul>
+ * 10.1090/S0273-0979-10-01278-4</a>.
+ * </ul>
*
* The description of the Piola transform has been taken from the <a
* href="http://www.math.uh.edu/~rohop/spring_05/downloads/">lecture
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * A class to represent a unique ID for a cell in a Triangulation.
- * This class stores the index of the coarse cell together with the
- * information on how to reach the cell from that coarse cell (which
- * child index to take on each level). The internal representation
- * is not exposed on purpose.
+ * A class to represent a unique ID for a cell in a Triangulation. This class
+ * stores the index of the coarse cell from which a cell is descendant,
+ * together with information on how to reach the cell from that coarse cell
+ * (i.e., which child index to take on each level when moving from one cell to
+ * its children). The important point about this class is that an object of
+ * the current class uniquely identifies a cell in triangulation, and it even
+ * does so in the context of objects of type
+ * parallel::distributed::Triangulation where the local portion of a mesh may
+ * not store all cells. For example, the CellId computed for a ghost cell on
+ * one processor will be exactly the same as the CellId computed for the very
+ * same cell on the processor that actually owns the cell, although the level
+ * and index of the iterators pointing to that cell <i>within the
+ * triangulation stored on each of the processors</i> may (and in general
+ * will) be different. In other words, CellId provides the tool with which it
+ * is possible to uniquely identify cells in a parallel triangulation, and
+ * consequently makes it possible to exchange data between processors tied to
+ * individual cells.
*
- * TODO: does it make sense to implement a more efficient representation
+ * @note How this data is internally represented is not of importance (and not
+ * exposed on purpose).
+ *
+ * @todo Does it make sense to implement a more efficient representation
* (internally and/or as a string)? If yes, something like a 64bit int
* as in p4est would be a good option.
*/
#include <deal.II/base/exceptions.h>
#include <deal.II/base/point.h>
#include <deal.II/base/table.h>
+#include <deal.II/base/function.h>
#include <deal.II/grid/tria.h>
#include <map>
namespace GridGenerator
{
/**
- * Initialize the given triangulation with a hypercube (line in 1D, square
- * in 2D, etc) consisting of exactly one cell. The hypercube volume is the
- * tensor product interval <i>[left,right]<sup>dim</sup></i> in the present
- * number of dimensions, where the limits are given as arguments. They
- * default to zero and unity, then producing the unit hypercube. All
- * boundary indicators are set to zero ("not colorized") for 2d and 3d. In
- * 1d the indicators are colorized, see hyper_rectangle().
+ * Initialize the given triangulation with a hypercube (line in 1D,
+ * square in 2D, etc) consisting of exactly one cell. The hypercube
+ * volume is the tensor product interval
+ * \f$ [left,right]^{\text{dim}}\f$ in the present number of
+ * dimensions, where the limits are given as arguments. They default
+ * to zero and unity, then producing the unit hypercube. If the
+ * argument `colorize` is false, all boundary indicators are set to
+ * zero ("not colorized") for 2d and 3d. If it is true, the boundary
+ * is colorized as in hyper_rectangle(). In 1d the indicators are
+ * always colorized, see hyper_rectangle().
*
* @image html hyper_cubes.png
*
template <int dim, int spacedim>
void hyper_cube (Triangulation<dim,spacedim> &tria,
const double left = 0.,
- const double right= 1.);
+ const double right= 1.,
+ const bool colorize= false);
/**
* Same as hyper_cube(), but with the difference that not only one cell is
const double radius = 1.);
/**
- * Create a cylinder around the x-axis. The cylinder extends from
+ * Create a cylinder around the $x$-axis. The cylinder extends from
* <tt>x=-half_length</tt> to <tt>x=+half_length</tt> and its projection
* into the @p yz-plane is a circle of radius @p radius.
*
* hull of the cylinder, 1 for the left hand face and 2 for the right hand
* face.
*
+ * If you want the cylinder to revolve around a different axis than the
+ * $x$-axis, then simply rotate the mesh generated by this function using
+ * the GridTools::transform() function using a rotation operator as
+ * argument.
+ *
* @note The triangulation needs to be void upon calling this function.
*/
template <int dim>
Triangulation<3,3> &result);
/**
- * This function transformes the @p Triangulation @p tria smoothly to a
+ * This function transforms the @p Triangulation @p tria smoothly to a
* domain that is described by the boundary points in the map @p
* new_points. This map maps the point indices to the boundary points in the
* transformed domain.
*
* In 1d, this function is not currently implemented.
*
+ * An optional @p coefficient for the Laplace problem an be used to control the amount of
+ * mesh deformation in different parts of the domain.
+ * Larger values make cells less prone to deformation (effectively increasing their stiffness).
+ * The coefficient is evaluated in the coordinate system of the old,
+ * undeformed configuration of the triangulation as input, i.e., before
+ * the transformation is applied.
+ * Should this function be provided, sensible results can only be expected if
+ * all coefficients are positive.
+ *
* @deprecated This function has been moved to GridTools::laplace_transform
*/
template <int dim>
void laplace_transformation (Triangulation<dim> &tria,
- const std::map<unsigned int,Point<dim> > &new_points) DEAL_II_DEPRECATED;
+ const std::map<unsigned int,Point<dim> > &new_points,
+ const Function<dim> *coefficient = 0) DEAL_II_DEPRECATED;
/**
* Exception
#include <deal.II/base/config.h>
#include <deal.II/base/exceptions.h>
#include <deal.II/base/point.h>
+#include <deal.II/base/data_out_base.h>
#include <deal.II/grid/tria.h>
#include <deal.II/fe/mapping.h>
*/
struct Svg
{
+ /// Height of the plot in SVG units, computed from width if zero. Defaults to 1000
+ unsigned int height;
+ /// The width of the plot. Computed automatically from height if zero (default)
+ unsigned int width;
/// Thickness of the lines between cells
unsigned int line_thickness;
/// Thickness of lines at the boundary
/// Interpret the level number of the cells as altitude over the x-y-plane (useful in the perpspective view).
bool convert_level_number_to_height;
+ /// The factor determining the vertical distance between levels (default = 0.3)
+ float level_height_factor;
+
/**
* Cell labeling (fixed order).
*
const bool label_subdomain_id = false,
const bool draw_colorbar = true,
const bool draw_legend = true);
-
- /**
- * Declare parameters in
- * ParameterHandler.
- */
-// static void declare_parameters (ParameterHandler ¶m);
-
- /**
- * Parse parameters of
- * ParameterHandler.
- */
-// void parse_parameters (ParameterHandler ¶m);
};
/**
void parse_parameters (ParameterHandler ¶m);
};
+
+ /**
+ * Flags for grid output in Vtk format. These flags are the same as
+ * those declared in DataOutBase::VtkFlags.
+ *
+ * @ingroup output
+ */
+ struct Vtk : public DataOutBase::VtkFlags
+ {};
+
+
+ /**
+ * Flags for grid output in Vtu format. These flags are the same as
+ * those declared in DataOutBase::VtuFlags.
+ *
+ * @ingroup output
+ */
+ struct Vtu : public DataOutBase::VtkFlags
+ {};
}
/// write() calls write_svg()
svg,
/// write() calls write_mathgl()
- mathgl
+ mathgl,
+ /// write() calls write_vtk()
+ vtk,
+ /// write() calls write_vtu()
+ vtu
};
/**
* colorbar can be drawn to encode the chosen coloring. Moreover, a
* cell label can be added, showing level index, etc.
*
- * @note Yet only implemented for
+ * @note This function is currently only implemented for
* two-dimensional grids in two
* space dimensions.
- *
+ */
+ void write_svg (const Triangulation<2,2> &tria,
+ std::ostream &out) const;
+
+ /**
+ * Declaration of the same function as above for all other dimensions and
+ * space dimensions. This function is not currently implemented and is only
+ * declared to exist to support dimension independent programming.
*/
template <int dim, int spacedim>
void write_svg (const Triangulation<dim,spacedim> &tria,
std::ostream &out) const;
- void write_svg (const Triangulation<2,2> &tria,
- std::ostream &out) const;
/**
* Write triangulation in MathGL script format. To interpret this
*
* To get a handle on the resultant MathGL script within a graphical
* environment an interpreter is needed. A suggestion to start with
- * is <code>mglview</code>, which is bundled with MathGL. With
+ * is <code>mglview</code>, which is bundled with MathGL.
* <code>mglview</code> can interpret and display small-to-medium
* MathGL scripts in a graphical window and enables conversion to
* other formats such as EPS, PNG, JPG, SVG, as well as view/display
* animations. Some minor editing, such as modifying the lighting or
* alpha channels, can also be done.
*
- * @note Not implemented for the codimensional one case.
+ * @note Not implemented for the codimension one case.
*/
template <int dim>
void write_mathgl (const Triangulation<dim> &tria,
std::ostream &out) const;
+ /**
+ * Write triangulation in VTK format.
+ */
+ template <int dim, int spacedim>
+ void write_vtk (const Triangulation<dim,spacedim> &tria,
+ std::ostream &out) const;
+
+ /**
+ * Write triangulation in VTU format.
+ */
+ template <int dim, int spacedim>
+ void write_vtu (const Triangulation<dim,spacedim> &tria,
+ std::ostream &out) const;
+
/**
* Write grid to @p out according to the given data format. This
* function simply calls the appropriate <tt>write_*</tt> function.
void set_flags (const GridOutFlags::MathGL &flags);
/**
- * Provide a function which tells us which
- * suffix with a given output format
- * usually has. At present the following
- * formats are defined:
+ * Set flags for VTK output
+ */
+ void set_flags (const GridOutFlags::Vtk &flags);
+
+ /**
+ * Set flags for VTU output
+ */
+ void set_flags (const GridOutFlags::Vtu &flags);
+
+ /**
+ * Provide a function that can tell us which
+ * suffix a given output format
+ * usually has. For example, it defines the following mappings:
* <ul>
* <li> @p OpenDX: <tt>.dx</tt>
* <li> @p gnuplot: <tt>.gnuplot</tt>
* <li> @p ucd: <tt>.inp</tt>
* <li> @p eps: <tt>.eps</tt>.
* </ul>
+ * Similar mappings are provided for all implemented formats.
*
* Since this function does not need data from this object, it is
* static and can thus be called without creating an object of this
GridOutFlags::Svg svg_flags;
/**
- * Flags for OpenDX output.
+ * Flags for MathGL output.
*/
GridOutFlags::MathGL mathgl_flags;
+ /**
+ * Flags for VTK output.
+ */
+ GridOutFlags::Vtk vtk_flags;
+
+ /**
+ * Flags for VTU output.
+ */
+ GridOutFlags::Vtu vtu_flags;
+
/**
* Write the grid information about faces to @p out. Only those
* faces are printed which are on the boundary and which have a
* 1d. Simply returns zero.
*/
unsigned int n_boundary_faces (const Triangulation<1,1> &tria) const;
+
/**
* Declaration of the specialization of above function for 1d,
* 2sd. Simply returns zero.
*/
unsigned int n_boundary_faces (const Triangulation<1,2> &tria) const;
unsigned int n_boundary_faces (const Triangulation<1,3> &tria) const;
+
/**
* Return the number of lines in the triangulation which have a
* boundary indicator not equal to zero. Only these lines are
* is mainly used when reading in grids from files and converting them to
* deal.II triangulations.
*
- * Note: In contrast to the rest of the deal.II library this class
+ * @note In contrast to the rest of the deal.II library, by default this class
* uses the old deal.II numbering scheme, which was used up to deal.II
- * version 5.2. That is, the vertex and face ordering in 2d is assumed
+ * version 5.2 (but the main function of this class takes a flag that
+ * specifies whether it should do an implicit conversion from the new
+ * to the old format before doing its work, and then back again after
+ * reordering). In this old format, the vertex and face ordering in 2d is assumed
* to be
* @verbatim
* 2
* |/ / | |/
* *-------* *-------*
* @endverbatim
- *
* After calling the GridReordering::reorder_cells() function the
* CellData is still in this old numbering scheme. Hence, for creating
* a Triangulation based on the resulting CellData the
*
* Prior to the implementation of the algorithms developed by Michael Anderson
* and described above, we used a branch-and-cut algorithm initially
- * implemented in 2000 by Wolfgang Bangerth. Although it is no longer used
+ * implemented in 2000 by Wolfgang Bangerth. Although it is no longer used,
* here is how it works, and why it doesn't always work for large meshes since
- * its run-time can exponential in bad cases.
+ * its run-time can be exponential in bad cases.
*
* The first observation is that although there are counterexamples,
* problems are usually local. For example, in the second example
* If a consistent reordering is not
* possible in dim=3, the original
* connectivity data is restored.
+ *
+ * @param original_cells An object that contains the data that describes
+ * the mesh.
+ * @param use_new_style_ordering If true, then use the standard
+ * ordering of vertices within a cell. If false (the default), then
+ * use the "old-style" ordering of vertices within cells used by
+ * deal.II before version 5.2 and as explained in the documentation
+ * of this class.
*/
- static void reorder_cells (std::vector<CellData<dim> > &original_cells);
+ static void reorder_cells (std::vector<CellData<dim> > &original_cells,
+ const bool use_new_style_ordering = false);
/**
* Grids generated by grid
// declaration of explicit specializations
template<>
void
-GridReordering<2>::reorder_cells (std::vector<CellData<2> > &original_cells);
+GridReordering<2>::reorder_cells (std::vector<CellData<2> > &original_cells,
+ const bool);
template<>
void
-GridReordering<2,3>::reorder_cells (std::vector<CellData<2> > &original_cells);
+GridReordering<2,3>::reorder_cells (std::vector<CellData<2> > &original_cells,
+ const bool);
template<>
void
-GridReordering<3>::reorder_cells (std::vector<CellData<3> > &original_cells);
+GridReordering<3>::reorder_cells (std::vector<CellData<3> > &original_cells,
+ const bool);
template<>
void
*/
namespace GridTools
{
+ /**
+ * @name Information about meshes and cells
+ */
+ /*@{*/
+
/**
* Return the diameter of a
* triangulation. The diameter is
double volume (const Triangulation<dim,spacedim> &tria,
const Mapping<dim,spacedim> &mapping = (StaticMappingQ1<dim,spacedim>::mapping));
+ /**
+ * Return the diamater of the smallest
+ * active cell of a triangulation. See
+ * step-24 for an example
+ * of use of this function.
+ */
+ template <int dim, int spacedim>
+ double
+ minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
+
+ /**
+ * Return the diamater of the largest
+ * active cell of a triangulation.
+ */
+ template <int dim, int spacedim>
+ double
+ maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
+
/**
* Given a list of vertices (typically
* obtained using
double cell_measure (const std::vector<Point<dim> > &all_vertices,
const unsigned int (&vertex_indices)[GeometryInfo<dim>::vertices_per_cell]);
+ /*@}*/
+ /**
+ * @name Functions supporting the creation of meshes
+ */
+ /*@{*/
+
/**
* Remove vertices that are not
* referenced by any of the
std::vector<unsigned int> &considered_vertices,
const double tol=1e-12);
+ /*@}*/
+ /**
+ * @name Rotating, stretching and otherwise transforming meshes
+ */
+ /*@{*/
+
/**
* Transform the vertices of the given
* triangulation by applying the
* pointer to the function. In
* either case, argument and
* return value have to be of
- * type <tt>Point<spacedim></tt>.
+ * type <tt>Point@<spacedim@></tt>.
*
- * Note: if you are using a parallel::distributed::Triangulation you will have
+ * @note If you are using a parallel::distributed::Triangulation you will have
* hanging nodes in your local Triangulation even if your "global" mesh has
* no hanging nodes. This will cause issues with wrong positioning of hanging
- * nodes in ghost cells. The active cells will be correct, but keep in mind that
- * computations like KellyErrorEstimator will give wrong answers. A safe bet is
- * to use this function prior to any refinement in parallel.
+ * nodes in ghost cells if you call the current functions: The vertices of
+ * all locally owned cells will be correct,
+ * but the vertices of some ghost cells may not. This means that
+ * computations like KellyErrorEstimator may give wrong answers. A safe approach is
+ * to use this function prior to any refinement in parallel, if that is possible, but
+ * not after you refine the mesh.
*
* This function is used in the
* "Possibilities for extensions" section
Triangulation<2> &triangulation);
/**
- * Transform the given triangulation smoothly to a different domain where
- * each of the vertices at the boundary of the triangulation is mapped to
+ * Transform the given triangulation smoothly to a different domain where,
+ * typically, each of the vertices at the boundary of the triangulation is mapped to
* the corresponding points in the @p new_points map.
*
* The way this function works is that it solves a Laplace equation for each
* @param[in,out] tria The Triangulation object. This object is changed in-place,
* i.e., the previous locations of vertices are overwritten.
*
+ * @param[in] coefficient An optional coefficient for the Laplace problem.
+ * Larger values make cells less prone to deformation (effectively increasing their stiffness).
+ * The coefficient is evaluated in the coordinate system of the old,
+ * undeformed configuration of the triangulation as input, i.e., before
+ * the transformation is applied.
+ * Should this function be provided, sensible results can only be expected if
+ * all coefficients are positive.
+ *
* @note This function is not currently implemented for the 1d case.
*/
template <int dim>
void laplace_transform (const std::map<unsigned int,Point<dim> > &new_points,
- Triangulation<dim> &tria);
+ Triangulation<dim> &tria,
+ const Function<dim> *coefficient = 0);
/**
* Scale the entire triangulation
Triangulation<dim, spacedim> &triangulation,
const bool keep_boundary=true);
+ /*@}*/
+ /**
+ * @name Finding cells and vertices of a triangulation
+ */
+ /*@{*/
+
/**
* Find and return the number of
* the used vertex in a given
* not be deduced from a function call,
* you will have to specify it after the
* function name, as for example in
- * <code>GridTools::get_active_child_cells@<DoFHandler@<dim@>
- * @> (cell)</code>.
+ * @code
+ * GridTools::get_active_child_cells<DoFHandler<dim> > (cell)
+ * @endcode
*/
template <class Container>
std::vector<typename Container::active_cell_iterator>
get_active_neighbors (const typename Container::active_cell_iterator &cell,
std::vector<typename Container::active_cell_iterator> &active_neighbors);
+ /*@}*/
+ /**
+ * @name Partitions and subdomains of triangulations
+ */
+ /*@{*/
+
/**
* Produce a sparsity pattern in which
* nonzero entries indicate that two
count_cells_with_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
const types::subdomain_id subdomain);
+ /*@}*/
+ /**
+ * @name Comparing different meshes
+ */
+ /*@{*/
+
/**
* Given two mesh containers
* (i.e. objects of type
have_same_coarse_mesh (const Container &mesh_1,
const Container &mesh_2);
- /**
- * Return the diamater of the smallest
- * active cell of a triangulation. See
- * step-24 for an example
- * of use of this function.
- */
- template <int dim, int spacedim>
- double
- minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
-
- /**
- * Return the diamater of the largest
- * active cell of a triangulation.
- */
- template <int dim, int spacedim>
- double
- maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
-
/**
* Given the two triangulations
* specified as the first two
* triangulation that contains the
* <i>most refined cells</i> from
* two input triangulations that
- * were derived from the <i>same </i>
+ * were derived from the <i>same</i>
* coarse grid by adaptive refinement.
* This is an operation sometimes
* needed when one solves for two
* example in order to compose a mesh
* for a complicated geometry from
* meshes for simpler geometries,
- * take a look at
- * GridGenerator::merge_triangulations .
+ * then this is not the function for you. Instead, consider
+ * GridGenerator::merge_triangulations().
*/
template <int dim, int spacedim>
void
const Triangulation<dim, spacedim> &triangulation_2,
Triangulation<dim, spacedim> &result);
+ /*@}*/
+ /**
+ * @name Dealing with distorted cells
+ */
+ /*@{*/
+
/**
* Given a triangulation and a
* list of cells whose children
fix_up_distorted_child_cells (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
Triangulation<dim,spacedim> &triangulation);
+ /*@}*/
+ /**
+ * @name Lower-dimensional meshes for parts of higher-dimensional meshes
+ */
+ /*@{*/
+
+
#ifdef _MSC_VER
// Microsoft's VC++ has a bug where it doesn't want to recognize that
// an implementation (definition) of the extract_boundary_mesh function
const std::set<types::boundary_id> &boundary_ids
= std::set<types::boundary_id>());
+ /*@}*/
+ /**
+ * @name Dealing with periodic domains
+ */
+ /*@{*/
+
/**
* Data type that provides all the information that is needed
* to create periodicity constraints and a periodic p4est forest
std::vector<PeriodicFacePair<typename CONTAINER::cell_iterator> > &matched_pairs,
const dealii::Tensor<1,CONTAINER::space_dimension> &offset = dealii::Tensor<1,CONTAINER::space_dimension>());
+ /*@}*/
+ /**
+ * @name Exceptions
+ */
+ /*@{*/
+
/**
* Exception
<< "> could not be found inside any of the "
<< "subcells of a coarse grid cell.");
+ /**
+ * Exception
+ */
DeclException1 (ExcVertexNotUsed,
unsigned int,
<< "The given vertex " << arg1
<< " is not used in the given triangulation");
+ /*@}*/
+
} /*namespace GridTools*/
/* ----------------- Template function --------------- */
+#ifndef DOXYGEN
+
namespace GridTools
{
template <int dim, typename Predicate, int spacedim>
const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell]);
}
-
+#endif
DEAL_II_NAMESPACE_CLOSE
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
maximum_smoothing = 0xffff ^ allow_anisotropic_smoothing
};
+ /**
+ * A typedef that is used to to identify cell iterators. The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies cells in a triangulation. The
+ * TriaIterator class works like a pointer that when you
+ * dereference it yields an object of type CellAccessor.
+ * CellAccessor is a class that identifies properties that
+ * are specific to cells in a triangulation, but it is derived
+ * (and consequently inherits) from TriaAccessor that describes
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation.
+ *
+ * @ingroup Iterators
+ */
typedef TriaIterator <CellAccessor<dim,spacedim> > cell_iterator;
+
+ /**
+ * A typedef that is used to to identify
+ * @ref GlossActive "active cell iterators". The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies active cells in a triangulation. The
+ * TriaActiveIterator class works like a pointer to active objects that when you
+ * dereference it yields an object of type CellAccessor.
+ * CellAccessor is a class that identifies properties that
+ * are specific to cells in a triangulation, but it is derived
+ * (and consequently inherits) from TriaAccessor that describes
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation.
+ *
+ * @ingroup Iterators
+ */
typedef TriaActiveIterator<CellAccessor<dim,spacedim> > active_cell_iterator;
typedef TriaIterator <TriaAccessor<dim-1, dim, spacedim> > face_iterator;
typedef typename IteratorSelector::quad_iterator quad_iterator;
typedef typename IteratorSelector::active_quad_iterator active_quad_iterator;
- typedef typename IteratorSelector::hex_iterator hex_iterator;
- typedef typename IteratorSelector::active_hex_iterator active_hex_iterator;
+ typedef typename IteratorSelector::hex_iterator hex_iterator;
+ typedef typename IteratorSelector::active_hex_iterator active_hex_iterator;
/**
* Base class for refinement listeners.
virtual void set_mesh_smoothing (const MeshSmoothing mesh_smoothing);
/**
- * If @p dim==spacedim, assign a boundary
- * object to a certain part of the
- * boundary of a the triangulation. If a
- * face with boundary number @p number is
- * refined, this object is used to find
- * the location of new vertices on the
- * boundary (see the results section of step-49
- * for a more in-depth discussion of this, with examples).
- * It is also used for
- * non-linear (i.e.: non-Q1)
- * transformations of cells to the unit
- * cell in shape function calculations.
+ * If @p dim==spacedim, assign a boundary object to a certain part
+ * of the boundary of a the triangulation. If a face with boundary
+ * number @p number is refined, this object is used to find the
+ * location of new vertices on the boundary (see the results section
+ * of step-49 for a more in-depth discussion of this, with
+ * examples). It is also used for non-linear (i.e.: non-Q1)
+ * transformations of cells to the unit cell in shape function
+ * calculations.
+ *
+ * If @p dim!=spacedim the boundary object is in fact the exact
+ * manifold that the triangulation is approximating (for example a
+ * circle approximated by a polygon triangulation). As above, the
+ * refinement is made in such a way that the new points are located
+ * on the exact manifold.
+ *
+ * Numbers of boundary objects correspond to material numbers of
+ * faces at the boundary, for instance the material id in a UCD
+ * input file. They are not necessarily consecutive but must be in
+ * the range 0-(types::boundary_id-1). Material IDs on boundaries
+ * are also called boundary indicators and are accessed with
+ * accessor functions of that name.
+ *
+ * The @p boundary_object is not copied and MUST persist until the
+ * triangulation is destroyed. This is also true for triangulations
+ * generated from this one by @p copy_triangulation.
*
- * If @p dim!=spacedim the boundary object
- * is in fact the exact manifold that the
- * triangulation is approximating (for
- * example a circle approximated by a
- * polygon triangulation). As above, the
- * refinement is made in such a way that
- * the new points are located on the exact
- * manifold.
- *
- * Numbers of boundary objects correspond
- * to material numbers of faces at the
- * boundary, for instance the material id
- * in a UCD input file. They are not
- * necessarily consecutive but must be in
- * the range 0-(types::boundary_id-1).
- * Material IDs on boundaries are also
- * called boundary indicators and are
- * accessed with accessor functions
- * of that name.
- *
- * The @p boundary_object is not copied
- * and MUST persist until the
- * triangulation is destroyed. This is
- * also true for triangulations generated
- * from this one by @p
- * copy_triangulation.
- *
- * It is possible to remove or replace
- * the boundary object during the
- * lifetime of a non-empty
- * triangulation. Usually, this is done
- * before the first refinement and is
- * dangerous afterwards. Removal of a
- * boundary object is done by
- * <tt>set_boundary(number)</tt>,
- * i.e. the function of same name but
- * only one argument. This operation then
- * replaces the boundary object given
- * before by a straight boundary
- * approximation.
+ * It is possible to remove or replace the boundary object during
+ * the lifetime of a non-empty triangulation. Usually, this is done
+ * before the first refinement and is dangerous afterwards. Removal
+ * of a boundary object is done by <tt>set_boundary(number)</tt>,
+ * i.e. the function of same name but only one argument. This
+ * operation then replaces the boundary object given before by a
+ * straight boundary approximation.
*
* @ingroup boundary
*
* @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
*/
void set_boundary (const types::manifold_id number,
- const Manifold<spacedim> &boundary_object);
+ const Manifold<spacedim> &boundary_object);
+
+
/**
- * Assign a Manifold object to a certain part of the
- * triangulation. The Manifold object is used to find the location
- * of new vertices on the domain and for non-linear (i.e.: non-Q1)
- * transformations of cells to the unit cell in shape function
- * calculations.
+ * Reset those parts of the triangulation with the given manifold_id
+ * to use a FlatManifold object. This is the default state of a
+ * triangulation, and undoes assignment of a different Manifold
+ * object by the function of same name and two arguments.
+ *
+ * @ingroup manifold
*
- * Numbers of manifold objects are stored in the manifold_id
- * variable of each triangulation object. By default each
- * triangulation object (i.e., cell, face, etc.) is assigned the
- * special value types::invalid_manifold_id, corresponding to a
- * FlatManifold object, i.e., one where new points are placed in the
- * middle of the surrounding ones.
- *
- * A different manifold can be specified by calling this function,
- * which will store the Manifold description in the Triangulation
- * object, and then setting different manifold_id for each relevant
- * object by calling the functions TriaAccessor::set_manifold_id()
- * or TriaAccessor::set_all_manifold_ids(). Manifold ids are not
- * necessarily consecutive but must be in the range
- * 0-(types::invalid_manifold_id-1).
+ * @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
+ */
+ void set_manifold (const types::manifold_id number);
+
+ /**
+ * Assign a manifold object to a certain part of the the
+ * triangulation. If an object with manfifold number @p number is
+ * refined, this object is used to find the location of new vertices
+ * (see the results section of step-49 for a more in-depth
+ * discussion of this, with examples). It is also used for
+ * non-linear (i.e.: non-Q1) transformations of cells to the unit
+ * cell in shape function calculations.
*
* The @p manifold_object is not copied and MUST persist until the
* triangulation is destroyed. This is also true for triangulations
* generated from this one by @p copy_triangulation.
*
- * It is possible to remove or replace the Manifold object during
+ * It is possible to remove or replace the boundary object during
* the lifetime of a non-empty triangulation. Usually, this is done
* before the first refinement and is dangerous afterwards. Removal
- * of a boundary object is done by <tt>set_manifold(number)</tt>,
+ * of a manifold object is done by <tt>set_manifold(number)</tt>,
* i.e. the function of same name but only one argument. This
- * operation then replaces the Manifold object given before by a
- * FlatManifold object.
+ * operation then replaces the manifold object given before by a
+ * straight manifold approximation.
*
* @ingroup manifold
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
void set_manifold (const types::manifold_id number,
- const Manifold<spacedim> &manifold_object);
-
-
+ const Manifold<spacedim> &manifold_object);
- /**
- * Reset those parts of the boundary with the given number to use a
- * straight boundary approximation. This is the default state of a
- * triangulation, and undoes assignment of a different boundary
- * object by the function of same name and two arguments.
- *
- * @ingroup boundary
- *
- * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
- */
- void set_boundary (const types::manifold_id number);
/**
* Reset those parts of the triangulation with the given manifold_id
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
- void set_manifold (const types::manifold_id number);
+ void set_boundary (const types::manifold_id number);
/**
* Return a constant reference to a boundary object used for this
*
* Keep in mind that this function also copies the pointer to the
* boundary descriptor previously set by the @p set_boundary
- * function and to the Manifold object previously set by the @p
- * set_manifold function. You must therefore also guarantee that
+ * function and to the Manifold object previously set by the
+ * set_manifold() function. You must therefore also guarantee that
* the boundary and manifold objects have a lifetime at least as
* long as the copied triangulation.
*
unsigned int n_lines (const unsigned int level) const;
/**
- * Return total number of active lines.
+ * Return the total number of active lines.
*/
unsigned int n_active_lines () const;
unsigned int n_active_cells () const;
/**
- * Return total number of active cells on level @p level. Maps to
- * <tt>n_active_lines(level)</tt> in one space dimension and so on.
+ * Return the total number of active cells. For the current class, this is
+ * the same as n_active_cells(). However, the function may be overloaded in
+ * derived classes (e.g., in parallel::distributed::Triangulation) where it
+ * may return a value greater than the number of active cells reported by
+ * the triangulation object on the current processor.
+ */
+ virtual types::global_dof_index n_global_active_cells () const;
+
+
+ /**
+ * Return the total number of active cells on
+ * level @p level. Maps to
+ * <tt>n_active_lines(level)</tt> in one
+ * space dimension and so on.
*/
unsigned int n_active_cells (const unsigned int level) const;
* parallel::distributed::Triangulation and therefore can be larger
* than n_levels().
*/
- virtual unsigned int n_global_levels () const;
+ virtual
+ unsigned int n_global_levels () const;
/**
- * Return the total number of vertices. Some of them may not be
- * used, which usually happens upon coarsening of a triangulation
- * when some vertices are discarded, but we do not want to renumber
- * the remaining ones, leading to holes in the numbers of used
- * vertices. You can get the number of used vertices using @p
- * n_used_vertices function.
+ * Return true if the triangulation has hanging nodes.
+ *
+ * The function is made virtual since the result can be interpreted in different
+ * ways, depending on whether the triangulation lives only on a single processor,
+ * or may be distributed as done in the parallel::distributed::Triangulation
+ * class (see there for a description of what the function is supposed to do in the
+ * parallel context).
+ */
+ virtual
+ bool has_hanging_nodes() const;
+
+ /**
+ * Return the total number of
+ * vertices. Some of them may
+ * not be used, which usually
+ * happens upon coarsening of a
+ * triangulation when some
+ * vertices are discarded, but we
+ * do not want to renumber the
+ * remaining ones, leading to
+ * holes in the numbers of used
+ * vertices. You can get the
+ * number of used vertices using
+ * @p n_used_vertices function.
*/
unsigned int n_vertices () const;
* in 2d and higher where we have space in the structures that store
* data for faces, but in 1d there is no such space for faces.
*
+ * @note Manifold objects are pretty useless for points since they are
+ * neither refined nor are their interiors mapped. We nevertheless allow
+ * storing manifold ids for points to be consistent in dimension-independent
+ * programs.
+ *
* The field is declared as a pointer for a rather mundane reason:
* all other fields of this class that can be modified by the
* TriaAccessor hierarchy are pointers, and so these accessor
const unsigned int) const
{
// as discussed in the documentation, do not store the signals as
- // well as boundary and manifold descrption but everything else
+ // well as boundary and manifold description but everything else
ar &smooth_grid;
ar &levels;
ar &faces;
ar &check_for_distorted_cells;
- if (dim == 1)
+ if (dim == 1) {
ar &vertex_to_boundary_id_map_1d;
+ ar &vertex_to_manifold_id_map_1d;
+ }
}
"same setting with regard to reporting distorted "
"cell as the one previously stored."));
- if (dim == 1)
+ if (dim == 1) {
ar &vertex_to_boundary_id_map_1d;
+ ar &vertex_to_manifold_id_map_1d;
+ }
// trigger the create signal to indicate
// that new content has been imported into
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*/
/**
- * Return the level the element
- * pointed to belongs to.
- * This is only valid for cells.
+ * For cells, this function returns the level within the mesh hierarchy at
+ * which this cell is located. For all other objects, the function returns
+ * zero.
+ *
+ * @note Within a Triangulation object, cells are uniquely identified by a
+ * pair <code>(level, index)</code> where the former is the cell's
+ * refinement level and the latter is the index of the cell within
+ * this refinement level (the former being what this function
+ * returns). Consequently, there may be multiple cells on different
+ * refinement levels but with the same index within their level.
+ * Contrary to this, if the current object corresponds to a face or
+ * edge, then the object is uniquely identified solely by its index
+ * as faces and edges do not have a refinement level. For these objects,
+ * the current function always returns zero as the level.
*/
int level () const;
* element presently pointed to
* on the present level.
*
- * Within a Triangulation object cells are uniquely identified by a
+ * Within a Triangulation object, cells are uniquely identified by a
* pair <code>(level, index)</code> where the former is the cell's
* refinement level and the latter is the index of the cell within
* this refinement level (the latter being what this function
*/
bool used () const;
- /**
- * Index of the parent.
- * The level of the parent is one
- * lower than that of the
- * present cell, if the parent
- * of a cell is accessed. If the
- * parent does not exist, -1 is
- * returned.
- */
- int parent_index () const;
-
-
/**
* @name Accessing sub-objects
*/
/**
* Return a reference to the
- * @p ith vertex.
+ * @p ith vertex. The reference is not const, i.e., it is possible
+ * to call this function on the left hand side of an assignment,
+ * thereby moving the vertex of a cell within the triangulation. Of
+ * course, doing so requires that you ensure that the new location
+ * of the vertex remains useful -- for example, avoiding inverted
+ * or otherwise distorted (see also @ref GlossDistorted "this glossary entry").
+ *
+ * @note When a cell is refined, its children inherit the position
+ * of the vertex positions of those vertices they share with the mother
+ * cell (plus the locations of the new vertices on edges, faces, and
+ * cell interiors that are created for the new child cells). If the
+ * vertex of a cell is moved, this implies that its children will also
+ * use these new locations. On the other hand, imagine a 2d situation
+ * where you have one cell that is refined (with four children) and then
+ * you move the central vertex connecting all four children. If you
+ * coarsen these four children again to the mother cell, then the
+ * location of the moved vertex is lost and if, in a later step, you
+ * refine the mother cell again, the then again new vertex will be
+ * placed again at the same position as the first time around -- i.e.,
+ * not at the location you had previously moved it to.
+ *
+ * @note The behavior described above is relevant if
+ * you have a parallel::distributed::Triangulation object. There,
+ * refining a mesh always involves a re-partitioning. In other words,
+ * vertices of locally owned cells (see
+ * @ref GlossLocallyOwnedCell "this glossary entry")
+ * that you may have moved to a different location on one processor
+ * may be moved to a different processor upon mesh refinement (even
+ * if these particular cells were not refined) which will re-create
+ * their position based on the position of the coarse cells they
+ * previously had, not based on the position these vertices had on
+ * the processor that previously owned them. In other words, in
+ * parallel computations, you will probably have to move nodes
+ * explicitly after every mesh refinement because vertex positions
+ * may or may not be preserved across the re-partitioning that
+ * accompanies mesh refinement.
*/
Point<spacedim> &vertex (const unsigned int i) const;
bool at_boundary () const;
/**
- * Return a constant reference to a
- * boundary object used for this
- * object. This function is a shortcut to
- * retrieving the boundary indicator
- * using boundary_indicator() and then
- * asking the
- * Triangulation::get_boundary() function
- * for the boundary object.
+ * Return a constant reference to the manifold object used for this
+ * object. This function exists for backward compatibility and calls
+ * get_manifold() internally.
*/
const Manifold<spacedim> &get_boundary () const;
/**
- * Return a constant reference to a
- * manifold object used for this
- * object. This function is a shortcut to
- * retrieving the manifold indicator
- * using manifold_indicator() and then
- * asking the
- * Triangulation::get_manifold() function
- * for the manifold object.
+ * Return a constant reference to a manifold object used for this
+ * object. This function is a shortcut to retrieving the manifold
+ * indicator using manifold_indicator() and then asking the
+ * Triangulation::get_manifold() function for the manifold object.
+ *
+ * As explained in @ref boundary "Boundary and manifold description
+ * for triangulations", the process involved in finding the
+ * appropriate manifold description involves querying both the
+ * manifold or boundary indicators. See there for more information.
+
*/
const Manifold<spacedim> &get_manifold () const;
-
+
/**
* @}
*/
*/
/**
- * Manifold indicator of this
+ * Return the manifold indicator of this
* object.
*
* If the return value is the special value
* numbers::flat_manifold_id, then this object is associated with a
- * standard cartesian Manifold Description.
+ * standard Cartesian Manifold Description.
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
void set_manifold_id (const types::manifold_id) const;
/**
- * Do as set_manifold_id()
- * but also set the manifold
- * indicators of the objects that
- * bound the current object. For
- * example, in 3d, if
- * set_manifold_id() is
- * called on a face, then the
- * manifold indicator of the 4
- * edges that bound the face
- * remain unchanged. On the other
- * hand, the manifold indicators
- * of face and edges are all set
- * at the same time using the
- * current function.
+ * Do as set_manifold_id() but also set the manifold indicators of
+ * the objects that bound the current object. For example, in 3d, if
+ * set_manifold_id() is called on a face, then the manifold
+ * indicator of the 4 edges that bound the face remain unchanged. On
+ * the other hand, the manifold indicators of face and edges are all
+ * set at the same time using the current function.
*
* @ingroup manifold
*
*/
void clear_refinement_case () const;
- /**
- * Set the parent of a cell.
- */
- void set_parent (const unsigned int parent_index);
-
/**
* Set the index of the ith
* child. Since the children
* @}
*/
- /**
- * Index of the parent. You
- * can't do this for points.
- */
- static int parent_index ();
-
/**
* @name Accessing sub-objects
*/
bool at_boundary () const;
/**
- * Boundary indicator of this
- * object. The convention for one
- * dimensional triangulations is
- * that left end vertices have
- * boundary indicator zero, and
- * right end vertices have
- * boundary indicator one.
+ * Return the boundary indicator of this object. The convention for one
+ * dimensional triangulations is that left end vertices (of each line
+ * segment from which the triangulation may be constructed) have boundary
+ * indicator zero, and right end vertices have boundary indicator one,
+ * unless explicitly set differently.
*
- * If the return value is the special
- * value numbers::internal_face_boundary_id,
- * then this object is in the
- * interior of the domain.
+ * If the return value is the special value
+ * numbers::internal_face_boundary_id, then this object is in the interior
+ * of the domain.
*
* @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
*/
types::boundary_id boundary_indicator () const;
/**
- * Manifold indicator of this
+ * Return the manifold indicator of this
* object.
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
/**
- * Set the boundary indicator.
- * The same applies as for the
- * <tt>boundary_indicator()</tt>
- * function.
+ * Set the boundary indicator. The same applies as for the
+ * <tt>boundary_indicator()</tt> function.
*
- * @warning You should never set the
- * boundary indicator of an interior face
- * (a face not at the boundary of the
- * domain), or set set the boundary
- * indicator of an exterior face to
- * numbers::internal_face_boundary_id
- * (this value is reserved for another
- * purpose). Algorithms may not work or
- * produce very confusing results if
- * boundary cells have a boundary
- * indicator of numbers::internal_face_boundary_id
- * or if interior cells have boundary
- * indicators other than numbers::internal_face_boundary_id.
- * Unfortunately, the current object
- * has no means of finding out whether it
- * really is at the boundary of the
- * domain and so cannot determine whether
- * the value you are trying to set makes
- * sense under the current circumstances.
+ * @warning You should never set the boundary indicator of an
+ * interior face (a face not at the boundary of the domain), or set
+ * set the boundary indicator of an exterior face to
+ * numbers::internal_face_boundary_id (this value is reserved for
+ * another purpose). Algorithms may not work or produce very
+ * confusing results if boundary cells have a boundary indicator of
+ * numbers::internal_face_boundary_id or if interior cells have
+ * boundary indicators other than
+ * numbers::internal_face_boundary_id. Unfortunately, the current
+ * object has no means of finding out whether it really is at the
+ * boundary of the domain and so cannot determine whether the value
+ * you are trying to set makes sense under the current
+ * circumstances.
*
* @ingroup boundary
*
void
set_boundary_indicator (const types::boundary_id);
- /**
- * Set the manifold indicator of
- * this vertex. Does nothing so
- * far. This function is here
- * only to allow dimension
- * independent programming.
- */
- void
- set_manifold_id (const types::manifold_id);
/**
- * Since this object only represents a
- * single vertex, call
- * set_boundary_indicator with the same
- * argument.
+ * Set the manifold indicator of this vertex. This does nothing so
+ * far since manifolds are only used to refine and map objects, but
+ * vertices are not refined and the mapping is trivial. This
+ * function is here only to allow dimension independent programming,
+ * and eventually to allow people to attach specific geometrical
+ * meaning to vertices, which can be later retrieved with the
+ * corresponding get_manifold_id() function.
+ */
+ void set_manifold_id (const types::manifold_id);
+
+ /**
+ * Set the boundary indicator of this object and all of its
+ * lower-dimensional sub-objects. Since this object only represents a
+ * single vertex, there are no lower-dimensional obejct and this function is
+ * equivalent to calling set_boundary_indicator with the same argument.
*
* @ingroup boundary
*
* @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
*/
- void
- set_all_boundary_indicators (const types::boundary_id);
+ void set_all_boundary_indicators (const types::boundary_id);
+
/**
- * @}
- */
-/**
- * Since this object only represents a
- * single vertex, call
- * set_manifold_id with the same
- * argument.
+ * Set the manifold indicator of this object and all of its
+ * lower-dimensional sub-objects. Since this object only represents a
+ * single vertex, there are no lower-dimensional obejct and this function is
+ * equivalent to calling set_manifold_indicator with the same argument.
*
* @ingroup manifold
*
* @see @ref GlossManifoldIndicator "Glossary entry on manifold indicators"
*/
- void
- set_all_manifold_ids (const types::manifold_id);
- /**
+ void set_all_manifold_ids (const types::manifold_id);
+ /**
* @}
*/
*/
/**
- * Return the @p
- * RefinementCase<dim> this cell
- * was flagged to be refined
- * with.
+ * Return the @p RefinementCase<dim> this cell was flagged to be refined
+ * with. The return value of this function can be compared to a bool to
+ * check if this cell is flagged for any kind of refinement. For example, if
+ * you have previously called cell->set_refine_flag() for a cell, then you
+ * will enter the 'if' block in the following snippet:
+ *
+ * @code
+ * if (cell->refine_flag_set())
+ * {
+ * // yes, this cell is marked for refinement.
+ * }
+ * @endcode
*/
RefinementCase<dim> refine_flag_set () const;
* Flag the cell pointed to for
* refinement. This function is
* only allowed for active
- * cells.
+ * cells. Keeping the default value for @p ref_case will mark this cell for
+ * isotropic refinement.
*/
void set_refine_flag (const RefinementCase<dim> ref_case = RefinementCase<dim>::isotropic_refinement) const;
*/
bool direction_flag () const;
-
+ /**
+ * Index of the parent of this cell within the level of the triangulation
+ * to which the parent cell belongs. The level of the parent is of course
+ * one lower than that of the present cell. If the parent does not exist
+ * (i.e., if the object is at the coarsest level of the mesh hierarchy), an
+ * exception is generated.
+ */
+ int parent_index () const;
/**
* Return an iterator to the
- * parent. Throws an exception if this cell has no parent, i.e. has
- * level 0.
+ * parent. If the
+ * parent does not exist (i.e., if the object is at the coarsest level of
+ * the mesh hierarchy), an exception is generated.
*/
TriaIterator<CellAccessor<dim,spacedim> >
parent () const;
*/
bool active () const;
- /**
- * Ordering of accessors. This function implements a total ordering
- * of cells even on a parallel::distributed::Triangulation. This
- * function first compares level_subdomain_id(). If these are equal,
- * and both cells are active, it compares subdomain_id(). If this is
- * inconclusive, TriaAccessorBase::operator < () is called.
- */
- bool operator < (const CellAccessor<dim, spacedim> &other) const;
-
-
/**
* Return whether this cell is owned by the current processor
* or is owned by another processor. The function always returns
* may be different as to whether
* a point is in- or outside the
* cell in real space.
-
- In case of codim>0, the point is first projected
- to the manifold where the cell is embedded and
- then check if this projection is inside the cell.
-
- */
+ *
+ * In case of codim>0, the point is first projected
+ * to the manifold where the cell is embedded and
+ * then check if this projection is inside the cell.
+ */
bool point_inside (const Point<spacedim> &p) const;
/**
/**
* Return a unique ID for the current cell. This ID is constructed from the
- * path in the hierarchy from the coarse father cell and works correctly
- * in parallel computations.
+ * path in the hierarchy from the coarse father cell and works correctly in
+ * parallel computations using objects of type
+ * parallel::distributed::Triangulation. This function is therefore useful
+ * in providing a unique identifier for cells (active or not) that also
+ * works for parallel triangulations. See the documentation of the CellId
+ * class for more information.
*
- * Note: This operation takes O(log(level)) time.
+ * @note This operation takes O(level) time to compute. In most practicaly
+ * cases, the number of levels of a triangulation will depend
+ * logarithmically on the number of cells in the triangulation.
*/
CellId id() const;
private:
+ /**
+ * Set the parent of a cell.
+ */
+ void set_parent (const unsigned int parent_index);
+
/**
* Set the orientation of this
* cell.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
}
-template <int structdim, int dim, int spacedim>
-int
-TriaAccessor<structdim, dim, spacedim>::
-parent_index () const
-{
- Assert (this->present_level > 0, TriaAccessorExceptions::ExcCellHasNoParent ());
-
- // the parent of two consecutive cells
- // is stored only once, since it is
- // the same
- return this->tria->levels[this->present_level]->parents[this->present_index / 2];
-}
-
-
template <int structdim, int dim, int spacedim>
int
TriaAccessor<structdim, dim, spacedim>::
-template <int structdim, int dim, int spacedim>
-void
-TriaAccessor<structdim, dim, spacedim>::set_parent (const unsigned int parent_index)
-{
- Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
- Assert (this->present_level > 0, TriaAccessorExceptions::ExcCellHasNoParent ());
- this->tria->levels[this->present_level]->parents[this->present_index / 2]
- = parent_index;
-}
-
-
-
template <int structdim, int dim, int spacedim>
void
TriaAccessor<structdim, dim, spacedim>::clear_children () const
TriaAccessor<structdim, dim, spacedim>::get_manifold () const
{
Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
+
// Get the default (manifold_id)
- types::manifold_id mi = this->objects().manifold_id[this->present_index];
+ const types::manifold_id mi = this->objects().manifold_id[this->present_index];
// In case this is not valid, check
// the boundary id, after having
// casted it to a manifold id
if(mi == numbers::invalid_manifold_id)
- mi = static_cast<types::manifold_id>
- (structdim < dim ?
- this->objects().boundary_or_material_id[this->present_index].boundary_id:
- dim < spacedim ?
- this->objects().boundary_or_material_id[this->present_index].material_id:
- numbers::invalid_manifold_id);
-
- return this->tria->get_manifold(mi);
+ return this->tria->get_manifold(structdim < dim ?
+ this->objects().boundary_or_material_id[this->present_index].boundary_id:
+ dim < spacedim ?
+ this->objects().boundary_or_material_id[this->present_index].material_id:
+ numbers::invalid_manifold_id);
+ else
+ return this->tria->get_manifold(mi);
}
-
-template <int spacedim>
-inline
-int
-TriaAccessor<0, 1, spacedim>::parent_index ()
-{
- return -1;
-}
-
-
template <int spacedim>
inline
unsigned int
TriaAccessor<0, 1, spacedim>::manifold_id () const
{
if( tria->vertex_to_manifold_id_map_1d->find (this->vertex_index())
- != tria->vertex_to_boundary_id_map_1d->end())
+ != tria->vertex_to_manifold_id_map_1d->end())
return (*tria->vertex_to_manifold_id_map_1d)[this->vertex_index()];
else
return numbers::invalid_manifold_id;
+template <int dim, int spacedim>
+inline
+types::subdomain_id
+CellAccessor<dim, spacedim>::subdomain_id () const
+{
+ Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
+ Assert (this->active(), ExcMessage("subdomains only work on active cells!"));
+ return this->tria->levels[this->present_level]->subdomain_ids[this->present_index];
+}
+
+
+
template <int dim, int spacedim>
inline
unsigned int
}
-template <int dim, int spacedim>
-inline
-bool
-CellAccessor<dim,spacedim>::operator < (const CellAccessor<dim,spacedim> &other) const
-{
- Assert (this->tria == other.tria, TriaAccessorExceptions::ExcCantCompareIterators());
-
- if (level_subdomain_id() != other.level_subdomain_id())
- return (level_subdomain_id() < other.level_subdomain_id());
-
- if (active() && other.active() &&
- (subdomain_id() != other.subdomain_id()))
- return (subdomain_id() < other.subdomain_id());
-
- return TriaAccessorBase<dim,dim,spacedim>::operator < (other);
-}
* but rather one of the derived classes TriaIterator or
* TriaActiveIterator.
*
- * <ul> <li> TriaRawIterator objects point to lines, cells, etc in the
+ * <ul>
+ * <li> TriaRawIterator objects point to lines, cells, etc in the
* lists whether they are used or not (in the vectors, also
* <i>dead</i> objects are stored, since deletion in vectors is
* expensive and we also do not want to destroy the ordering induced
* parameter), which really does the access to data. An Accessor
* has to fulfil some requirements:
*
- * <ul> <li> It must have two members named <tt>present_level</tt> and
+ * <ul>
+ * <li> It must have two members named <tt>present_level</tt> and
* <tt>present_index</tt> storing the address of the element in the
* triangulation presently pointed to. These data have to be
* accessible by all triangulation iterators listed above.
/**
* Ordering relation for iterators.
*
- * This relation attempts a total ordering of cells. For lower
- * dimensional objects on distributed meshes, we only attempt a
- * partial ordering.
+ * This relation attempts a total ordering of cells.
*
* The relation is defined as follows:
*
* For objects of <tt>Accessor::structure_dimension <
* Accessor::dimension</tt>, we simply compare the index of such an
- * object. This consitutes an ordering of the elements of same
- * dimension on a mesh on a single process. For a distributed mesh,
- * the result of the ordering relation between faces across
- * processes is not defined, but most likely irrelevant.
- *
- * For cells, there is a total ordering even in a
- * distributed::parallel::Triangulation. The ordering is lexicographic
+ * object. The ordering is lexicographic
* according to the following hierarchy (in the sense, that the next
* test is only applied if the previous was inconclusive):
*
* past-the-end iterators rank the same, thus false is returned in
* that case.</li>
*
- * <li> The level subdomain id</li>
- * <li> If both cells are active, the subdomain id.</li>
* <li> The level of the cell.</li>
* <li> The index of a cell inside the level.</li>
* </ol>
+ *
+ * @Note: the ordering is not consistent between different processor in
+ * a parallel::distributed::Triangulation because we rely on index(),
+ * which is likely not the same.
*/
bool operator < (const TriaRawIterator &) const;
* In TriaLevel, all cell data is stored which is not dependent on the
* dimension, e.g. a field to store the refinement flag for the cells
* (what a cell actually is is declared elsewhere), etc. See also
- * TriaObjects for non leveloriented data.
+ * TriaObjects for non level-oriented data.
*
* There is another field, which may fit in here, namely the
* material data (for cells) or the boundary indicators (for faces),
* One integer for every consecutive
* pair of cells to store which
* index their parent has.
+ *
+ * (We store this information once for each pair of cells since every
+ * refinement, isotropic or anisotropic, and in any space dimension,
+ * always creates children in multiples of two, so there is no need to
+ * store the parent index for every cell.)
*/
std::vector<int> parents;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
typedef typename ActiveSelector::hex_iterator hex_iterator;
typedef typename ActiveSelector::active_hex_iterator active_hex_iterator;
+ /**
+ * A typedef that is used to to identify
+ * @ref GlossActive "active cell iterators". The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies active cells in a hp::DoFHandler object.
+ * While the actual data type of the typedef is hidden behind a few layers
+ * of (unfortunately necessary) indirections, it is in essence
+ * TriaActiveIterator<DoFCellAccessor>. The TriaActiveIterator
+ * class works like a pointer to active objects that when you
+ * dereference it yields an object of type DoFCellAccessor.
+ * DoFCellAccessor is a class that identifies properties that
+ * are specific to cells in a DoFHandler, but it is derived
+ * (and consequently inherits) from both DoFAccessor, TriaCellAccessor
+ * and TriaAccessor that describe
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation and hp::DoFHandler objects.
+ *
+ * @ingroup Iterators
+ */
typedef typename ActiveSelector::active_cell_iterator active_cell_iterator;
+ typedef typename LevelSelector::cell_iterator level_cell_iterator;
+
+ /**
+ * A typedef that is used to to identify cell iterators. The
+ * concept of iterators is discussed at length in the
+ * @ref Iterators "iterators documentation module".
+ *
+ * The current typedef identifies cells in a DoFHandler object. Some
+ * of these cells may in fact be active (see @ref GlossActive "active cell iterators")
+ * in which case they can in fact be asked for the degrees of freedom
+ * that live on them. On the other hand, if the cell is not active,
+ * any such query will result in an error. Note that this is what distinguishes
+ * this typedef from the level_cell_iterator typedef.
+ *
+ * While the actual data type of the typedef is hidden behind a few layers
+ * of (unfortunately necessary) indirections, it is in essence
+ * TriaIterator<DoFCellAccessor>. The TriaIterator
+ * class works like a pointer to objects that when you
+ * dereference it yields an object of type DoFCellAccessor.
+ * DoFCellAccessor is a class that identifies properties that
+ * are specific to cells in a DoFHandler, but it is derived
+ * (and consequently inherits) from both DoFAccessor, TriaCellAccessor
+ * and TriaAccessor that describe
+ * what you can ask of more general objects (lines, faces, as
+ * well as cells) in a triangulation and DoFHandler objects.
+ *
+ * @ingroup Iterators
+ */
+ typedef typename ActiveSelector::cell_iterator cell_iterator;
+
typedef typename ActiveSelector::face_iterator face_iterator;
typedef typename ActiveSelector::active_face_iterator active_face_iterator;
typedef typename LevelSelector::CellAccessor level_cell_accessor;
typedef typename LevelSelector::FaceAccessor level_face_accessor;
- typedef typename LevelSelector::cell_iterator level_cell_iterator;
typedef typename LevelSelector::face_iterator level_face_iterator;
- typedef level_cell_iterator cell_iterator;
-
/**
* Alias the @p FunctionMap type
* declared elsewhere.
*/
std::vector<types::global_dof_index> vertex_dofs_offsets;
- std::vector<MGVertexDoFs> mg_vertex_dofs;
+ std::vector<MGVertexDoFs> mg_vertex_dofs; // we should really remove this field!
/**
* Array to store the
/**
* In order to avoid creation of static MappingQ1 objects at several
- * places in the library (in particular in backward compatibility
- * functions), we define a static collection of mappings with a single
+ * places in the library, this class
+ * defines a static collection of mappings with a single
* MappingQ1 mapping object once and for all places where it is
* needed.
*/
template<int dim, int spacedim=dim>
struct StaticMappingQ1
{
- private:
- /**
- * A static MappingQ1 object. We can't use the one in ::StaticMappingQ1
- * since we can't make sure that the constructor for that object is run
- * before we want to use the object (when constructing mapping_collection
- * below). Therefore we create a helper function which returns a
- * reference to a static object that will be constructed the first time
- * this function is called.
- */
- static
- MappingQ1<dim,spacedim>& return_static_mapping_q1();
-
public:
/**
* The publicly available
}
}
+ /**
+ * The weak form of the grad-div residual
+ * @f[
+ * \int_Z \nabla\!\cdot\!u \nabla\!\cdot\!v \,dx
+ * @f]
+ *
+ * @author Guido Kanschat
+ * @date 2014
+ */
+ template <int dim, typename number>
+ void grad_div_residual (
+ Vector<number> &result,
+ const FEValuesBase<dim> &fetest,
+ const VectorSlice<const std::vector<std::vector<Tensor<1,dim> > > > &input,
+ const double factor = 1.)
+ {
+ const unsigned int n_dofs = fetest.dofs_per_cell;
+
+ AssertDimension(fetest.get_fe().n_components(), dim);
+ AssertVectorVectorDimension(input, dim, fetest.n_quadrature_points);
+
+ for (unsigned int k=0; k<fetest.n_quadrature_points; ++k)
+ {
+ const double dx = factor * fetest.JxW(k);
+ for (unsigned int i=0; i<n_dofs; ++i)
+ {
+ double dv = 0.;
+ double du = 0.;
+ for (unsigned int d=0; d<dim; ++d)
+ {
+ dv += fetest.shape_grad_component(i,k,d)[d];
+ du += input[d][k][d];
+ }
+
+ result(i) += dx * du * dv;
+ }
+ }
+ }
+
/**
* The jump of the normal component
* @f[
* Print the block structure as a
* LaTeX-array. This output will
* not be very intuitive, since
- * the matrix object lacks
- * important information. What
- * you see is an entry for each
+ * the current object lacks
+ * knowledge about what the individual blocks represent or
+ * how they should be named. Instead, what
+ * you will see is an entry for each
* block showing all the matrices
- * with their multiplicaton
+ * with their multiplication
* factors and possibly transpose
- * mark. The matrices itself are
- * numbered successively upon
- * being entred. If the same
+ * marks. The matrices itself are
+ * named successively as they are encountered. If the same
* matrix is entered several
* times, it will be listed with
- * the same number everytime.
+ * different names.
+ *
+ * As an example, consider the following code:
+ * @code
+ * FullMatrix<double> A1(4,4);
+ * FullMatrix<double> A2(4,4);
+ * FullMatrix<double> B(4,3);
+ * FullMatrix<double> C(3,3);
+ *
+ * BlockMatrixArray<double> block(2,2);
+ *
+ * block.enter(A1,0,0);
+ * block.enter(A2,0,0,2,true);
+ * block.enter(B,0,1,-3.);
+ * block.enter(B,0,1,-3.,true);
+ * block.enter(C,1,1,1.,true);
+ *
+ * block.print_latex(std::cout);
+ * @endcode
+ * The current function will then produce output of the following
+ * kind:
+ * @code
+ * \begin{array}{cc}
+ * M0+2xM1^T & -3xM2-3xM3^T\\
+ * & M4^T
+ * \end{array}
+ * @endcode
+ * Note how the individual blocks here are just numbered successively
+ * as <code>M0</code> to <code>M4</code> and that the output misses
+ * the fact that <code>M2</code> and <code>M3</code> are, in fact,
+ * the same matrix. Nevertheless, the output at least gives some
+ * kind of idea of the block structure of this matrix.
*/
template <class STREAM>
void print_latex (STREAM &out) const;
}
-template<typename number>
-struct BlockMatrixArrayPointerMatrixLess
-{
- bool operator () (const PointerMatrixBase<Vector<number> > *a,
- const PointerMatrixBase<Vector<number> > *b) const
- {
- return *a < *b;
- }
-};
-
-
template <typename number>
template <class STREAM>
inline
Table<2,std::string> array(n_block_rows(), n_block_cols());
- typedef std::map<const PointerMatrixBase<Vector<number> > *,
- std::string, BlockMatrixArrayPointerMatrixLess<number> > NameMap;
+ typedef std::map<const PointerMatrixBase<Vector<number> > *, std::string> NameMap;
NameMap matrix_names;
typename std::vector<Entry>::const_iterator m = entries.begin();
{
out << '\t' << array(i,j);
if (j==n_block_cols()-1)
- out << "\\\\" << std::endl;
+ {
+ if (i != n_block_rows() - 1)
+ out << "\\\\" << std::endl;
+ else
+ out << std::endl;
+ }
else
out << " &";
}
sparsity_pattern.add_entries(actual_dof_indices[i],
actual_dof_indices.begin(),
actual_dof_indices.end(),
- true);
+ true);
// need to add the whole row and column structure in case we keep
// constrained entries. Unfortunately, we can't use the nice matrix
if (dof_mask.n_rows() == n_local_rows && dof_mask.n_cols() == n_local_cols)
dof_mask_is_active = true;
+ // if constrained entries should be kept, need to add rows and columns of
+ // those to the sparsity pattern
+ if (keep_constrained_entries == true)
+ {
+ for (size_type i=0; i<row_indices.size(); i++)
+ if (is_constrained(row_indices[i]))
+ for (size_type j=0; j<col_indices.size(); j++)
+ sparsity_pattern.add (row_indices[i], col_indices[j]);
+ for (size_type i=0; i<col_indices.size(); i++)
+ if (is_constrained(col_indices[i]))
+ for (size_type j=0; j<row_indices.size(); j++)
+ sparsity_pattern.add (row_indices[j], col_indices[i]);
+ }
+
// if the dof mask is not active, all we have to do is to add some indices
// in a matrix format. To do this, we first create an array of all the
// indices that are to be added. these indices are the local dof indices
return;
}
- // if constrained entries should be kept, need to add rows and columns of
- // those to the sparsity pattern
- if (keep_constrained_entries == true)
- {
- for (size_type i=0; i<row_indices.size(); i++)
- if (is_constrained(row_indices[i]))
- for (size_type j=0; j<col_indices.size(); j++)
- sparsity_pattern.add (row_indices[i], col_indices[j]);
- for (size_type i=0; i<col_indices.size(); i++)
- if (is_constrained(col_indices[i]))
- for (size_type j=0; j<row_indices.size(); j++)
- sparsity_pattern.add (row_indices[j], col_indices[i]);
- }
-
// TODO: implement this
Assert (false, ExcNotImplemented());
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
* Assignment operator.
+ *
+ * @dealiiOperationIsMultithreaded
*/
FullMatrix<number> &
operator = (const FullMatrix<number> &);
* This operator assigns a scalar to a matrix. To avoid confusion with the
* semantics of this function, zero is the only value allowed for
* <tt>d</tt>, allowing you to clear a matrix in an intuitive way.
+ *
+ * @dealiiOperationIsMultithreaded
*/
FullMatrix<number> &
operator = (const number d);
(void)d; // removes -Wunused-parameter warning in optimized mode
if (this->n_elements() != 0)
- std::memset (&this->values[0], 0, this->n_elements()*sizeof(number));
+ this->reset_values();
return *this;
}
* it is fast.
*
* @code
- * // Declare related objects
- *
+ * // Declare related objects
* SparseMatrix<double> A;
* Vector<double> x;
* Vector<double> b;
* GrowingVectorMemory<Vector<double> > mem;
-
+ *
* ReductionControl inner_control (10, 1.e-30, 1.e-2);
* PreconditionSSOR <SparseMatrix<double> > inner_precondition;
* inner_precondition.initialize (A, 1.2);
template<typename number> class Vector;
template<typename number> class BlockVector;
template<typename number> class FullMatrix;
+template<typename number> class SparseMatrix;
/**
class LAPACKFullMatrix : public TransposeTable<number>
{
public:
+
/**
* Declare type for container size.
*/
*
* By default, no memory is allocated.
*/
- explicit LAPACKFullMatrix (const size_type n = 0);
+ explicit LAPACKFullMatrix (const size_type size = 0);
+
/**
* Constructor. Initialize the matrix as a rectangular matrix.
LAPACKFullMatrix (const size_type rows,
const size_type cols);
+
/**
* Copy constructor. This constructor does a deep copy of the
* matrix. Therefore, it poses a possible efficiency problem, if for
operator = (const LAPACKFullMatrix<number> &);
/**
- * Assignment operator for a regular FullMatrix. Note that since LAPACK
- * expects matrices in transposed order, this transposition is included
- * here.
+ * Assignment operator from a regular FullMatrix. @note Since LAPACK
+ * expects matrices in transposed order, this transposition is
+ * included here.
*/
template <typename number2>
LAPACKFullMatrix<number> &
operator = (const FullMatrix<number2> &);
+ /**
+ * Assignment operator from a regular SparseMatrix. @note Since
+ * LAPACK expects matrices in transposed order, this transposition
+ * is included here.
+ */
+ template <typename number2>
+ LAPACKFullMatrix<number> &
+ operator = (const SparseMatrix<number2> &);
+
/**
* This operator assigns a scalar to a matrix. To avoid confusion with
* constructors, zero is the only value allowed for <tt>d</tt>
template <class MATRIX>
void copy_from (const MATRIX &);
+ /**
+ * Regenerate the current matrix by one that has the same properties
+ * as if it were created by the constructor of this class with the
+ * same argument list as this present function.
+ */
+ void reinit (const size_type size);
+
+ /**
+ * Regenerate the current matrix by one that has the same properties
+ * as if it were created by the constructor of this class with the
+ * same argument list as this present function.
+ */
+ void reinit (const size_type rows,
+ const size_type cols);
+
+ /**
+ * Return the dimension of the range space. @note The matrix is of
+ * dimension $m \times n$.
+ */
+ unsigned int m () const;
+
+ /**
+ * Return the number of the range space. @note The matrix is of
+ * dimension $m \times n$.
+ */
+ unsigned int n () const;
+
/**
* Fill rectangular block.
*
* system is to be performed.
*/
void apply_lu_factorization (Vector<number> &v,
- const bool transposed) const;
+ const bool transposed) const;
/**
* Solve the linear system with multiple right hand sides (as many as there
* system is to be performed.
*/
void apply_lu_factorization (LAPACKFullMatrix<number> &B,
- const bool transposed) const;
+ const bool transposed) const;
/**
* Compute eigenvalues of the matrix. After this routine has been called,
* @note Calls the LAPACK function Xgeev.
*/
void compute_eigenvalues (const bool right_eigenvectors = false,
- const bool left_eigenvectors = false);
+ const bool left_eigenvectors = false);
/**
* Compute eigenvalues and eigenvectors of a real symmetric matrix. Only
* @note Calls the LAPACK function Xsyevx. For this to work, ./configure has
* to be told to use LAPACK.
*/
- void compute_eigenvalues_symmetric(
- const number lower_bound,
- const number upper_bound,
- const number abs_accuracy,
- Vector<number> &eigenvalues,
- FullMatrix<number> &eigenvectors);
+ void compute_eigenvalues_symmetric (const number lower_bound,
+ const number upper_bound,
+ const number abs_accuracy,
+ Vector<number> &eigenvalues,
+ FullMatrix<number> &eigenvectors);
/**
* Compute generalized eigenvalues and eigenvectors of a real generalized
* @note Calls the LAPACK function Xsygvx. For this to work, ./configure has
* to be told to use LAPACK.
*/
- void compute_generalized_eigenvalues_symmetric(
- LAPACKFullMatrix<number> &B,
- const number lower_bound,
- const number upper_bound,
- const number abs_accuracy,
- Vector<number> &eigenvalues,
- std::vector<Vector<number> > &eigenvectors,
- const int itype = 1);
+ void compute_generalized_eigenvalues_symmetric (LAPACKFullMatrix<number> &B,
+ const number lower_bound,
+ const number upper_bound,
+ const number abs_accuracy,
+ Vector<number> &eigenvalues,
+ std::vector<Vector<number> > &eigenvectors,
+ const int itype = 1);
/**
* Same as the other compute_generalized_eigenvalues_symmetric function
* @note Calls the LAPACK function Xsygv. For this to work, ./configure has
* to be told to use LAPACK.
*/
- void compute_generalized_eigenvalues_symmetric (
- LAPACKFullMatrix<number> &B,
- std::vector<Vector<number> > &eigenvectors,
- const int itype = 1);
+ void compute_generalized_eigenvalues_symmetric (LAPACKFullMatrix<number> &B,
+ std::vector<Vector<number> > &eigenvectors,
+ const int itype = 1);
/**
* Compute the singular value decomposition of the matrix using LAPACK
* #wr, #svd_u, and #svd_vt, and leaves the object in the #state
* LAPACKSupport::svd.
*/
- void compute_svd();
+ void compute_svd ();
/**
* Compute the inverse of the matrix by singular value decomposition.
const double threshold = 0.) const;
private:
+
/**
- * Since LAPACK operations notoriously change the meaning of the matrix
- * entries, we record the current state after the last operation here.
+ * Since LAPACK operations notoriously change the meaning of the
+ * matrix entries, we record the current state after the last
+ * operation here.
*/
LAPACKSupport::State state;
SmartPointer<VectorMemory<Vector<number> >,PreconditionLU<number> > mem;
};
+/*---------------------- Inline functions -----------------------------------*/
+template <typename number>
+inline
+unsigned int
+LAPACKFullMatrix<number>::m () const
+{
+ return this->n_rows ();
+}
+
+template <typename number>
+inline
+unsigned int
+LAPACKFullMatrix<number>::n () const
+{
+ return this->n_cols ();
+}
template <typename number>
template <class MATRIX>
* quadratic matrices #m1 and #m2 of arbitrary types and implements
* matrix-vector multiplications for the product
* <i>M<sub>1</sub>M<sub>2</sub></i> by performing multiplication with
- * both factors consecutively.
+ * both factors consecutively. Because the types of the matrices are
+ * opaque (i.e., they can be arbitrary), you can stack products of three
+ * or more matrices by making one of the two matrices an object of the
+ * current type handles be a ProductMatrix itself.
*
- * Here an example multiplying two different FullMatrix objects:
+ * Here is an example multiplying two different FullMatrix objects:
* @include product_matrix.cc
*
* @author Guido Kanschat, 2000, 2001, 2002, 2005
const MATRIX2 &m2,
VectorMemory<VECTOR> &mem);
+ /**
+ * Destructor.
+ */
+ ~ProductMatrix();
+
/**
* Change the matrices.
*/
void initialize(const MATRIX1 &m1, const MATRIX2 &m2,
VectorMemory<VECTOR> &mem);
- /**
- * Destructor.
- */
- ~ProductMatrix();
-
// Doc in PointerMatrixBase
void clear();
const VECTOR &v) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product <i>w = m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
*/
const VECTOR &v) const;
/**
- * Adding, tranposed
+ * Adding, transposed
* matrix-vector product <i>w +=
* m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
* Memory for auxiliary vector.
*/
SmartPointer<VectorMemory<VECTOR>,ProductMatrix<VECTOR> > mem;
- /**
- * Return some kind of
- * identifier.
- */
- virtual const void *get() const;
};
/**
- * A matrix that is the scaled version of another matrix.
+ * A matrix that is the multiple of another matrix.
*
* Matrix-vector products of this matrix are composed of those of the
- * original matrix and scaling by a constant factor.
+ * original matrix with the vector and then scaling of the result by
+ * a constant factor.
*
* @author Guido Kanschat, 2007
*/
void initialize (const MATRIX &M, const double factor);
/**
- * Delete internal matrix pointer.
+ * Reset the object to its original state.
*/
void clear ();
/**
* Constructor leaving an
- * unitialized
+ * uninitialized
* matrix. initialize() must be
* called, before the matrix can
* be used.
const VectorType &v) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product <i>w = m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
*/
const VectorType &v) const;
/**
- * Adding, tranposed
+ * Adding, transposed
* matrix-vector product <i>w +=
* m2<sup>T</sup> *
* m1<sup>T</sup> * v</i>.
* Memory for auxiliary vector.
*/
SmartPointer<VectorMemory<VectorType>,ProductSparseMatrix<number,vector_number> > mem;
- /**
- * Return some kind of
- * identifier.
- */
- virtual const void *get() const;
};
* BlockVector, then an additional parameter selects a single
* component for this operation.
*
+ * In mathematical terms, this class acts as if it was the matrix
+ * $I-\frac 1n{\mathbf 1}_n{\mathbf 1}_n^T$ where ${\mathbf 1}_n$ is
+ * a vector of size $n$ that has only ones as its entries. Thus,
+ * taking the dot product between a vector $\mathbf v$ and
+ * $\frac 1n {\mathbf 1}_n$ yields the <i>mean value</i> of the entries
+ * of ${\mathbf v}$. Consequently,
+ * $ \left[I-\frac 1n{\mathbf 1}_n{\mathbf 1}_n^T\right] \mathbf v
+ * = \mathbf v - \left[\frac 1n \mathbf v} \cdot {\mathbf 1}_n\right]{\mathbf 1}_n$
+ * subtracts from every vector element the mean value of all elements.
+ *
* @author Guido Kanschat, 2002, 2003
*/
class MeanValueFilter : public Subscriptor
* Constructor, optionally
* selecting a component.
*/
- MeanValueFilter(size_type component = numbers::invalid_size_type);
+ MeanValueFilter(const size_type component = numbers::invalid_size_type);
/**
* Subtract mean value from @p v.
/**
* Component for filtering block vectors.
*/
- size_type component;
+ const size_type component;
};
/**
- * Inverse matrix computed approximately by using the SolverRichardson
- * iterative solver. In particular, the function
- * SolverRichardson::Tsolve() allows for the implementation of
- * transpose matrix vector products.
+ * Objects of this type represent the inverse of a matrix as
+ * computed approximately by using the SolverRichardson
+ * iterative solver. In other words, if you set up an object
+ * of the current type for a matrix $A$, then calling the
+ * vmult() function with arguments $v,w$ amounts to setting
+ * $w=A^{-1}v$ by solving the linear system $Aw=v$ using the
+ * Richardson solver with a preconditioner that can be chosen. Similarly,
+ * this class allows to also multiple with the transpose of the
+ * inverse (i.e., the inverse of the transpose) using the function
+ * SolverRichardson::Tsolve().
*
- * The functions vmult() and Tvmult() appoximate the inverse
+ * The functions vmult() and Tvmult() approximate the inverse
* iteratively starting with the vector <tt>dst</tt>. Functions
* vmult_add() and Tvmult_add() start the iteration with a zero
- * vector.
+ * vector. All of the matrix-vector multiplication functions
+ * expect that the Richardson solver with the given preconditioner
+ * actually converge. If the Richardson solver does not converge
+ * within the specified number of iterations, the exception that will
+ * result in the solver will simply be propagated to the caller of
+ * the member function of the current class.
+ *
+ * @note A more powerful version of this class is provided by the
+ * IterativeInverse class.
*
* @note Instantiations for this template are provided for <tt>@<float@> and
* @<double@></tt>; others can be generated in application programs (see the
}
-template<class VECTOR>
-const void *
-ProductMatrix<VECTOR>::get () const
-{
- return (void *) m1;
-}
-
//---------------------------------------------------------------------------
Assert (matrix != 0, ExcNotInitialized());
Assert (precondition != 0, ExcNotInitialized());
dst = 0.;
- try
- {
- solver.solve(*matrix, dst, src, *precondition);
- }
- catch (...)
- {}
+ solver.solve(*matrix, dst, src, *precondition);
}
Assert (precondition != 0, ExcNotInitialized());
VECTOR *aux = mem.alloc();
aux->reinit(dst);
- try
- {
- solver.solve(*matrix, *aux, src, *precondition);
- }
- catch (...)
- {}
+
+ solver.solve(*matrix, *aux, src, *precondition);
+
dst += *aux;
mem.free(aux);
}
Assert (matrix != 0, ExcNotInitialized());
Assert (precondition != 0, ExcNotInitialized());
dst = 0.;
- try
- {
- solver.Tsolve(*matrix, dst, src, *precondition);
- }
- catch (...)
- {}
+ solver.Tsolve(*matrix, dst, src, *precondition);
}
Assert (precondition != 0, ExcNotInitialized());
VECTOR *aux = mem.alloc();
aux->reinit(dst);
- try
- {
- solver.Tsolve(*matrix, *aux, src, *precondition);
- }
- catch (...)
- {}
+
+ solver.Tsolve(*matrix, *aux, src, *precondition);
+
dst += *aux;
mem.free(aux);
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/lac/vector_view.h>
#include <cstring>
+#include <iomanip>
DEAL_II_NAMESPACE_OPEN
* ghost entries in the vector layout (for that information, use
* n_ghost_entries() instead).
*
+ * This vector uses the facilities of the class dealii::Vector<Number> for
+ * implementing the operations on the local range of the vector. In
+ * particular, it also inherits thread parallelism that splits most
+ * vector-vector operations into smaller chunks if the program uses
+ * multiple threads. This may or may not be desired when working also with
+ * MPI.
+ *
* @author Katharina Kormann, Martin Kronbichler, 2010, 2011
*/
template <typename Number>
std::size_t memory_consumption () const;
//@}
+ /**
+ * Exception
+ */
+ DeclException3 (ExcNonMatchingElements,
+ double, double, unsigned int,
+ << "Called compress(VectorOperation::insert), but"
+ << " the element received from a remote processor, value "
+ << std::setprecision(16) << arg1
+ << ", does not match with the value "
+ << std::setprecision(16) << arg2
+ << " on the owner processor " << arg3);
+
private:
/**
* Local part of all_zero().
{
reinit (v, true);
vector_view = v.vector_view;
+ zero_out_ghosts();
}
for (size_type j=my_imports->first; j<my_imports->second;
j++, read_position++)
Assert(*read_position == 0. ||
- std::abs(local_element(j) - *read_position) <
+ std::abs(local_element(j) - *read_position) <=
std::abs(local_element(j)) * 1000. *
std::numeric_limits<Number>::epsilon(),
- ExcMessage("Inserted elements do not match."));
+ ExcNonMatchingElements(*read_position, local_element(j),
+ part.this_mpi_process()));
AssertDimension(read_position-import_data,part.n_import_indices());
}
#ifdef DEAL_II_WITH_MPI
#ifdef DEBUG
- // make sure that there are not outstanding requests from updating ghost
- // values or compress
- int flag = 1;
- int ierr = MPI_Testall (update_ghost_values_requests.size(),
- &update_ghost_values_requests[0],
+ if (Utilities::System::job_supports_mpi())
+ {
+ // make sure that there are not outstanding requests from updating
+ // ghost values or compress
+ int flag = 1;
+ int ierr = MPI_Testall (update_ghost_values_requests.size(),
+ &update_ghost_values_requests[0],
+ &flag, MPI_STATUSES_IGNORE);
+ Assert (ierr == MPI_SUCCESS, ExcInternalError());
+ Assert (flag == 1,
+ ExcMessage("MPI found unfinished update_ghost_values() requests"
+ "when calling swap, which is not allowed"));
+ ierr = MPI_Testall (compress_requests.size(), &compress_requests[0],
&flag, MPI_STATUSES_IGNORE);
- Assert (ierr == MPI_SUCCESS, ExcInternalError());
- Assert (flag == 1,
- ExcMessage("MPI found unfinished update_ghost_values() requests"
- "when calling swap, which is not allowed"));
- ierr = MPI_Testall (compress_requests.size(), &compress_requests[0],
- &flag, MPI_STATUSES_IGNORE);
- Assert (ierr == MPI_SUCCESS, ExcInternalError());
- Assert (flag == 1,
- ExcMessage("MPI found unfinished compress() requests "
- "when calling swap, which is not allowed"));
+ Assert (ierr == MPI_SUCCESS, ExcInternalError());
+ Assert (flag == 1,
+ ExcMessage("MPI found unfinished compress() requests "
+ "when calling swap, which is not allowed"));
+ }
#endif
std::swap (compress_requests, v.compress_requests);
Vector &
Vector::operator = (const Vector &v)
{
+ // make sure left- and right-hand side of the assignment are compress()'ed:
+ Assert(v.last_action == VectorOperation::unknown,
+ internal::VectorReference::ExcWrongMode (VectorOperation::unknown,
+ v.last_action));
+ Assert(last_action == VectorOperation::unknown,
+ internal::VectorReference::ExcWrongMode (VectorOperation::unknown,
+ last_action));
+
+
if (v.size()==0)
{
// this happens if v has not been initialized to something useful:
/**
* The method allows to take advantage
* if the system matrix is symmetric by
- * using LDL^T decomposition unstead of
+ * using LDL^T decomposition instead of
* more expensive LU. The argument
* indicates whether the matrix is
* symmetric or not.
/**
* Virtual destructor. Does
* nothing except making sure that
- * the destructor of the derived
- * class is called.
+ * the destructor of any derived
+ * class is called whenever a pointer-to-base-class object is destroyed.
*/
virtual ~PointerMatrixBase ();
/**
- * Reset pointer and release the
- * matrix pointed to.
+ * Reset the object to its original state.
*/
virtual void clear () = 0;
- /**
- * Find out if two matrices point
- * to the same object.
- */
- bool operator == (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if two matrices do
- * not point to the same object.
- */
- bool operator != (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * less.
- */
- bool operator < (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * less or equal.
- */
- bool operator <= (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * greater.
- */
- bool operator > (const PointerMatrixBase<VECTOR> &) const;
-
- /**
- * Find out if this pointer is
- * greater or equal.
- */
- bool operator >= (const PointerMatrixBase<VECTOR> &) const;
-
-
/**
* Matrix-vector product.
*/
const VECTOR &src) const = 0;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const = 0;
const VECTOR &src) const = 0;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const = 0;
-
-private:
- /**
- * Get the pointer for comparison.
- */
- virtual const void *get() const = 0;
};
+
/**
* A pointer to be used as a matrix. This class stores a pointer to a
* matrix and can be used as a matrix itself in iterative methods.
PointerMatrix (const MATRIX *M=0);
/**
- * Constructor. The name argument
- * is used to identify the
- * SmartPointer for this object.
+ * Constructor.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrix(const char *name);
* Constructor. <tt>M</tt> points
* to a matrix which must live
* longer than the
- * PointerMatrix. The name
- * argument is used to identify
- * the SmartPointer for this
- * object.
+ * PointerMatrix.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrix(const MATRIX *M,
const char *name);
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const;
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
/**
* Constructor not using a
- * matrix. The name argument is
- * used to identify the
- * SmartPointer for this object.
+ * matrix.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrixAux(VectorMemory<VECTOR> *mem,
const char *name);
* Constructor. <tt>M</tt> points
* to a matrix which must live
* longer than the
- * PointerMatrixAux. The name
- * argument is used to identify
- * the SmartPointer for this
- * object.
+ * PointerMatrixAux.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrixAux(VectorMemory<VECTOR> *mem,
const MATRIX *M,
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product.
+ * Transposed matrix-vector product.
*/
virtual void Tvmult (VECTOR &dst,
const VECTOR &src) const;
const VECTOR &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*/
virtual void Tvmult_add (VECTOR &dst,
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The backup memory if none was provided.
*/
PointerMatrixVector (const Vector<number> *M=0);
/**
- * Constructor. The name argument
- * is used to identify the
- * SmartPointer for this object.
+ * Constructor.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrixVector (const char *name);
* Constructor. <tt>M</tt> points
* to a matrix which must live
* longer than the
- * PointerMatrix. The name
- * argument is used to identify
- * the SmartPointer for this
- * object.
+ * PointerMatrix.
+ *
+ * This class internally stores a pointer to a matrix via a SmartPointer
+ * object. The SmartPointer class allows to associate a name with the
+ * object pointed to that identifies the object that has the pointer,
+ * in order to identify objects that still refer to the object pointed to.
+ * The @p name argument to this function
+ * is used to this end, i.e., you can in essence assign a name to
+ * the current PointerMatrix object.
*/
PointerMatrixVector (const Vector<number> *M,
const char *name);
const Vector<number> &src) const;
/**
- * Tranposed matrix-vector
+ * Transposed matrix-vector
* product, actually the
* multiplication of the vector
* representing this matrix with
const Vector<number> &src) const;
/**
- * Tranposed matrix-vector product,
+ * Transposed matrix-vector product,
* adding to <tt>dst</tt>.
*
* The dimension of <tt>src</tt>
const Vector<number> &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator == (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() == other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator != (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() != other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator < (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() < other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator <= (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() <= other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator > (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() > other.get());
-}
-
-
-
-template<class VECTOR>
-inline
-bool
-PointerMatrixBase<VECTOR>::operator >= (const PointerMatrixBase<VECTOR> &other) const
-{
- return (get() >= other.get());
-}
-
-
//----------------------------------------------------------------------//
}
-template<class MATRIX, class VECTOR>
-inline const void *
-PointerMatrix<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
//----------------------------------------------------------------------//
}
-template<class MATRIX, class VECTOR>
-inline const void *
-PointerMatrixAux<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
-
//----------------------------------------------------------------------//
}
-template<typename number>
-inline const void *
-PointerMatrixVector<number>::get () const
-{
- return m;
-}
-
-
-
DEAL_II_NAMESPACE_CLOSE
#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/*@{*/
/**
- * Preconditioned cg method for symmetric positive definite matrices.
- *
- * For the requirements on matrices and vectors in order to work with
- * this class, see the documentation of the Solver base class.
+ * Preconditioned cg method for symmetric positive definite matrices. This
+ * class is used first in step-3 and step-4, but is used in many other
+ * tutorial programs as well. Like all other solver classes, it can work on
+ * any kind of vector and matrix as long as they satisfy certain requirements
+ * (for the requirements on matrices and vectors in order to work with this
+ * class, see the documentation of the Solver base class). The type of the
+ * solution vector must be passed as template argument, and defaults to
+ * dealii::Vector<double>.
*
* Like all other solver classes, this class has a local structure
* called @p AdditionalData which is used to pass additional
* a switch allowing for additional output for the computation of
* eigenvalues of the matrix.
*
- * <h3>Eigenvalue computation</h3>
+ * @note This version of CG is taken from D. Braess's book "Finite
+ * Elements". It requires a symmetric preconditioner (i.e., for example, SOR
+ * is not a possible choice).
*
- * See Y. Saad: "Iterative methods for Sparse Linear Systems", section
- * 6.7.3 for details.
+ * <h3>Eigenvalue computation</h3>
*
* The cg-method performs an orthogonal projection of the original
* preconditioned linear system to another system of smaller
* <tt>sqrt(beta_0)/alpha_0</tt>, ..., <tt>sqrt(beta_{m-2</tt>)/alpha_{m-2}}.
* The eigenvalues of this matrix can be computed by postprocessing.
*
- * This version of CG is taken from Braess: "Finite Elements". It
- * requires a symmetric preconditioner, i.e. SOR is not feasible.
+ * See Y. Saad: "Iterative methods for Sparse Linear Systems", section
+ * 6.7.3 for details.
*
* @author W. Bangerth, G. Kanschat, R. Becker and F.-T. Suttmeier
*/
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
virtual void print_info (std::ostream &out) const
{
out << "Iterative method reported convergence failure in step "
- << last_step << " with residual " << last_residual << std::endl;
+ << last_step << ". The residual in the last step was " << last_residual
+ << ".\n\n"
+ << "This error message can indicate that you have simply not allowed "
+ << "a sufficiently large number of iterations for your iterative solver "
+ << "to converge. This often happens when you increase the size of your "
+ << "problem. In such cases, the last residual will likely still be very "
+ << "small, and you can make the error go away by increasing the allowed "
+ << "number of iterations when setting up the SolverControl object that "
+ << "determines the maximal number of iterations you allow."
+ << "\n\n"
+ << "The other situation where this error may occur is when your matrix "
+ << "is not invertible (e.g., your matrix has a null-space), or if you "
+ << "try to apply the wrong solver to a matrix (e.g., using CG for a "
+ << "matrix that is not symmetric or not positive definite). In these "
+ << "cases, the residual in the last iteration is likely going to be large."
+ << std::endl;
}
/**
#include <deal.II/lac/solver.h>
#include <deal.II/lac/solver_control.h>
#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/lapack_full_matrix.h>
#include <deal.II/lac/vector.h>
#include <vector>
AdditionalData (const unsigned int max_n_tmp_vectors = 30,
const bool right_preconditioning = false,
const bool use_default_residual = true,
- const bool force_re_orthogonalization = false);
+ const bool force_re_orthogonalization = false,
+ const bool compute_eigenvalues = false);
/**
* Maximum number of temporary vectors. This parameter controls the size
* if necessary.
*/
bool force_re_orthogonalization;
+
+ /**
+ * Compute all eigenvalues of the Hessenberg matrix generated while
+ * solving, i.e., the projected system matrix. This gives an approximation
+ * of the eigenvalues of the (preconditioned) system matrix. Since the
+ * Hessenberg matrix is thrown away at restart, the eigenvalues are
+ * printed for every 30 iterations.
+ *
+ * @note Requires LAPACK support.
+ */
+ bool compute_eigenvalues;
};
/**
}
return *data[i-offset];
}
+
+ // A comparator for better printing eigenvalues
+ inline
+ bool complex_less_pred(const std::complex<double> &x,
+ const std::complex<double> &y)
+ {
+ return x.real() < y.real() || (x.real() == y.real() && x.imag() < y.imag());
+ }
}
}
AdditionalData (const unsigned int max_n_tmp_vectors,
const bool right_preconditioning,
const bool use_default_residual,
- const bool force_re_orthogonalization)
+ const bool force_re_orthogonalization,
+ const bool compute_eigenvalues)
:
max_n_tmp_vectors(max_n_tmp_vectors),
right_preconditioning(right_preconditioning),
use_default_residual(use_default_residual),
- force_re_orthogonalization(force_re_orthogonalization)
+ force_re_orthogonalization(force_re_orthogonalization),
+ compute_eigenvalues (compute_eigenvalues)
{}
// restart
unsigned int accumulated_iterations = 0;
+ // for eigenvalue computation, need to collect the Hessenberg matrix (before
+ // applying Givens rotations)
+ FullMatrix<double> H_orig;
+ if (additional_data.compute_eigenvalues)
+ H_orig.reinit(n_tmp_vectors, n_tmp_vectors-1);
+
// matrix used for the orthogonalization process later
H.reinit(n_tmp_vectors, n_tmp_vectors-1);
if (numbers::is_finite(1./s))
vv *= 1./s;
+ // for eigenvalues, get the resulting coefficients from the
+ // orthogonalization process
+ if (additional_data.compute_eigenvalues)
+ for (unsigned int i=0; i<dim+1; ++i)
+ H_orig(i,inner_iteration) = h(i);
+
// Transformation into triagonal structure
givens_rotation(h,gamma,ci,si,inner_iteration);
for (unsigned int j=0; j<dim; ++j)
H1(i,j) = H(i,j);
+ // compute eigenvalues from the Hessenberg matrix generated during the
+ // inner iterations
+ if (additional_data.compute_eigenvalues)
+ {
+ LAPACKFullMatrix<double> mat(dim,dim);
+ for (unsigned int i=0; i<dim; ++i)
+ for (unsigned int j=0; j<dim; ++j)
+ mat(i,j) = H_orig(i,j);
+ mat.compute_eigenvalues();
+ std::vector<std::complex<double> > eigenvalues(dim);
+ for (unsigned int i=0; i<mat.n(); ++i)
+ eigenvalues[i] = mat.eigenvalue(i);
+
+ std::sort(eigenvalues.begin(), eigenvalues.end(),
+ internal::SolverGMRES::complex_less_pred);
+
+ deallog << "Eigenvalue estimate: ";
+ for (unsigned int i=0; i<mat.n(); ++i)
+ deallog << ' ' << eigenvalues[i];
+ deallog << std::endl;
+ }
+
H1.backward(h,gamma);
if (left_precondition)
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/lac/sparsity_pattern.h>
#include <deal.II/lac/identity_matrix.h>
#include <deal.II/lac/exceptions.h>
-// Included for VectorOperation
#include <deal.II/lac/vector.h>
DEAL_II_NAMESPACE_OPEN
friend class Iterator;
/**
- * Make the inner reference class a friend if the compiler has a bug and
- * requires this.
+ * Make the SparseMatrix class a friend so that it, in turn, can
+ * declare the Reference class a friend.
*/
+ template <typename> friend class dealii::SparseMatrix;
};
* exists to allow for the obvious notation <tt>matrix=0</tt>, which sets
* all elements of the matrix to zero, but keep the sparsity pattern
* previously used.
+ *
+ * @dealiiOperationIsMultithreaded
*/
SparseMatrix &operator = (const double d);
* yourself, you should also rename this function to avoid programs relying
* on outdated information!
*
- * @internal @deprecated Use iterator or const_iterator instead!
+ * @deprecated Use iterator or const_iterator instead!
*/
number global_entry (const size_type i) const DEAL_II_DEPRECATED;
/**
* Same as above, but with write access. You certainly know what you do?
*
- * @internal @deprecated Use iterator or const_iterator instead!
+ * @deprecated Use iterator or const_iterator instead!
*/
number &global_entry (const size_type i) DEAL_II_DEPRECATED;
* consider using a BlockSparseMatrix as well.
*
* Source and destination must not be the same vector.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <class OutVector, class InVector>
void vmult (OutVector &dst,
* consider using a BlockSparseMatrix as well.
*
* Source and destination must not be the same vector.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <class OutVector, class InVector>
void vmult_add (OutVector &dst,
* The underlying template types of both this matrix and the given vector
* should either both be real or complex-valued, but not mixed, for this
* function to make sense.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <typename somenumber>
somenumber matrix_norm_square (const Vector<somenumber> &v) const;
/**
* Compute the matrix scalar product $\left(u,Mv\right)$.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <typename somenumber>
somenumber matrix_scalar_product (const Vector<somenumber> &u,
* <i>l<sub>2</sub></i> norm of the residual vector is returned.
*
* Source <i>x</i> and destination <i>dst</i> must not be the same vector.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <typename somenumber>
somenumber residual (Vector<somenumber> &dst,
*/
template <typename,bool> friend class SparseMatrixIterators::Iterator;
template <typename,bool> friend class SparseMatrixIterators::Accessor;
+
+ template <typename number2> friend class SparseMatrixIterators::Accessor<number2, false>::Reference;
};
#ifndef DOXYGEN
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
&B.val[new_cols-&sp_B.colnums[sp_B.rowstart[0]]];
const numberB *const end_cols = &B.val[sp_B.rowstart[col+1]];
for (; B_val_ptr != end_cols; ++B_val_ptr)
- *new_ptr++ = A_val **B_val_ptr * (use_vector ? V(col) : 1);
+ *new_ptr++ = A_val * *B_val_ptr * (use_vector ? V(col) : 1);
C.add (i, new_ptr-&new_entries[0], new_cols, &new_entries[0],
false, true);
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2002 - 2013 by the deal.II authors
+// Copyright (C) 2002 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
* Increment when a row grows.
*/
unsigned int increment;
-
- /**
- * Make member classes
- * friends. Not strictly
- * necessary according to the
- * standard, but some compilers
- * require this...
- */
};
/**
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/config.h>
#include <deal.II/base/exceptions.h>
+#include <deal.II/lac/sparsity_pattern.h>
#include <vector>
DEAL_II_NAMESPACE_OPEN
-class SparsityPattern;
-
-
/*! @addtogroup Sparsity
*@{
*/
namespace SparsityTools
{
- /**
- * Declare type for container size.
- */
- typedef types::global_dof_index size_type;
-
/**
* Use the METIS partitioner to generate a partitioning of the degrees of
* freedom represented by this sparsity pattern. In effect, we view this
*/
void
reorder_Cuthill_McKee (const SparsityPattern &sparsity,
- std::vector<size_type> &new_indices,
- const std::vector<size_type> &starting_indices = std::vector<size_type>());
+ std::vector<SparsityPattern::size_type> &new_indices,
+ const std::vector<SparsityPattern::size_type> &starting_indices = std::vector<SparsityPattern::size_type>());
#ifdef DEAL_II_WITH_MPI
*/
template <class CSP_t>
void distribute_sparsity_pattern(CSP_t &csp,
- const std::vector<size_type> &rows_per_cpu,
+ const std::vector<typename CSP_t::size_type> &rows_per_cpu,
const MPI_Comm &mpi_comm,
const IndexSet &myrange);
const VECTOR &src) const;
private:
- /**
- * Return the address of the
- * matrix for comparison.
- */
- virtual const void *get() const;
-
/**
* The pointer to the actual matrix.
*/
}
-template<class MATRIX, class VECTOR>
-inline const void *
-TransposeMatrix<MATRIX, VECTOR>::get () const
-{
- return m;
-}
-
-
-
DEAL_II_NAMESPACE_CLOSE
#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
typedef dealii::types::global_dof_index size_type;
/**
- * Standardized data struct to
- * pipe additional flags to the
+ * Standardized data struct to pipe additional flags to the
* preconditioner.
*/
struct AdditionalData
{};
/**
- * Constructor. Does not do
- * anything. The
- * <tt>initialize</tt> function
- * of the derived classes will
- * have to create the
- * preconditioner from a given
+ * Constructor. Does not do anything. The <tt>initialize</tt> function of
+ * the derived classes will have to create the preconditioner from a given
* sparse matrix.
*/
PreconditionBase ();
~PreconditionBase ();
/**
- * Destroys the preconditioner, leaving
- * an object like just after having
+ * Destroys the preconditioner, leaving an object like just after having
* called the constructor.
*/
void clear ();
const VectorBase &src) const;
/**
- * Apply the preconditioner on
- * deal.II data structures
- * instead of the ones provided
- * in the Trilinos wrapper
- * class.
+ * Apply the preconditioner on deal.II data structures instead of the ones
+ * provided in the Trilinos wrapper class.
*/
virtual void vmult (dealii::Vector<double> &dst,
const dealii::Vector<double> &src) const;
/**
- * Apply the transpose preconditioner on
- * deal.II data structures
- * instead of the ones provided
- * in the Trilinos wrapper
- * class.
+ * Apply the transpose preconditioner on deal.II data structures instead
+ * of the ones provided in the Trilinos wrapper class.
*/
virtual void Tvmult (dealii::Vector<double> &dst,
const dealii::Vector<double> &src) const;
/**
- * Apply the preconditioner on deal.II
- * parallel data structures instead of
- * the ones provided in the Trilinos
- * wrapper class.
+ * Apply the preconditioner on deal.II parallel data structures instead of
+ * the ones provided in the Trilinos wrapper class.
*/
virtual void vmult (dealii::parallel::distributed::Vector<double> &dst,
const dealii::parallel::distributed::Vector<double> &src) const;
/**
- * Apply the transpose preconditioner on deal.II
- * parallel data structures instead of
- * the ones provided in the Trilinos
- * wrapper class.
+ * Apply the transpose preconditioner on deal.II parallel data structures
+ * instead of the ones provided in the Trilinos wrapper class.
*/
virtual void Tvmult (dealii::parallel::distributed::Vector<double> &dst,
const dealii::parallel::distributed::Vector<double> &src) const;
protected:
/**
- * This is a pointer to the
- * preconditioner object that
- * is used when applying the
- * preconditioner.
+ * This is a pointer to the preconditioner object that is used when
+ * applying the preconditioner.
*/
std_cxx1x::shared_ptr<Epetra_Operator> preconditioner;
/**
- * Internal communication
- * pattern in case the matrix
- * needs to be copied from
- * deal.II format.
+ * Internal communication pattern in case the matrix needs to be copied
+ * from deal.II format.
*/
#ifdef DEAL_II_WITH_MPI
Epetra_MpiComm communicator;
#endif
/**
- * Internal Trilinos map in
- * case the matrix needs to be
- * copied from deal.II format.
+ * Internal Trilinos map in case the matrix needs to be copied from
+ * deal.II format.
*/
std_cxx1x::shared_ptr<Epetra_Map> vector_distributor;
};
public:
/**
- * Standardized data struct to
- * pipe additional flags to the
- * preconditioner. The
- * parameter <tt>omega</tt>
- * specifies the relaxation
- * parameter in the Jacobi
- * preconditioner. The
- * parameter
- * <tt>min_diagonal</tt> can be
- * used to make the application
- * of the preconditioner also
- * possible when some diagonal
- * elements are zero. In a
- * default application this
- * would mean that we divide by
- * zero, so by setting the
- * parameter
- * <tt>min_diagonal</tt> to a
- * small nonzero value the SOR
- * will work on a matrix that
- * is not too far away from the
- * one we want to
- * treat.
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>omega</tt> specifies the relaxation
+ * parameter in the Jacobi preconditioner. The parameter
+ * <tt>min_diagonal</tt> can be used to make the application of the
+ * preconditioner also possible when some diagonal elements are zero. In a
+ * default application this would mean that we divide by zero, so by
+ * setting the parameter <tt>min_diagonal</tt> to a small nonzero value
+ * the SOR will work on a matrix that is not too far away from the one we
+ * want to treat.
*/
struct AdditionalData
{
/**
- * Constructor. By default, set
- * the damping parameter to
- * one, and do not modify the
- * diagonal.
+ * Constructor. By default, set the damping parameter to one, and do not
+ * modify the diagonal.
*/
AdditionalData (const double omega = 1,
- const double min_diagonal = 0);
+ const double min_diagonal = 0,
+ const unsigned int n_sweeps = 1);
/**
- * This specifies the
- * relaxation parameter in the
- * Jacobi preconditioner.
+ * This specifies the relaxation parameter in the Jacobi preconditioner.
*/
double omega;
/**
- * This specifies the minimum
- * value the diagonal elements
- * should have. This might be
- * necessary when the Jacobi
- * preconditioner is used on
- * matrices with zero diagonal
- * elements. In that case, a
- * straight-forward application
- * would not be possible since
- * we would divide by zero.
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the Jacobi preconditioner is used
+ * on matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we would
+ * divide by zero.
*/
double min_diagonal;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
};
/**
- * Take the sparse matrix the
- * preconditioner object should
- * be built of, and additional
- * flags (damping parameter,
- * etc.) if there are any.
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, etc.) if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
public:
/**
- * Standardized data struct to
- * pipe additional flags to the
- * preconditioner. The
- * parameter <tt>omega</tt>
- * specifies the relaxation
- * parameter in the SSOR
- * preconditioner. The
- * parameter
- * <tt>min_diagonal</tt> can be
- * used to make the application
- * of the preconditioner also
- * possible when some diagonal
- * elements are zero. In a
- * default application this
- * would mean that we divide by
- * zero, so by setting the
- * parameter
- * <tt>min_diagonal</tt> to a
- * small nonzero value the SOR
- * will work on a matrix that
- * is not too far away from the
- * one we want to
- * treat. Finally,
- * <tt>overlap</tt> governs the
- * overlap of the partitions
- * when the preconditioner runs
- * in parallel, forming a
- * so-called additive Schwarz
- * preconditioner.
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>omega</tt> specifies the relaxation
+ * parameter in the SSOR preconditioner. The parameter
+ * <tt>min_diagonal</tt> can be used to make the application of the
+ * preconditioner also possible when some diagonal elements are zero. In a
+ * default application this would mean that we divide by zero, so by
+ * setting the parameter <tt>min_diagonal</tt> to a small nonzero value
+ * the SOR will work on a matrix that is not too far away from the one we
+ * want to treat. Finally, <tt>overlap</tt> governs the overlap of the
+ * partitions when the preconditioner runs in parallel, forming a
+ * so-called additive Schwarz preconditioner.
*/
struct AdditionalData
{
/**
- * Constructor. By default, set
- * the damping parameter to
- * one, we do not modify the
- * diagonal, and there is no
- * overlap (i.e. in parallel,
- * we run a BlockJacobi
- * preconditioner, where each
- * block is inverted
- * approximately by an SSOR.
+ * Constructor. By default, set the damping parameter to one, we do not
+ * modify the diagonal, and there is no overlap (i.e. in parallel, we
+ * run a BlockJacobi preconditioner, where each block is inverted
+ * approximately by an SSOR).
*/
AdditionalData (const double omega = 1,
const double min_diagonal = 0,
- const unsigned int overlap = 0);
+ const unsigned int overlap = 0,
+ const unsigned int n_sweeps = 1);
/**
- * This specifies the (over-)
- * relaxation parameter in the
- * SSOR preconditioner.
+ * This specifies the (over-) relaxation parameter in the SSOR
+ * preconditioner.
*/
double omega;
/**
- * This specifies the minimum
- * value the diagonal elements
- * should have. This might be
- * necessary when the SSOR
- * preconditioner is used on
- * matrices with zero diagonal
- * elements. In that case, a
- * straight-forward application
- * would not be possible since
- * we divide by the diagonal
- * element.
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the SSOR preconditioner is used on
+ * matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we divide by
+ * the diagonal element.
*/
double min_diagonal;
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
};
/**
- * Take the sparse matrix the
- * preconditioner object should
- * be built of, and additional
- * flags (damping parameter,
- * overlap in parallel
- * computations, etc.) if there
- * are any.
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, overlap in parallel
+ * computations, etc.) if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
public:
/**
- * Standardized data struct to
- * pipe additional flags to the
- * preconditioner. The
- * parameter <tt>omega</tt>
- * specifies the relaxation
- * parameter in the SOR
- * preconditioner. The
- * parameter
- * <tt>min_diagonal</tt> can be
- * used to make the application
- * of the preconditioner also
- * possible when some diagonal
- * elements are zero. In a
- * default application this
- * would mean that we divide by
- * zero, so by setting the
- * parameter
- * <tt>min_diagonal</tt> to a
- * small nonzero value the SOR
- * will work on a matrix that
- * is not too far away from the
- * one we want to
- * treat. Finally,
- * <tt>overlap</tt> governs the
- * overlap of the partitions
- * when the preconditioner runs
- * in parallel, forming a
- * so-called additive Schwarz
- * preconditioner.
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>omega</tt> specifies the relaxation
+ * parameter in the SOR preconditioner. The parameter
+ * <tt>min_diagonal</tt> can be used to make the application of the
+ * preconditioner also possible when some diagonal elements are zero. In a
+ * default application this would mean that we divide by zero, so by
+ * setting the parameter <tt>min_diagonal</tt> to a small nonzero value
+ * the SOR will work on a matrix that is not too far away from the one we
+ * want to treat. Finally, <tt>overlap</tt> governs the overlap of the
+ * partitions when the preconditioner runs in parallel, forming a
+ * so-called additive Schwarz preconditioner.
*/
struct AdditionalData
{
/**
- * Constructor. By default, set
- * the damping parameter to
- * one, we do not modify the
- * diagonal, and there is no
- * overlap (i.e. in parallel,
- * we run a BlockJacobi
- * preconditioner, where each
- * block is inverted
+ * Constructor. By default, set the damping parameter to one, we do not
+ * modify the diagonal, and there is no overlap (i.e. in parallel, we
+ * run a BlockJacobi preconditioner, where each block is inverted
* approximately by an SOR.
*/
AdditionalData (const double omega = 1,
const double min_diagonal = 0,
- const unsigned int overlap = 0);
+ const unsigned int overlap = 0,
+ const unsigned int n_sweeps = 1);
/**
- * This specifies the (over-)
- * relaxation parameter in the
- * SOR preconditioner.
+ * This specifies the (over-) relaxation parameter in the SOR
+ * preconditioner.
*/
double omega;
/**
- * This specifies the minimum
- * value the diagonal elements
- * should have. This might be
- * necessary when the SOR
- * preconditioner is used on
- * matrices with zero diagonal
- * elements. In that case, a
- * straight-forward application
- * would not be possible since
- * we divide by the diagonal
- * element.
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the SOR preconditioner is used on
+ * matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we divide by
+ * the diagonal element.
*/
double min_diagonal;
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
};
/**
- * Take the sparse matrix the
- * preconditioner object should
- * be built of, and additional
- * flags (damping parameter,
- * overlap in parallel
- * computations etc.) if there
- * are any.
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, overlap in parallel
+ * computations etc.) if there are any.
+ */
+ void initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data = AdditionalData());
+ };
+
+
+
+ /**
+ * A wrapper class for a block Jacobi preconditioner for Trilinos
+ * matrices. As opposed to PreconditionSOR where each row is treated
+ * separately, this scheme collects block of a given size and inverts a full
+ * matrix for all these rows simultaneously. Trilinos allows to select
+ * several strategies for selecting which rows form a block, including
+ * "linear" (i.e., divide the local range of the matrix in slices of the
+ * block size), "greedy" or "metis". Note that the term <em>block
+ * Jacobi</em> does not relate to possible blocks in the MPI setting, but
+ * small blocks of dense matrices extracted from the sparse matrix local to
+ * each processor.
+ *
+ * The AdditionalData data structure allows to set preconditioner
+ * options.
+ *
+ * @ingroup TrilinosWrappers
+ * @ingroup Preconditioners
+ * @author Martin Kronbichler, 2014
+ */
+ class PreconditionBlockJacobi : public PreconditionBase
+ {
+ public:
+
+ /**
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>block_size</tt> sets the size of
+ * small blocks. It is recommended to choose this parameter not too large
+ * (a few hundreds at most) since this implementation uses a dense matrix
+ * for the block. The parameter <tt>block_creation_type</tt> allows to
+ * pass the strategy for finding the blocks to Ifpack. The parameter
+ * <tt>omega</tt> specifies the relaxation parameter in the SOR
+ * preconditioner. The parameter <tt>min_diagonal</tt> can be used to make
+ * the application of the preconditioner also possible when some diagonal
+ * elements are zero. In a default application this would mean that we
+ * divide by zero, so by setting the parameter <tt>min_diagonal</tt> to a
+ * small nonzero value the SOR will work on a matrix that is not too far
+ * away from the one we want to treat. Finally, <tt>overlap</tt> governs
+ * the overlap of the partitions when the preconditioner runs in parallel,
+ * forming a so-called additive Schwarz preconditioner.
+ */
+ struct AdditionalData
+ {
+ /**
+ * Constructor. By default, use a block size of 1, use linear
+ * subdivision of the rows, set the damping parameter to one, and do not
+ * modify the diagonal.
+ */
+ AdditionalData (const unsigned int block_size = 1,
+ const std::string block_creation_type = "linear",
+ const double omega = 1,
+ const double min_diagonal = 0,
+ const unsigned int n_sweeps = 1);
+
+ /**
+ * This specifies the size of blocks.
+ */
+ unsigned int block_size;
+
+ /**
+ * Strategy for creation of blocks passed on to Ifpack block relaxation
+ * (variable 'partitioner: type') with this string as the given
+ * value. Available types in Ifpack include "linear" (i.e., divide the
+ * local range of the matrix in slices of the block size), "greedy"
+ * "metis". For a full list, see the documentation of Ifpack.
+ */
+ std::string block_creation_type;
+
+ /**
+ * This specifies the (over-) relaxation parameter in the Jacobi
+ * preconditioner.
+ */
+ double omega;
+
+ /**
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the block Jacobi preconditioner is
+ * used on matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we divide by
+ * the diagonal element.
+ */
+ double min_diagonal;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
+ };
+
+ /**
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, etc.) if there are any.
+ */
+ void initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data = AdditionalData());
+ };
+
+
+
+
+ /**
+ * A wrapper class for a block SSOR preconditioner for Trilinos matrices. As
+ * opposed to PreconditionSSOR where each row is treated separately
+ * (point-wise), this scheme collects block of a given size and inverts a
+ * full matrix for all these rows simultaneously. Trilinos allows to select
+ * several strategies for selecting which rows form a block, including
+ * "linear" (i.e., divide the local range of the matrix in slices of the
+ * block size), "greedy" or "metis".
+ *
+ * The AdditionalData data structure allows to set preconditioner
+ * options.
+ *
+ * Note that a parallel application of this preconditioner is actually a
+ * block-Jacobi preconditioner with (outer) block size equal to the local
+ * matrix size. Spoken more technically, this parallel operation is an <a
+ * href="http://en.wikipedia.org/wiki/Additive_Schwarz_method">additive
+ * Schwarz method</a> with a block SSOR <em>approximate solve</em> as inner
+ * solver, based on the outer parallel partitioning.
+ *
+ * @ingroup TrilinosWrappers
+ * @ingroup Preconditioners
+ * @author Martin Kronbichler, 2014
+ */
+ class PreconditionBlockSSOR : public PreconditionBase
+ {
+ public:
+
+ /**
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>block_size</tt> sets the size of
+ * small blocks. It is recommended to choose this parameter not too large
+ * (a few hundreds at most) since this implementation uses a dense matrix
+ * for the block. The parameter <tt>block_creation_type</tt> allows to
+ * pass the strategy for finding the blocks to Ifpack. The parameter
+ * <tt>omega</tt> specifies the relaxation parameter in the SSOR
+ * preconditioner. The parameter <tt>min_diagonal</tt> can be used to make
+ * the application of the preconditioner also possible when some diagonal
+ * elements are zero. In a default application this would mean that we
+ * divide by zero, so by setting the parameter <tt>min_diagonal</tt> to a
+ * small nonzero value the SOR will work on a matrix that is not too far
+ * away from the one we want to treat. Finally, <tt>overlap</tt> governs
+ * the overlap of the partitions when the preconditioner runs in parallel,
+ * forming a so-called additive Schwarz preconditioner.
+ */
+ struct AdditionalData
+ {
+ /**
+ * Constructor. By default, use a block size of 1, use linear
+ * subdivision of the rows, set the damping parameter to one, we do not
+ * modify the diagonal, and there is no overlap (i.e. in parallel, we
+ * run a BlockJacobi preconditioner, where each block is inverted
+ * approximately by a block SOR).
+ */
+ AdditionalData (const unsigned int block_size = 1,
+ const std::string block_creation_type = "linear",
+ const double omega = 1,
+ const double min_diagonal = 0,
+ const unsigned int overlap = 0,
+ const unsigned int n_sweeps = 1);
+
+ /**
+ * This specifies the size of blocks.
+ */
+ unsigned int block_size;
+
+ /**
+ * Strategy for creation of blocks passed on to Ifpack block relaxation
+ * (variable 'partitioner: type') with this string as the given
+ * value. Available types in Ifpack include "linear" (i.e., divide the
+ * local range of the matrix in slices of the block size), "greedy"
+ * "metis". For a full list, see the documentation of Ifpack.
+ */
+ std::string block_creation_type;
+
+ /**
+ * This specifies the (over-) relaxation parameter in the SOR
+ * preconditioner.
+ */
+ double omega;
+
+ /**
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the SSOR preconditioner is used on
+ * matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we divide by
+ * the diagonal element.
+ */
+ double min_diagonal;
+
+ /**
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
+ */
+ unsigned int overlap;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
+ };
+
+ /**
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, overlap in parallel
+ * computations, etc.) if there are any.
+ */
+ void initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data = AdditionalData());
+ };
+
+
+
+
+ /**
+ * A wrapper class for a block SOR preconditioner for Trilinos matrices. As
+ * opposed to PreconditionSOR where each row is treated separately, this
+ * scheme collects block of a given size and inverts a full matrix for all
+ * these rows simultaneously. Trilinos allows to select several strategies
+ * for selecting which rows form a block, including "linear" (i.e., divide
+ * the local range of the matrix in slices of the block size), "greedy" or
+ * "metis".
+ *
+ * The AdditionalData data structure allows to set preconditioner
+ * options.
+ *
+ * Note that a parallel application of this preconditioner is actually a
+ * block-Jacobi preconditioner with (outer) block size equal to the local
+ * matrix size. Spoken more technically, this parallel operation is an <a
+ * href="http://en.wikipedia.org/wiki/Additive_Schwarz_method">additive
+ * Schwarz method</a> with a block SOR <em>approximate solve</em> as inner
+ * solver, based on the outer parallel partitioning.
+ *
+ * @ingroup TrilinosWrappers
+ * @ingroup Preconditioners
+ * @author Martin Kronbichler, 2014
+ */
+ class PreconditionBlockSOR : public PreconditionBase
+ {
+ public:
+
+ /**
+ * Standardized data struct to pipe additional flags to the
+ * preconditioner. The parameter <tt>block_size</tt> sets the size of
+ * small blocks. It is recommended to choose this parameter not too large
+ * (a few hundreds at most) since this implementation uses a dense matrix
+ * for the block. The parameter <tt>block_creation_type</tt> allows to
+ * pass the strategy for finding the blocks to Ifpack. The parameter
+ * <tt>omega</tt> specifies the relaxation parameter in the SOR
+ * preconditioner. The parameter <tt>min_diagonal</tt> can be used to make
+ * the application of the preconditioner also possible when some diagonal
+ * elements are zero. In a default application this would mean that we
+ * divide by zero, so by setting the parameter <tt>min_diagonal</tt> to a
+ * small nonzero value the SOR will work on a matrix that is not too far
+ * away from the one we want to treat. Finally, <tt>overlap</tt> governs
+ * the overlap of the partitions when the preconditioner runs in parallel,
+ * forming a so-called additive Schwarz preconditioner.
+ */
+ struct AdditionalData
+ {
+ /**
+ * Constructor. By default, use a block size of 1, use linear
+ * subdivision of the rows, set the damping parameter to one, we do not
+ * modify the diagonal, and there is no overlap (i.e. in parallel, we
+ * run a BlockJacobi preconditioner, where each block is inverted
+ * approximately by a block SOR).
+ */
+ AdditionalData (const unsigned int block_size = 1,
+ const std::string block_creation_type = "linear",
+ const double omega = 1,
+ const double min_diagonal = 0,
+ const unsigned int overlap = 0,
+ const unsigned int n_sweeps = 1);
+
+ /**
+ * This specifies the size of blocks.
+ */
+ unsigned int block_size;
+
+ /**
+ * Strategy for creation of blocks passed on to Ifpack block relaxation
+ * (variable 'partitioner: type') with this string as the given
+ * value. Available types in Ifpack include "linear" (i.e., divide the
+ * local range of the matrix in slices of the block size), "greedy"
+ * "metis". For a full list, see the documentation of Ifpack.
+ */
+ std::string block_creation_type;
+
+ /**
+ * This specifies the (over-) relaxation parameter in the SOR
+ * preconditioner.
+ */
+ double omega;
+
+ /**
+ * This specifies the minimum value the diagonal elements should
+ * have. This might be necessary when the SOR preconditioner is used on
+ * matrices with zero diagonal elements. In that case, a
+ * straight-forward application would not be possible since we divide by
+ * the diagonal element.
+ */
+ double min_diagonal;
+
+ /**
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
+ */
+ unsigned int overlap;
+
+ /**
+ * Sets how many times the given operation should be applied during the
+ * vmult() operation.
+ */
+ unsigned int n_sweeps;
+ };
+
+ /**
+ * Take the sparse matrix the preconditioner object should be built of,
+ * and additional flags (damping parameter, overlap in parallel
+ * computations etc.) if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
{
public:
/**
- * Standardized data struct to
- * pipe additional parameters
- * to the preconditioner. The
- * Trilinos IC decomposition
- * allows for some fill-in, so
- * it actually is a threshold
- * incomplete Cholesky
- * factorization. The amount of
- * fill-in, and hence, the
- * amount of memory used by
- * this preconditioner, is
- * controlled by the parameter
- * <tt>ic_fill</tt>, which
- * specifies this as a
- * double. When forming the
- * preconditioner, for certain
- * problems bad conditioning
- * (or just bad luck) can cause
- * the preconditioner to be
- * very poorly
- * conditioned. Hence it can
- * help to add diagonal
- * perturbations to the
- * original matrix and form the
- * preconditioner for this
- * slightly better
- * matrix. <tt>ic_atol</tt> is
- * an absolute perturbation
- * that is added to the
- * diagonal before forming the
- * prec, and <tt>ic_rtol</tt>
- * is a scaling factor $rtol
- * \geq 1$. The last parameter
- * specifies the overlap of the
- * partitions when the
- * preconditioner runs in
- * parallel.
+ * Standardized data struct to pipe additional parameters to the
+ * preconditioner. The Trilinos IC decomposition allows for some fill-in,
+ * so it actually is a threshold incomplete Cholesky factorization. The
+ * amount of fill-in, and hence, the amount of memory used by this
+ * preconditioner, is controlled by the parameter <tt>ic_fill</tt>, which
+ * specifies this as a double. When forming the preconditioner, for
+ * certain problems bad conditioning (or just bad luck) can cause the
+ * preconditioner to be very poorly conditioned. Hence it can help to add
+ * diagonal perturbations to the original matrix and form the
+ * preconditioner for this slightly better matrix. <tt>ic_atol</tt> is an
+ * absolute perturbation that is added to the diagonal before forming the
+ * prec, and <tt>ic_rtol</tt> is a scaling factor $rtol \geq 1$. The last
+ * parameter specifies the overlap of the partitions when the
+ * preconditioner runs in parallel.
*/
struct AdditionalData
{
/**
- * Constructor. By default, set
- * the drop tolerance to 0, the
- * level of extra fill-ins is
- * set to be zero (just use the
- * matrix structure, do not
- * generate any additional
- * fill-in), the tolerance
- * level are 0 and 1,
- * respectively, and the
- * overlap in case of a
- * parallel execution is
- * zero. This overlap in a
- * block-application of the IC
- * in the parallel case makes
- * the preconditioner a
- * so-called additive Schwarz
+ * Constructor. By default, set the drop tolerance to 0, the level of
+ * extra fill-ins is set to be zero (just use the matrix structure, do
+ * not generate any additional fill-in), the tolerance level are 0 and
+ * 1, respectively, and the overlap in case of a parallel execution is
+ * zero. This overlap in a block-application of the IC in the parallel
+ * case makes the preconditioner a so-called additive Schwarz
* preconditioner.
*/
AdditionalData (const unsigned int ic_fill = 0,
const unsigned int overlap = 0);
/**
- * This specifies the amount of
- * additional fill-in elements
- * besides the sparse matrix
- * structure. When
- * <tt>ic_fill</tt> is large,
- * this means that many
- * fill-ins will be added, so
- * that the IC preconditioner
- * comes closer to a direct
- * sparse Cholesky
- * decomposition. Note,
- * however, that this will
- * drastically increase the
- * memory requirement,
- * especially when the
- * preconditioner is used in
- * 3D.
+ * This specifies the amount of additional fill-in elements besides the
+ * sparse matrix structure. When <tt>ic_fill</tt> is large, this means
+ * that many fill-ins will be added, so that the IC preconditioner comes
+ * closer to a direct sparse Cholesky decomposition. Note, however, that
+ * this will drastically increase the memory requirement, especially
+ * when the preconditioner is used in 3D.
*/
unsigned int ic_fill;
/**
- * This specifies the amount of
- * an absolute perturbation
- * that will be added to the
- * diagonal of the matrix,
- * which sometimes can help to
- * get better preconditioners.
+ * This specifies the amount of an absolute perturbation that will be
+ * added to the diagonal of the matrix, which sometimes can help to get
+ * better preconditioners.
*/
double ic_atol;
/**
- * This specifies the factor by
- * which the diagonal of the
- * matrix will be scaled, which
- * sometimes can help to get
- * better preconditioners.
+ * This specifies the factor by which the diagonal of the matrix will be
+ * scaled, which sometimes can help to get better preconditioners.
*/
double ic_rtol;
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
};
/**
- * Initialize function. Takes
- * the matrix the
- * preconditioner should be
- * computed of, and additional
- * flags if there are any.
+ * Initialize function. Takes the matrix the preconditioner should be
+ * computed of, and additional flags if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
{
public:
/**
- * Standardized data struct to
- * pipe additional parameters
- * to the preconditioner. The
- * Trilinos ILU decomposition
- * allows for some fill-in, so
- * it actually is a threshold
- * incomplete LU
- * factorization. The amount of
- * fill-in, and hence, the
- * amount of memory used by
- * this preconditioner, is
- * controlled by the parameter
- * <tt>ilu_fill</tt>, which
- * specifies this as a
- * double. When forming the
- * preconditioner, for certain
- * problems bad conditioning
- * (or just bad luck) can cause
- * the preconditioner to be
- * very poorly
- * conditioned. Hence it can
- * help to add diagonal
- * perturbations to the
- * original matrix and form the
- * preconditioner for this
- * slightly better
- * matrix. <tt>ilu_atol</tt> is
- * an absolute perturbation
- * that is added to the
- * diagonal before forming the
- * prec, and <tt>ilu_rtol</tt>
- * is a scaling factor $rtol
- * \geq 1$. The last parameter
- * specifies the overlap of the
- * partitions when the
- * preconditioner runs in
- * parallel.
+ * Standardized data struct to pipe additional parameters to the
+ * preconditioner. The Trilinos ILU decomposition allows for some fill-in,
+ * so it actually is a threshold incomplete LU factorization. The amount
+ * of fill-in, and hence, the amount of memory used by this
+ * preconditioner, is controlled by the parameter <tt>ilu_fill</tt>, which
+ * specifies this as a double. When forming the preconditioner, for
+ * certain problems bad conditioning (or just bad luck) can cause the
+ * preconditioner to be very poorly conditioned. Hence it can help to add
+ * diagonal perturbations to the original matrix and form the
+ * preconditioner for this slightly better matrix. <tt>ilu_atol</tt> is an
+ * absolute perturbation that is added to the diagonal before forming the
+ * prec, and <tt>ilu_rtol</tt> is a scaling factor $rtol \geq 1$. The last
+ * parameter specifies the overlap of the partitions when the
+ * preconditioner runs in parallel.
*/
struct AdditionalData
{
/**
- * Constructor. By default, the
- * level of extra fill-ins is
- * set to be zero (just use the
- * matrix structure, do not
- * generate any additional
- * fill-in), the tolerance
- * level are 0 and 1,
- * respectively, and the
- * overlap in case of a
- * parallel execution is
- * zero. This overlap in a
- * block-application of the ILU
- * in the parallel case makes
- * the preconditioner a
- * so-called additive Schwarz
- * preconditioner.
+ * Constructor. By default, the level of extra fill-ins is set to be
+ * zero (just use the matrix structure, do not generate any additional
+ * fill-in), the tolerance level are 0 and 1, respectively, and the
+ * overlap in case of a parallel execution is zero. This overlap in a
+ * block-application of the ILU in the parallel case makes the
+ * preconditioner a so-called additive Schwarz preconditioner.
*/
AdditionalData (const unsigned int ilu_fill = 0,
const double ilu_atol = 0.,
const unsigned int overlap = 0);
/**
- * This specifies the amount of
- * additional fill-in elements
- * besides the sparse matrix
- * structure. When
- * <tt>ilu_fill</tt> is large,
- * this means that many
- * fill-ins will be added, so
- * that the ILU preconditioner
- * comes closer to a (direct)
- * sparse LU
- * decomposition. Note,
- * however, that this will
- * drastically increase the
- * memory requirement,
- * especially when the
- * preconditioner is used in
- * 3D.
+ * This specifies the amount of additional fill-in elements besides the
+ * sparse matrix structure. When <tt>ilu_fill</tt> is large, this means
+ * that many fill-ins will be added, so that the ILU preconditioner
+ * comes closer to a (direct) sparse LU decomposition. Note, however,
+ * that this will drastically increase the memory requirement,
+ * especially when the preconditioner is used in 3D.
*/
unsigned int ilu_fill;
/**
- * This specifies the amount of
- * an absolute perturbation
- * that will be added to the
- * diagonal of the matrix,
- * which sometimes can help to
- * get better preconditioners.
+ * This specifies the amount of an absolute perturbation that will be
+ * added to the diagonal of the matrix, which sometimes can help to get
+ * better preconditioners.
*/
double ilu_atol;
/**
- * This specifies the factor by
- * which the diagonal of the
- * matrix will be scaled, which
- * sometimes can help to get
- * better preconditioners.
+ * This specifies the factor by which the diagonal of the matrix will be
+ * scaled, which sometimes can help to get better preconditioners.
*/
double ilu_rtol;
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
};
/**
- * Initialize function. Takes
- * the matrix which is used to
- * form the preconditioner, and
- * additional flags if there
- * are any.
+ * Initialize function. Takes the matrix which is used to form the
+ * preconditioner, and additional flags if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
{
public:
/**
- * Standardized data struct to pipe
- * additional parameters to the
- * preconditioner. The Trilinos ILU-T
- * decomposition allows for some
- * fill-in, so it actually is a
- * threshold incomplete LU
- * factorization. The amount of
- * fill-in, and hence, the amount of
- * memory used by this
- * preconditioner, is controlled by
- * the parameters <tt>ilut_drop</tt>
- * and <tt>ilut_fill</tt>, which
- * specifies a threshold about which
- * values should form the incomplete
- * factorization and the level of
- * additional fill-in. When forming
- * the preconditioner, for certain
- * problems bad conditioning (or just
- * bad luck) can cause the
- * preconditioner to be very poorly
- * conditioned. Hence it can help to
- * add diagonal perturbations to the
- * original matrix and form the
- * preconditioner for this slightly
- * better matrix. <tt>ilut_atol</tt>
- * is an absolute perturbation that
- * is added to the diagonal before
- * forming the prec, and
- * <tt>ilu_rtol</tt> is a scaling
- * factor $rtol \geq 1$. The last
- * parameter specifies the overlap of
- * the partitions when the
- * preconditioner runs in parallel.
+ * Standardized data struct to pipe additional parameters to the
+ * preconditioner. The Trilinos ILU-T decomposition allows for some
+ * fill-in, so it actually is a threshold incomplete LU factorization. The
+ * amount of fill-in, and hence, the amount of memory used by this
+ * preconditioner, is controlled by the parameters <tt>ilut_drop</tt> and
+ * <tt>ilut_fill</tt>, which specifies a threshold about which values
+ * should form the incomplete factorization and the level of additional
+ * fill-in. When forming the preconditioner, for certain problems bad
+ * conditioning (or just bad luck) can cause the preconditioner to be very
+ * poorly conditioned. Hence it can help to add diagonal perturbations to
+ * the original matrix and form the preconditioner for this slightly
+ * better matrix. <tt>ilut_atol</tt> is an absolute perturbation that is
+ * added to the diagonal before forming the prec, and <tt>ilu_rtol</tt> is
+ * a scaling factor $rtol \geq 1$. The last parameter specifies the
+ * overlap of the partitions when the preconditioner runs in parallel.
*/
struct AdditionalData
{
/**
- * Constructor. By default, no
- * element will be dropped, the level
- * of extra fill-ins is set to be
- * zero (just use the matrix
- * structure, do not generate any
- * additional fill-in except the one
- * that results from non-dropping
- * large elements), the tolerance
- * level are 0 and 1, respectively,
- * and the overlap in case of a
- * parallel execution is zero. This
- * overlap in a block-application of
- * the ILU in the parallel case makes
- * the preconditioner a so-called
- * additive Schwarz preconditioner.
+ * Constructor. By default, no element will be dropped, the level of
+ * extra fill-ins is set to be zero (just use the matrix structure, do
+ * not generate any additional fill-in except the one that results from
+ * non-dropping large elements), the tolerance level are 0 and 1,
+ * respectively, and the overlap in case of a parallel execution is
+ * zero. This overlap in a block-application of the ILU in the parallel
+ * case makes the preconditioner a so-called additive Schwarz
+ * preconditioner.
*/
AdditionalData (const double ilut_drop = 0.,
const unsigned int ilut_fill = 0,
const unsigned int overlap = 0);
/**
- * This specifies the relative size
- * of elements which should be
- * dropped when forming an incomplete
- * LU decomposition with threshold.
+ * This specifies the relative size of elements which should be dropped
+ * when forming an incomplete LU decomposition with threshold.
*/
double ilut_drop;
/**
- * This specifies the amount of
- * additional fill-in elements
- * besides the sparse matrix
- * structure. When
- * <tt>ilu_fill</tt> is large,
- * this means that many
- * fill-ins will be added, so
- * that the ILU preconditioner
- * comes closer to a (direct)
- * sparse LU
- * decomposition. Note,
- * however, that this will
- * drastically increase the
- * memory requirement,
- * especially when the
- * preconditioner is used in
- * 3D.
+ * This specifies the amount of additional fill-in elements besides the
+ * sparse matrix structure. When <tt>ilu_fill</tt> is large, this means
+ * that many fill-ins will be added, so that the ILU preconditioner
+ * comes closer to a (direct) sparse LU decomposition. Note, however,
+ * that this will drastically increase the memory requirement,
+ * especially when the preconditioner is used in 3D.
*/
unsigned int ilut_fill;
/**
- * This specifies the amount of
- * an absolute perturbation
- * that will be added to the
- * diagonal of the matrix,
- * which sometimes can help to
- * get better preconditioners.
+ * This specifies the amount of an absolute perturbation that will be
+ * added to the diagonal of the matrix, which sometimes can help to get
+ * better preconditioners.
*/
double ilut_atol;
/**
- * This specifies the factor by
- * which the diagonal of the
- * matrix will be scaled, which
- * sometimes can help to get
- * better preconditioners.
+ * This specifies the factor by which the diagonal of the matrix will be
+ * scaled, which sometimes can help to get better preconditioners.
*/
double ilut_rtol;
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
};
/**
- * Initialize function. Takes
- * the matrix which is used to
- * form the preconditioner, and
- * additional flags if there
- * are any.
+ * Initialize function. Takes the matrix which is used to form the
+ * preconditioner, and additional flags if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
{
public:
/**
- * Standardized data struct to
- * pipe additional parameters
- * to the preconditioner.
+ * Standardized data struct to pipe additional parameters to the
+ * preconditioner.
*/
struct AdditionalData
{
/**
- * This determines how large
- * the overlap of the local
- * matrix portions on each
- * processor in a parallel
- * application should be.
+ * This determines how large the overlap of the local matrix portions on
+ * each processor in a parallel application should be.
*/
unsigned int overlap;
};
/**
- * Initialize function. Takes
- * the matrix which is used to
- * form the preconditioner, and
- * additional flags if there
- * are any.
+ * Initialize function. Takes the matrix which is used to form the
+ * preconditioner, and additional flags if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
{
public:
/**
- * Standardized data struct to
- * pipe additional parameters
- * to the preconditioner.
+ * Standardized data struct to pipe additional parameters to the
+ * preconditioner.
*/
struct AdditionalData
{
const bool nonzero_starting = false);
/**
- * This determines the degree of the
- * Chebyshev polynomial. The degree
- * of the polynomial gives the number
- * of matrix-vector products to be
- * performed for one application of
- * the vmult() operation.
+ * This determines the degree of the Chebyshev polynomial. The degree of
+ * the polynomial gives the number of matrix-vector products to be
+ * performed for one application of the vmult() operation.
*/
unsigned int degree;
/**
- * This sets the maximum eigenvalue
- * of the matrix, which needs to be
- * set properly for appropriate
- * performance of the Chebyshev
- * preconditioner.
+ * This sets the maximum eigenvalue of the matrix, which needs to be set
+ * properly for appropriate performance of the Chebyshev preconditioner.
*/
double max_eigenvalue;
/**
- * This sets the ratio between the
- * maximum and the minimum
- * eigenvalue.
+ * This sets the ratio between the maximum and the minimum eigenvalue.
*/
double eigenvalue_ratio;
/**
- * This sets the minimum eigenvalue,
- * which is an optional parameter
- * only used internally for checking
- * whether we use an identity matrix.
+ * This sets the minimum eigenvalue, which is an optional parameter only
+ * used internally for checking whether we use an identity matrix.
*/
double min_eigenvalue;
/**
- * This sets a threshold below which
- * the diagonal element will not be
- * inverted in the Chebyshev
- * algorithm.
+ * This sets a threshold below which the diagonal element will not be
+ * inverted in the Chebyshev algorithm.
*/
double min_diagonal;
/**
- * When this flag is set to
- * <tt>true</tt>, it enables the
- * method <tt>vmult(dst, src)</tt> to
- * use non-zero data in the vector
- * <tt>dst</tt>, appending to it the
- * Chebyshev corrections. This can be
- * useful in some situations
- * (e.g. when used for high-frequency
- * error smoothing), but not the way
- * the solver classes expect a
- * preconditioner to work (where one
- * ignores the content in
- * <tt>dst</tt> for the
- * preconditioner application). The
- * user should really know what she
- * is doing when touching this flag.
+ * When this flag is set to <tt>true</tt>, it enables the method
+ * <tt>vmult(dst, src)</tt> to use non-zero data in the vector
+ * <tt>dst</tt>, appending to it the Chebyshev corrections. This can be
+ * useful in some situations (e.g. when used for high-frequency error
+ * smoothing), but not the way the solver classes expect a
+ * preconditioner to work (where one ignores the content in <tt>dst</tt>
+ * for the preconditioner application). The user should really know what
+ * she is doing when touching this flag.
*/
bool nonzero_starting;
};
/**
- * Initialize function. Takes
- * the matrix which is used to
- * form the preconditioner, and
- * additional flags if there
- * are any.
+ * Initialize function. Takes the matrix which is used to form the
+ * preconditioner, and additional flags if there are any.
*/
void initialize (const SparseMatrix &matrix,
const AdditionalData &additional_data = AdditionalData());
const unsigned int n_cycles = 1,
const bool w_cyle = false,
const double aggregation_threshold = 1e-4,
- const std::vector<std::vector<bool> > &constant_modes = std::vector<std::vector<bool> > (1),
+ const std::vector<std::vector<bool> > &constant_modes = std::vector<std::vector<bool> > (0),
const unsigned int smoother_sweeps = 2,
const unsigned int smoother_overlap = 0,
const bool output_details = false,
/**
* Determines which smoother to use for the AMG cycle. Possibilities
* for smoother_type are the following:
- * "Aztec"
- * "IFPACK"
- * "Jacobi"
- * "ML symmetric Gauss-Seidel"
- * "symmetric Gauss-Seidel"
- * "ML Gauss-Seidel"
- * "Gauss-Seidel"
- * "block Gauss-Seidel"
- * "symmetric block Gauss-Seidel"
- * "Chebyshev"
- * "MLS"
- * "Hiptmair"
- * "Amesos-KLU"
- * "Amesos-Superlu"
- * "Amesos-UMFPACK"
- * "Amesos-Superludist"
- * "Amesos-MUMPS"
- * "user-defined"
- * "SuperLU"
- * "IFPACK-Chebyshev"
- * "self"
- * "do-nothing"
- * "IC"
- * "ICT"
- * "ILU"
- * "ILUT"
- * "Block Chebyshev"
- * "IFPACK-Block Chebyshev"
+ * <ul>
+ * <li> "Aztec" </li>
+ * <li> "IFPACK" </li>
+ * <li> "Jacobi" </li>
+ * <li> "ML symmetric Gauss-Seidel" </li>
+ * <li> "symmetric Gauss-Seidel" </li>
+ * <li> "ML Gauss-Seidel" </li>
+ * <li> "Gauss-Seidel" </li>
+ * <li> "block Gauss-Seidel" </li>
+ * <li> "symmetric block Gauss-Seidel" </li>
+ * <li> "Chebyshev" </li>
+ * <li> "MLS" </li>
+ * <li> "Hiptmair" </li>
+ * <li> "Amesos-KLU" </li>
+ * <li> "Amesos-Superlu" </li>
+ * <li> "Amesos-UMFPACK" </li>
+ * <li> "Amesos-Superludist" </li>
+ * <li> "Amesos-MUMPS" </li>
+ * <li> "user-defined" </li>
+ * <li> "SuperLU" </li>
+ * <li> "IFPACK-Chebyshev" </li>
+ * <li> "self" </li>
+ * <li> "do-nothing" </li>
+ * <li> "IC" </li>
+ * <li> "ICT" </li>
+ * <li> "ILU" </li>
+ * <li> "ILUT" </li>
+ * <li> "Block Chebyshev" </li>
+ * <li> "IFPACK-Block Chebyshev" </li>
+ * </ul>
*/
const char* smoother_type;
const char* coarse_type;
};
+ /**
+ * Destructor.
+ */
+ ~PreconditionAMG();
+
/**
* Let Trilinos compute a multilevel hierarchy for the solution of a
}
- // For the implementation of
- // the <code>vmult</code>
- // function with deal.II data
- // structures we note that
- // invoking a call of the
- // Trilinos preconditioner
- // requires us to use Epetra
- // vectors as well. We do this
- // by providing a view, i.e.,
- // feed Trilinos with a
- // pointer to the data, so we
- // avoid copying the content
- // of the vectors during the
- // iteration (this function is
- // only useful when used in
- // serial anyway). In the
- // declaration of the right
- // hand side, we need to cast
- // the source vector (that is
- // <code>const</code> in all
- // deal.II calls) to
- // non-constant value, as this
- // is the way Trilinos wants
- // to have them.
+ // For the implementation of the <code>vmult</code> function with deal.II
+ // data structures we note that invoking a call of the Trilinos
+ // preconditioner requires us to use Epetra vectors as well. We do this by
+ // providing a view, i.e., feed Trilinos with a pointer to the data, so we
+ // avoid copying the content of the vectors during the iteration (this
+ // function is only useful when used in serial anyway). In the declaration
+ // of the right hand side, we need to cast the source vector (that is
+ // <code>const</code> in all deal.II calls) to non-constant value, as this
+ // is the way Trilinos wants to have them.
inline
void PreconditionBase::vmult (dealii::Vector<double> &dst,
const dealii::Vector<double> &src) const
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
# include <deal.II/lac/exceptions.h>
# include <deal.II/lac/solver_control.h>
# include <deal.II/lac/vector.h>
+# include <deal.II/lac/parallel_vector.h>
# include <Epetra_LinearProblem.h>
# include <AztecOO.h>
public:
/**
- * Enumeration object that is
- * set in the constructor of
- * the derived classes and
- * tells Trilinos which solver
- * to use. This option can also
- * be set in the user program,
- * so one might use this base
- * class instead of one of the
- * specialized derived classes
- * when the solver should be
- * set at runtime. Currently
- * enabled options are:
+ * Enumeration object that is set in the constructor of the derived
+ * classes and tells Trilinos which solver to use. This option can also be
+ * set in the user program, so one might use this base class instead of
+ * one of the specialized derived classes when the solver should be set at
+ * runtime. Currently enabled options are:
*/
enum SolverName {cg, cgs, gmres, bicgstab, tfqmr} solver_name;
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format and puts
- * the restart parameter in case the
- * derived class is GMRES.
+ * Sets the additional data field to the desired output format and puts
+ * the restart parameter in case the derived class is GMRES.
*
- * TODO: Find a better way for
- * setting the GMRES restart
- * parameter since it is quite
- * inelegant to set a specific option
- * of one solver in the base class
- * for all solvers.
+ * TODO: Find a better way for setting the GMRES restart parameter since
+ * it is quite inelegant to set a specific option of one solver in the
+ * base class for all solvers.
*/
AdditionalData (const bool output_solver_details = false,
const unsigned int gmres_restart_parameter = 30);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
const bool output_solver_details;
/**
- * Restart parameter for GMRES
- * solver.
+ * Restart parameter for GMRES solver.
*/
const unsigned int gmres_restart_parameter;
};
/**
- * Constructor. Takes the
- * solver control object and
- * creates the solver.
+ * Constructor. Takes the solver control object and creates the solver.
*/
SolverBase (SolverControl &cn);
/**
- * Second constructor. This
- * constructor takes an enum
- * object that specifies the
- * solver name and sets the
- * appropriate Krylov
- * method.
+ * Second constructor. This constructor takes an enum object that
+ * specifies the solver name and sets the appropriate Krylov method.
*/
SolverBase (const enum SolverName solver_name,
SolverControl &cn);
virtual ~SolverBase ();
/**
- * Solve the linear system
- * <tt>Ax=b</tt>. Depending on
- * the information provided by
- * derived classes and the
- * object passed as a
- * preconditioner, one of the
- * linear solvers and
- * preconditioners of Trilinos
- * is chosen.
+ * Solve the linear system <tt>Ax=b</tt>. Depending on the information
+ * provided by derived classes and the object passed as a preconditioner,
+ * one of the linear solvers and preconditioners of Trilinos is chosen.
*/
void
solve (const SparseMatrix &A,
const PreconditionBase &preconditioner);
/**
- * Solve the linear system
- * <tt>Ax=b</tt> where <tt>A</tt>
- * is an operator. This function
- * can be used for matrix free
- * computation. Depending on
- * the information provided by
- * derived classes and the
- * object passed as a
- * preconditioner, one of the
- * linear solvers and
- * preconditioners of Trilinos
- * is chosen.
+ * Solve the linear system <tt>Ax=b</tt> where <tt>A</tt> is an
+ * operator. This function can be used for matrix free
+ * computation. Depending on the information provided by derived classes
+ * and the object passed as a preconditioner, one of the linear solvers
+ * and preconditioners of Trilinos is chosen.
*/
void
solve (Epetra_Operator &A,
const PreconditionBase &preconditioner);
/**
- * Solve the linear system
- * <tt>Ax=b</tt>. Depending on the
- * information provided by derived
- * classes and the object passed as a
- * preconditioner, one of the linear
- * solvers and preconditioners of
- * Trilinos is chosen. This class
- * works with matrices according to
- * the TrilinosWrappers format, but
- * can take deal.II vectors as
- * argument. Since deal.II are serial
- * vectors (not distributed), this
- * function does only what you expect
- * in case the matrix is locally
- * owned. Otherwise, an exception
- * will be thrown.
+ * Solve the linear system <tt>Ax=b</tt>. Depending on the information
+ * provided by derived classes and the object passed as a preconditioner,
+ * one of the linear solvers and preconditioners of Trilinos is
+ * chosen. This class works with matrices according to the
+ * TrilinosWrappers format, but can take deal.II vectors as
+ * argument. Since deal.II are serial vectors (not distributed), this
+ * function does only what you expect in case the matrix is locally
+ * owned. Otherwise, an exception will be thrown.
*/
void
solve (const SparseMatrix &A,
const PreconditionBase &preconditioner);
/**
- * Solve the linear system
- * <tt>Ax=b</tt> where <tt>A</tt>
- * is an operator. This function can
- * be used for matric free. Depending on the
- * information provided by derived
- * classes and the object passed as a
- * preconditioner, one of the linear
- * solvers and preconditioners of
- * Trilinos is chosen. This class
- * works with matrices according to
- * the TrilinosWrappers format, but
- * can take deal.II vectors as
- * argument. Since deal.II are serial
- * vectors (not distributed), this
- * function does only what you expect
- * in case the matrix is locally
- * owned. Otherwise, an exception
- * will be thrown.
+ * Solve the linear system <tt>Ax=b</tt> where <tt>A</tt> is an
+ * operator. This function can be used for matrix free
+ * computations. Depending on the information provided by derived classes
+ * and the object passed as a preconditioner, one of the linear solvers
+ * and preconditioners of Trilinos is chosen. This class works with
+ * matrices according to the TrilinosWrappers format, but can take deal.II
+ * vectors as argument. Since deal.II are serial vectors (not
+ * distributed), this function does only what you expect in case the
+ * matrix is locally owned. Otherwise, an exception will be thrown.
*/
void
solve (Epetra_Operator &A,
const PreconditionBase &preconditioner);
/**
- * Access to object that controls
- * convergence.
+ * Solve the linear system <tt>Ax=b</tt> for deal.II's parallel
+ * distributed vectors. Depending on the information provided by derived
+ * classes and the object passed as a preconditioner, one of the linear
+ * solvers and preconditioners of Trilinos is chosen.
+ */
+ void
+ solve (const SparseMatrix &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b,
+ const PreconditionBase &preconditioner);
+
+ /**
+ * Solve the linear system <tt>Ax=b</tt> where <tt>A</tt> is an
+ * operator. This function can be used for matrix free
+ * computation. Depending on the information provided by derived classes
+ * and the object passed as a preconditioner, one of the linear solvers
+ * and preconditioners of Trilinos is chosen.
+ */
+ void
+ solve (Epetra_Operator &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b,
+ const PreconditionBase &preconditioner);
+
+
+ /**
+ * Access to object that controls convergence.
*/
SolverControl &control() const;
protected:
/**
- * Reference to the object that
- * controls convergence of the
- * iterative solver. In fact,
- * for these Trilinos wrappers,
- * Trilinos does so itself, but
- * we copy the data from this
- * object before starting the
- * solution process, and copy
- * the data back into it
- * afterwards.
+ * Reference to the object that controls convergence of the iterative
+ * solver. In fact, for these Trilinos wrappers, Trilinos does so itself,
+ * but we copy the data from this object before starting the solution
+ * process, and copy the data back into it afterwards.
*/
SolverControl &solver_control;
* The solve function is used to set properly the Epetra_LinearProblem,
* once it is done this function solves the linear problem.
*/
- void execute_solve(const PreconditionBase &preconditioner);
+ void do_solve(const PreconditionBase &preconditioner);
/**
- * A structure that collects
- * the Trilinos sparse matrix,
- * the right hand side vector
- * and the solution vector,
- * which is passed down to the
+ * A structure that collects the Trilinos sparse matrix, the right hand
+ * side vector and the solution vector, which is passed down to the
* Trilinos solver.
*/
std_cxx1x::shared_ptr<Epetra_LinearProblem> linear_problem;
/**
- * A structure that contains
- * the Trilinos solver and
- * preconditioner objects.
+ * A structure that contains the Trilinos solver and preconditioner
+ * objects.
*/
AztecOO solver;
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format.
+ * Sets the additional data field to the desired output format.
*/
AdditionalData (const bool output_solver_details = false);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
};
/**
- * Constructor. In contrast to
- * deal.II's own solvers, there is no
- * need to give a vector memory
- * object.
+ * Constructor. In contrast to deal.II's own solvers, there is no need to
+ * give a vector memory object.
*
- * The last argument takes a structure
- * with additional, solver dependent
+ * The last argument takes a structure with additional, solver dependent
* flags for tuning.
*/
SolverCG (SolverControl &cn,
protected:
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
};
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format.
+ * Sets the additional data field to the desired output format.
*/
AdditionalData (const bool output_solver_details = false);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
};
/**
- * Constructor. In contrast to
- * deal.II's own solvers, there is no
- * need to give a vector memory
- * object.
+ * Constructor. In contrast to deal.II's own solvers, there is no need to
+ * give a vector memory object.
*
- * The last argument takes a structure
- * with additional, solver dependent
+ * The last argument takes a structure with additional, solver dependent
* flags for tuning.
*/
SolverCGS (SolverControl &cn,
protected:
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
};
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Constructor. By default, set the
- * number of temporary vectors to
- * 30, i.e. do a restart every 30
- * iterations.
+ * Constructor. By default, set the number of temporary vectors to 30,
+ * i.e. do a restart every 30 iterations.
*/
AdditionalData (const bool output_solver_details = false,
const unsigned int restart_parameter = 30);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
/**
- * Maximum number of
- * tmp vectors.
+ * Maximum number of tmp vectors.
*/
unsigned int restart_parameter;
};
/**
- * Constructor. In contrast to
- * deal.II's own solvers, there is no
- * need to give a vector memory
- * object.
+ * Constructor. In contrast to deal.II's own solvers, there is no need to
+ * give a vector memory object.
*
- * The last argument takes a structure
- * with additional, solver dependent
+ * The last argument takes a structure with additional, solver dependent
* flags for tuning.
*/
SolverGMRES (SolverControl &cn,
protected:
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
};
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format.
+ * Sets the additional data field to the desired output format.
*/
AdditionalData (const bool output_solver_details = false);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
};
/**
- * Constructor. In contrast to
- * deal.II's own solvers, there is no
- * need to give a vector memory
- * object.
+ * Constructor. In contrast to deal.II's own solvers, there is no need to
+ * give a vector memory object.
*
- * The last argument takes a structure
- * with additional, solver dependent
+ * The last argument takes a structure with additional, solver dependent
* flags for tuning.
*/
SolverBicgstab (SolverControl &cn,
protected:
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
};
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format.
+ * Sets the additional data field to the desired output format.
*/
AdditionalData (const bool output_solver_details = false);
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
};
/**
- * Constructor. In contrast to
- * deal.II's own solvers, there is no
- * need to give a vector memory
- * object.
+ * Constructor. In contrast to deal.II's own solvers, there is no need to
+ * give a vector memory object.
*
- * The last argument takes a structure
- * with additional, solver dependent
+ * The last argument takes a structure with additional, solver dependent
* flags for tuning.
*/
SolverTFQMR (SolverControl &cn,
protected:
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
};
/**
- * An implementation of the Trilinos KLU direct solver (using the Amesos
- * package).
+ * An implementation of Trilinos direct solvers (using the Amesos
+ * package). The data field AdditionalData::solver_type can be used to
+ * specify the type of solver. It allows the use of built-in solvers
+ * Amesos_Klu as well as third-party solvers Amesos_Superludist or
+ * Amesos_Mumps.
+ *
+ * For instructions on how to install Trilinos for use with
+ * direct solvers other than KLU, see the link to the Trilinos
+ * installation instructions linked to from the deal.II ReadMe file.
*
* @ingroup TrilinosWrappers
- * @author Martin Kronbichler, 2009
+ * @author Martin Kronbichler, 2009, Uwe Köcher, 2014
*/
class SolverDirect
{
public:
/**
- * Standardized data struct to
- * pipe additional data to the
- * solver.
+ * Standardized data struct to pipe additional data to the solver.
*/
struct AdditionalData
{
/**
- * Sets the additional data field to
- * the desired output format.
+ * Sets the additional data field to the desired output format.
*/
- AdditionalData (const bool output_solver_details = false);
+ AdditionalData (const bool output_solver_details = false,
+ const std::string &solver_type = "Amesos_Klu");
/**
- * Enables/disables the output of
- * solver details (residual in each
+ * Enables/disables the output of solver details (residual in each
* iterations etc.).
*/
bool output_solver_details;
+
+ /**
+ * Set the solver type (for third party solver support of Trilinos
+ * Amesos package). Possibilities are:
+ * <ul>
+ * <li> "Amesos_Lapack" </li>
+ * <li> "Amesos_Scalapack" </li>
+ * <li> "Amesos_Klu" </li>
+ * <li> "Amesos_Umfpack" </li>
+ * <li> "Amesos_Pardiso" </li>
+ * <li> "Amesos_Taucs" </li>
+ * <li> "Amesos_Superlu" </li>
+ * <li> "Amesos_Superludist" </li>
+ * <li> "Amesos_Dscpack" </li>
+ * <li> "Amesos_Mumps" </li>
+ * </ul>
+ * Note that the availability of these solvers in deal.II depends on
+ * which solvers were set when configuring Trilinos.
+ */
+ std::string solver_type;
};
/**
- * Constructor. Takes the
- * solver control object and
- * creates the solver.
+ * Constructor. Takes the solver control object and creates the solver.
*/
SolverDirect (SolverControl &cn,
const AdditionalData &data = AdditionalData());
virtual ~SolverDirect ();
/**
- * Solve the linear system
- * <tt>Ax=b</tt>. Creates a KLU
- * factorization of the matrix and
- * performs the solve. Note that
- * there is no need for a
- * preconditioner here.
+ * Solve the linear system <tt>Ax=b</tt>. Creates a factorization of the
+ * matrix with the package chosen from the additional data structure and
+ * performs the solve. Note that there is no need for a preconditioner
+ * here.
*/
void
solve (const SparseMatrix &A,
const VectorBase &b);
/**
- * Solve the linear system
- * <tt>Ax=b</tt>. Depending on the
- * information provided by derived
- * classes and the object passed as a
- * preconditioner, one of the linear
- * solvers and preconditioners of
- * Trilinos is chosen. This class
- * works with matrices according to
- * the TrilinosWrappers format, but
- * can take deal.II vectors as
- * argument. Since deal.II are serial
- * vectors (not distributed), this
- * function does only what you expect
- * in case the matrix is locally
- * owned. Otherwise, an exception
- * will be thrown.
+ * Solve the linear system <tt>Ax=b</tt>. This class works with Trilinos
+ * matrices, but takes deal.II serial vectors as argument. Since these
+ * vectors are not distributed, this function does only what you expect in
+ * case the matrix is serial (i.e., locally owned). Otherwise, an
+ * exception will be thrown.
*/
void
solve (const SparseMatrix &A,
dealii::Vector<double> &x,
const dealii::Vector<double> &b);
+ /**
+ * Solve the linear system <tt>Ax=b</tt> for deal.II's own parallel
+ * vectors. Creates a factorization of the matrix with the package chosen
+ * from the additional data structure and performs the solve. Note that
+ * there is no need for a preconditioner here.
+ */
+ void
+ solve (const SparseMatrix &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b);
+
/**
* Access to object that controls
* convergence.
<< " occurred while calling a Trilinos function");
private:
+ /**
+ * Actually performs the operations for solving the linear system,
+ * including the factorization and forward and backward substitution.
+ */
+ void do_solve();
/**
- * Reference to the object that
- * controls convergence of the
- * iterative solver. In fact,
- * for these Trilinos wrappers,
- * Trilinos does so itself, but
- * we copy the data from this
- * object before starting the
- * solution process, and copy
- * the data back into it
- * afterwards.
+ * Reference to the object that controls convergence of the iterative
+ * solver. In fact, for these Trilinos wrappers, Trilinos does so itself,
+ * but we copy the data from this object before starting the solution
+ * process, and copy the data back into it afterwards.
*/
SolverControl &solver_control;
/**
- * A structure that collects
- * the Trilinos sparse matrix,
- * the right hand side vector
- * and the solution vector,
- * which is passed down to the
+ * A structure that collects the Trilinos sparse matrix, the right hand
+ * side vector and the solution vector, which is passed down to the
* Trilinos solver.
*/
std_cxx1x::shared_ptr<Epetra_LinearProblem> linear_problem;
/**
- * A structure that contains
- * the Trilinos solver and
- * preconditioner objects.
+ * A structure that contains the Trilinos solver and preconditioner
+ * objects.
*/
std_cxx1x::shared_ptr<Amesos_BaseSolver> solver;
/**
- * Store a copy of the flags for this
- * particular solver.
+ * Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
-
};
}
* TrilinosWrappers::SparsityPattern object that in turn has been
* initialized with the reinit function specifying three index sets, one
* for the rows, one for the columns and for the larger set of @p
- * writeable_rows, and the operation is an addition.
+ * writeable_rows, and the operation is an addition. If Trilinos version
+ * 11.10 and greater is used, initializing from a
+ * TrilinosWrappers::SparsityPattern that has been filled by a function
+ * similar to DoFTools::make_sparsity_pattern always results in a matrix
+ * that allows several processes to write into the same matrix row.
* </ul>
*
* Note that all other reinit methods and constructors of
const TrilinosScalar new_diag_value = 0);
/**
- * Make an in-place transpose of a matrix.
+ * Sets an internal flag so that all operations performed by the matrix,
+ * i.e., multiplications, are done in transposed order. However, this does
+ * not reshape the matrix to transposed form directly, so care should be
+ * taken when using this flag.
*/
void transpose ();
*/
std_cxx1x::shared_ptr<Epetra_Map> column_space_map;
- /**
- * A boolean variable to hold information on whether the vector is
- * compressed or not.
- */
- bool compressed;
-
/**
* A sparsity pattern object in Trilinos to be used for finite element
* based problems which allows for adding non-local elements to the
bool
SparsityPattern::is_compressed () const
{
- return compressed;
+ return graph->Filled();
}
TrilinosWrappers::types::int_type *col_index_ptr =
(TrilinosWrappers::types::int_type *)(&*begin);
const int n_cols = static_cast<int>(end - begin);
- compressed = false;
int ierr;
if ( graph->RowMap().LID(static_cast<TrilinosWrappers::types::int_type>(row)) != -1)
DeclException3 (ExcAccessToNonLocalElement,
size_type, size_type, size_type,
<< "You tried to access element " << arg1
- << " of a distributed vector, but it is not stored on "
- << "the current processor. Note: the elements stored "
+ << " of a distributed vector, but this element is not stored "
+ << "on the current processor. Note: The elements stored "
<< "on the current processor are within the range "
<< arg2 << " through " << arg3
<< " but Trilinos vectors need not store contiguous "
*/
const_iterator end () const;
+ //@}
+
+
+ /**
+ * @name 3: Modification of vectors
+ */
+ //@{
+
/**
* A collective set operation: instead of setting individual elements of a
* vector, this function allows to set a whole set of elements at
*/
void set (const std::vector<size_type> &indices,
const ::dealii::Vector<TrilinosScalar> &values);
- //@}
-
-
- /**
- * @name 3: Modification of vectors
- */
- //@{
/**
* This collective set operation is of lower level and can handle anything
const TrilinosScalar *values);
/**
- * A collective add operation: This funnction adds a whole set of values
+ * A collective add operation: This function adds a whole set of values
* stored in @p values to the vector components specified by @p indices.
*/
void add (const std::vector<size_type> &indices,
* Simple vector addition, equal to the <tt>operator +=</tt>.
*
* Though, if the second argument <tt>allow_different_maps</tt> is set,
- * then it is possible to add data from a different map.
+ * then it is possible to add data from a vector that uses a different
+ * map, i.e., a vector whose elements are split across processors
+ * differently. This may include vectors with ghost elements, for example.
+ * In general, however, adding vectors with a different element-to-processor
+ * map requires communicating data among processors and, consequently,
+ * is a slower operation than when using vectors using the same map.
*/
void add (const VectorBase &V,
const bool allow_different_maps = false);
/**
- * Simple addition of a multiple of a vector, i.e. <tt>*this = a*V</tt>.
+ * Simple addition of a multiple of a vector, i.e. <tt>*this += a*V</tt>.
*/
void add (const TrilinosScalar a,
const VectorBase &V);
/**
- * Multiple addition of scaled vectors, i.e. <tt>*this = a*V + b*W</tt>.
+ * Multiple addition of scaled vectors, i.e. <tt>*this += a*V + b*W</tt>.
*/
void add (const TrilinosScalar a,
const VectorBase &V,
bool has_ghosts;
/**
- * An Epetra distibuted vector type. Requires an existing Epetra_Map for
- * storing data.
+ * Pointer to the actual Epetra vector object. This may represent a
+ * vector that is in fact distributed among multiple processors. The
+ * object requires an existing Epetra_Map for
+ * storing data when setting it up.
*/
std_cxx1x::shared_ptr<Epetra_FEVector> vector;
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
- const int ierr = vector->Update(1., *(v.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ if(local_size() == v.local_size())
+ {
+ const int ierr = vector->Update(1., *(v.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ VectorBase tmp = v;
+ tmp *= s;
+ this->add(tmp, true);
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
- const int ierr = vector->Update(a, *(v.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ if(local_size() == v.local_size())
+ {
+ const int ierr = vector->Update(a, *(v.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ (*this)*=s;
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
- Assert (local_size() == w.local_size(),
- ExcDimensionMismatch(local_size(), w.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
+ Assert (size() == w.size(),
+ ExcDimensionMismatch (size(), w.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
Assert (numbers::is_finite(b), ExcNumberNotFinite());
-
- const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
-
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ if(local_size() == v.local_size() && local_size() == w.local_size())
+ {
+ const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+ else
+ {
+ (*this)*=s;
+ {
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = w;
+ tmp *= b;
+ this->add(tmp, true);
+ }
+ }
}
// if we have ghost values, do not allow
// writing to this vector at all.
Assert (!has_ghost_elements(), ExcGhostsPresent());
- Assert (local_size() == v.local_size(),
- ExcDimensionMismatch(local_size(), v.local_size()));
- Assert (local_size() == w.local_size(),
- ExcDimensionMismatch(local_size(), w.local_size()));
- Assert (local_size() == x.local_size(),
- ExcDimensionMismatch(local_size(), x.local_size()));
-
+ Assert (size() == v.size(),
+ ExcDimensionMismatch (size(), v.size()));
+ Assert (size() == w.size(),
+ ExcDimensionMismatch (size(), w.size()));
+ Assert (size() == x.size(),
+ ExcDimensionMismatch (size(), x.size()));
Assert (numbers::is_finite(s), ExcNumberNotFinite());
Assert (numbers::is_finite(a), ExcNumberNotFinite());
Assert (numbers::is_finite(b), ExcNumberNotFinite());
Assert (numbers::is_finite(c), ExcNumberNotFinite());
- // Update member can only
- // input two other vectors so
- // do it in two steps
- const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
- AssertThrow (ierr == 0, ExcTrilinosError(ierr));
-
- const int jerr = vector->Update(c, *(x.vector), 1.);
- Assert (jerr == 0, ExcTrilinosError(jerr));
- (void)jerr; // removes -Wunused-parameter warning in optimized mode
+ if(local_size() == v.local_size()
+ && local_size() == w.local_size()
+ && local_size() == x.local_size())
+ {
+ // Update member can only
+ // input two other vectors so
+ // do it in two steps
+ const int ierr = vector->Update(a, *(v.vector), b, *(w.vector), s);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ const int jerr = vector->Update(c, *(x.vector), 1.);
+ Assert (jerr == 0, ExcTrilinosError(jerr));
+ (void)jerr; // removes -Wunused-parameter warning in optimized mode
+ }
+ else
+ {
+ (*this)*=s;
+ {
+ VectorBase tmp = v;
+ tmp *= a;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = w;
+ tmp *= b;
+ this->add(tmp, true);
+ }
+ {
+ VectorBase tmp = x;
+ tmp *= c;
+ this->add(tmp, true);
+ }
+ }
}
// If we don't have the same map, copy.
if (vector->Map().SameAs(v.vector->Map())==false)
{
- *vector = *v.vector;
- *this *= a;
+ this->sadd(0., a, v);
}
else
{
// If we don't have the same map, copy.
if (vector->Map().SameAs(v.vector->Map())==false)
{
- *vector = *v.vector;
- sadd(a, b, w);
+ sadd(0., a, v, b, w);
}
else
{
{
public:
/**
- * Declare standard types used in all
- * containers. These types parallel
- * those in the <tt>C++</tt> standard libraries
- * <tt>vector<...></tt> class.
+ * Declare standard types used in all containers. These types parallel those
+ * in the <tt>C++</tt> standard libraries <tt>vector<...></tt> class.
*/
typedef Number value_type;
typedef value_type *pointer;
typedef types::global_dof_index size_type;
/**
- * Declare a type that has holds
- * real-valued numbers with the
- * same precision as the template
- * argument to this class. If the
- * template argument of this
- * class is a real data type,
- * then real_type equals the
- * template argument. If the
- * template argument is a
- * std::complex type then
- * real_type equals the type
- * underlying the complex
- * numbers.
+ * Declare a type that has holds real-valued numbers with the same precision
+ * as the template argument to this class. If the template argument of this
+ * class is a real data type, then real_type equals the template
+ * argument. If the template argument is a std::complex type then real_type
+ * equals the type underlying the complex numbers.
*
- * This typedef is used to
- * represent the return type of
- * norms.
+ * This typedef is used to represent the return type of norms.
*/
typedef typename numbers::NumberTraits<Number>::real_type real_type;
*/
//@{
/**
- * Constructor. Create a vector of
- * dimension zero.
+ * Constructor. Create a vector of dimension zero.
*/
Vector ();
/**
- * Copy-constructor. Sets the dimension
- * to that of the given vector, and
+ * Copy-constructor. Sets the dimension to that of the given vector, and
* copies all elements.
*
- * We would like to make this
- * constructor explicit, but STL
- * insists on using it implicitly.
+ * We would like to make this constructor explicit, but STL insists on using
+ * it implicitly.
*/
Vector (const Vector<Number> &v);
#ifndef DEAL_II_EXPLICIT_CONSTRUCTOR_BUG
/**
- * Copy constructor taking a vector of
- * another data type. This will fail if
- * there is no conversion path from
- * @p OtherNumber to @p Number. Note that
- * you may lose accuracy when copying
- * to a vector with data elements with
+ * Copy constructor taking a vector of another data type. This will fail if
+ * there is no conversion path from @p OtherNumber to @p Number. Note that
+ * you may lose accuracy when copying to a vector with data elements with
* less accuracy.
*
- * Older versions of gcc did not honor
- * the @p explicit keyword on template
- * constructors. In such cases, it is
- * easy to accidentally write code that
- * can be very inefficient, since the
- * compiler starts performing hidden
- * conversions. To avoid this, this
- * function is disabled if we have
- * detected a broken compiler during
- * configuration.
+ * Older versions of gcc did not honor the @p explicit keyword on template
+ * constructors. In such cases, it is easy to accidentally write code that
+ * can be very inefficient, since the compiler starts performing hidden
+ * conversions. To avoid this, this function is disabled if we have detected
+ * a broken compiler during configuration.
*/
template <typename OtherNumber>
explicit
#ifdef DEAL_II_WITH_PETSC
/**
- * Another copy constructor: copy the
- * values from a sequential PETSc wrapper
- * vector class. This copy constructor is
- * only available if PETSc was detected
- * during configuration time.
+ * Another copy constructor: copy the values from a sequential PETSc wrapper
+ * vector class. This copy constructor is only available if PETSc was
+ * detected during configuration time.
*/
Vector (const PETScWrappers::Vector &v);
/**
- * Another copy constructor: copy the
- * values from a parallel PETSc wrapper
- * vector class. This copy constructor is
- * only available if PETSc was detected
- * during configuration time.
+ * Another copy constructor: copy the values from a parallel PETSc wrapper
+ * vector class. This copy constructor is only available if PETSc was
+ * detected during configuration time.
*
- * Note that due to the communication
- * model used in MPI, this operation can
- * only succeed if all processes do it at
- * the same time. I.e., it is not
- * possible for only one process to
- * obtain a copy of a parallel vector
- * while the other jobs do something
- * else.
+ * Note that due to the communication model used in MPI, this operation can
+ * only succeed if all processes do it at the same time. I.e., it is not
+ * possible for only one process to obtain a copy of a parallel vector while
+ * the other jobs do something else.
*/
Vector (const PETScWrappers::MPI::Vector &v);
#endif
#ifdef DEAL_II_WITH_TRILINOS
/**
- * Another copy constructor: copy
- * the values from a Trilinos
- * wrapper vector. This copy
- * constructor is only available if
- * Trilinos was detected during
- * configuration time.
+ * Another copy constructor: copy the values from a Trilinos wrapper
+ * vector. This copy constructor is only available if Trilinos was detected
+ * during configuration time.
*
- * Note that due to the
- * communication model used in MPI,
- * this operation can only succeed
- * if all processes do it at the
- * same time. This means that it is
- * not possible for only one
- * process to obtain a copy of a
- * parallel vector while the other
- * jobs do something else. This
- * call will rather result in a
- * copy of the vector on all
- * processors.
+ * Note that due to the communication model used in MPI, this operation can
+ * only succeed if all processes do it at the same time. This means that it
+ * is not possible for only one process to obtain a copy of a parallel
+ * vector while the other jobs do something else. This call will rather
+ * result in a copy of the vector on all processors.
*/
Vector (const TrilinosWrappers::MPI::Vector &v);
/**
- * Another copy constructor: copy
- * the values from a localized
- * Trilinos wrapper vector. This
- * copy constructor is only
- * available if Trilinos was
- * detected during configuration
- * time.
+ * Another copy constructor: copy the values from a localized Trilinos
+ * wrapper vector. This copy constructor is only available if Trilinos was
+ * detected during configuration time.
*/
Vector (const TrilinosWrappers::Vector &v);
#endif
/**
- * Constructor. Set dimension to
- * @p n and initialize all
- * elements with zero.
+ * Constructor. Set dimension to @p n and initialize all elements with zero.
*
- * The constructor is made
- * explicit to avoid accidents
- * like this:
- * <tt>v=0;</tt>. Presumably, the user
- * wants to set every element of
- * the vector to zero, but
- * instead, what happens is this
- * call:
- * <tt>v=Vector@<number@>(0);</tt>,
- * i.e. the vector is replaced by
- * one of length zero.
+ * The constructor is made explicit to avoid accidents like this:
+ * <tt>v=0;</tt>. Presumably, the user wants to set every element of the
+ * vector to zero, but instead, what happens is this call:
+ * <tt>v=Vector@<number@>(0);</tt>, i.e. the vector is replaced by one of
+ * length zero.
*/
explicit Vector (const size_type n);
/**
- * Initialize the vector with a
- * given range of values pointed
- * to by the iterators. This
- * function is there in analogy
- * to the @p std::vector class.
+ * Initialize the vector with a given range of values pointed to by the
+ * iterators. This function is there in analogy to the @p std::vector class.
*/
template <typename InputIterator>
Vector (const InputIterator first,
const InputIterator last);
/**
- * Destructor, deallocates
- * memory. Made virtual to allow
- * for derived classes to behave
- * properly.
+ * Destructor, deallocates memory. Made virtual to allow for derived classes
+ * to behave properly.
*/
virtual ~Vector ();
/**
- * This function does nothing but is
- * there for compatibility with the
- * @p PETScWrappers::Vector class.
+ * This function does nothing but is there for compatibility with the @p
+ * PETScWrappers::Vector class.
*
- * For the PETSc vector wrapper class,
- * this function compresses the
- * underlying representation of the PETSc
- * object, i.e. flushes the buffers of
- * the vector object if it has any. This
- * function is necessary after writing
- * into a vector element-by-element and
- * before anything else can be done on
- * it.
+ * For the PETSc vector wrapper class, this function compresses the
+ * underlying representation of the PETSc object, i.e. flushes the buffers
+ * of the vector object if it has any. This function is necessary after
+ * writing into a vector element-by-element and before anything else can be
+ * done on it.
*
- * However, for the implementation of
- * this class, it is immaterial and thus
+ * However, for the implementation of this class, it is immaterial and thus
* an empty function.
*/
void compress (::dealii::VectorOperation::values operation
=::dealii::VectorOperation::unknown) const;
/**
- * Change the dimension of the vector to
- * @p N. The reserved memory for this
- * vector remains unchanged if possible,
- * to make things faster; this may waste
- * some memory, so keep this in mind.
- * However, if <tt>N==0</tt> all memory is
- * freed, i.e. if you want to resize the
- * vector and release the memory not
- * needed, you have to first call
- * <tt>reinit(0)</tt> and then
- * <tt>reinit(N)</tt>. This cited behaviour is
- * analogous to that of the STL
+ * Change the dimension of the vector to @p N. The reserved memory for this
+ * vector remains unchanged if possible, to make things faster; this may
+ * waste some memory, so keep this in mind. However, if <tt>N==0</tt> all
+ * memory is freed, i.e. if you want to resize the vector and release the
+ * memory not needed, you have to first call <tt>reinit(0)</tt> and then
+ * <tt>reinit(N)</tt>. This cited behaviour is analogous to that of the STL
* containers.
*
- * If @p fast is false, the vector is
- * filled by zeros. Otherwise, the
- * elements are left an unspecified
- * state.
+ * If @p fast is false, the vector is filled by zeros. Otherwise, the
+ * elements are left an unspecified state.
*
- * This function is virtual in
- * order to allow for derived
- * classes to handle memory
- * separately.
+ * This function is virtual in order to allow for derived classes to handle
+ * memory separately.
*/
virtual void reinit (const size_type N,
const bool fast=false);
/**
- * Change the dimension to that of the
- * vector @p V. The same applies as for
+ * Change the dimension to that of the vector @p V. The same applies as for
* the other @p reinit function.
*
- * The elements of @p V are not copied,
- * i.e. this function is the same as
+ * The elements of @p V are not copied, i.e. this function is the same as
* calling <tt>reinit (V.size(), fast)</tt>.
*/
template <typename Number2>
const bool fast=false);
/**
- * Swap the contents of this
- * vector and the other vector
- * @p v. One could do this
- * operation with a temporary
- * variable and copying over the
- * data elements, but this
- * function is significantly more
- * efficient since it only swaps
- * the pointers to the data of
- * the two vectors and therefore
- * does not need to allocate
- * temporary storage and move
- * data around.
+ * Swap the contents of this vector and the other vector @p v. One could do
+ * this operation with a temporary variable and copying over the data
+ * elements, but this function is significantly more efficient since it only
+ * swaps the pointers to the data of the two vectors and therefore does not
+ * need to allocate temporary storage and move data around.
*
- * This function is analog to the
- * the @p swap function of all C++
- * standard containers. Also,
- * there is a global function
- * <tt>swap(u,v)</tt> that simply calls
- * <tt>u.swap(v)</tt>, again in analogy
- * to standard functions.
+ * This function is analog to the the @p swap function of all C++ standard
+ * containers. Also, there is a global function <tt>swap(u,v)</tt> that
+ * simply calls <tt>u.swap(v)</tt>, again in analogy to standard functions.
*
- * This function is virtual in
- * order to allow for derived
- * classes to handle memory
- * separately.
+ * This function is virtual in order to allow for derived classes to handle
+ * memory separately.
*/
virtual void swap (Vector<Number> &v);
/**
- * Set all components of the vector to
- * the given number @p s. Simply pass
- * this down to the individual block
- * objects, but we still need to declare
- * this function to make the example
- * given in the discussion about making
+ * Set all components of the vector to the given number @p s. Simply pass
+ * this down to the individual block objects, but we still need to declare
+ * this function to make the example given in the discussion about making
* the constructor explicit work.
*
- * Since the semantics of assigning a
- * scalar to a vector are not
- * immediately clear, this operator
- * should really only be used if you
- * want to set the entire vector to
- * zero. This allows the intuitive
- * notation <tt>v=0</tt>. Assigning
- * other values is deprecated and may
- * be disallowed in the future.
+ * Since the semantics of assigning a scalar to a vector are not immediately
+ * clear, this operator should really only be used if you want to set the
+ * entire vector to zero. This allows the intuitive notation
+ * <tt>v=0</tt>. Assigning other values is deprecated and may be disallowed
+ * in the future.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator = (const Number s);
/**
- * Copy the given vector. Resize the
- * present vector if necessary.
+ * Copy the given vector. Resize the present vector if necessary.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator= (const Vector<Number> &v);
/**
- * Copy the given vector. Resize the
- * present vector if necessary.
+ * Copy the given vector. Resize the present vector if necessary.
+ *
+ * @dealiiOperationIsMultithreaded
*/
template <typename Number2>
Vector<Number> &operator= (const Vector<Number2> &v);
/**
- * Copy operator for assigning a
- * block vector to a regular
- * vector.
+ * Copy operator for assigning a block vector to a regular vector.
*/
Vector<Number> &operator= (const BlockVector<Number> &v);
#ifdef DEAL_II_WITH_PETSC
/**
- * Another copy operator: copy the
- * values from a sequential PETSc
- * wrapper vector class. This
- * operator is only available if
- * PETSc was detected during
- * configuration time.
+ * Another copy operator: copy the values from a sequential PETSc wrapper
+ * vector class. This operator is only available if PETSc was detected
+ * during configuration time.
*/
Vector<Number> &
operator = (const PETScWrappers::Vector &v);
/**
- * Another copy operator: copy the
- * values from a parallel PETSc
- * wrapper vector class. This
- * operator is only available if
- * PETSc was detected during
- * configuration time.
+ * Another copy operator: copy the values from a parallel PETSc wrapper
+ * vector class. This operator is only available if PETSc was detected
+ * during configuration time.
*
- * Note that due to the
- * communication model used in MPI,
- * this operation can only succeed
- * if all processes do it at the
- * same time. I.e., it is not
- * possible for only one process to
- * obtain a copy of a parallel
- * vector while the other jobs do
- * something else.
+ * Note that due to the communication model used in MPI, this operation can
+ * only succeed if all processes do it at the same time. I.e., it is not
+ * possible for only one process to obtain a copy of a parallel vector while
+ * the other jobs do something else.
*/
Vector<Number> &
operator = (const PETScWrappers::MPI::Vector &v);
#ifdef DEAL_II_WITH_TRILINOS
/**
- * Another copy operator: copy
- * the values from a (sequential
- * or parallel, depending on the
- * underlying compiler) Trilinos
- * wrapper vector class. This
- * operator is only available if
- * Trilinos was detected during
- * configuration time.
+ * Another copy operator: copy the values from a (sequential or parallel,
+ * depending on the underlying compiler) Trilinos wrapper vector class. This
+ * operator is only available if Trilinos was detected during configuration
+ * time.
*
- * Note that due to the
- * communication model used in MPI,
- * this operation can only succeed
- * if all processes do it at the
- * same time. I.e., it is not
- * possible for only one process to
- * obtain a copy of a parallel
- * vector while the other jobs do
- * something else.
+ * Note that due to the communication model used in MPI, this operation can
+ * only succeed if all processes do it at the same time. I.e., it is not
+ * possible for only one process to obtain a copy of a parallel vector while
+ * the other jobs do something else.
*/
Vector<Number> &
operator = (const TrilinosWrappers::MPI::Vector &v);
/**
- * Another copy operator: copy the
- * values from a sequential
- * Trilinos wrapper vector
- * class. This operator is only
- * available if Trilinos was
- * detected during configuration
- * time.
+ * Another copy operator: copy the values from a sequential Trilinos wrapper
+ * vector class. This operator is only available if Trilinos was detected
+ * during configuration time.
*/
Vector<Number> &
operator = (const TrilinosWrappers::Vector &v);
#endif
/**
- * Test for equality. This function
- * assumes that the present vector
- * and the one to compare with have
- * the same size already, since
- * comparing vectors of different
- * sizes makes not much sense
- * anyway.
+ * Test for equality. This function assumes that the present vector and the
+ * one to compare with have the same size already, since comparing vectors
+ * of different sizes makes not much sense anyway.
*/
template <typename Number2>
bool operator == (const Vector<Number2> &v) const;
/**
- * Test for inequality. This function
- * assumes that the present vector and
- * the one to compare with have the same
- * size already, since comparing vectors
- * of different sizes makes not much
- * sense anyway.
+ * Test for inequality. This function assumes that the present vector and
+ * the one to compare with have the same size already, since comparing
+ * vectors of different sizes makes not much sense anyway.
*/
template <typename Number2>
bool operator != (const Vector<Number2> &v) const;
/**
- * Return the scalar product of
- * two vectors. The return type
- * is the underlying type of
- * @p this vector, so the return
- * type and the accuracy with
- * which it the result is
- * computed depend on the order
- * of the arguments of this
- * vector.
+ * Return the scalar product of two vectors. The return type is the
+ * underlying type of @p this vector, so the return type and the accuracy
+ * with which it the result is computed depend on the order of the arguments
+ * of this vector.
+ *
+ * For complex vectors, the scalar product is implemented as
+ * $\left<v,w\right>=\sum_i v_i \bar{w_i}$.
*
- * For complex vectors, the
- * scalar product is implemented
- * as $\left<v,w\right>=\sum_i
- * v_i \bar{w_i}$.
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
template <typename Number2>
Number operator * (const Vector<Number2> &V) const;
/**
* Return square of the $l_2$-norm.
+ *
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
real_type norm_sqr () const;
/**
- * Mean value of the elements of
- * this vector.
+ * Mean value of the elements of this vector.
+ *
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
Number mean_value () const;
/**
- * $l_1$-norm of the vector.
- * The sum of the absolute values.
+ * $l_1$-norm of the vector. The sum of the absolute values.
+ *
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
real_type l1_norm () const;
/**
- * $l_2$-norm of the vector. The
- * square root of the sum of the
- * squares of the elements.
+ * $l_2$-norm of the vector. The square root of the sum of the squares of
+ * the elements.
+ *
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
real_type l2_norm () const;
/**
- * $l_p$-norm of the vector. The
- * pth root of the sum of the pth
- * powers of the absolute values
- * of the elements.
+ * $l_p$-norm of the vector. The pth root of the sum of the pth powers of
+ * the absolute values of the elements.
+ *
+ * @dealiiOperationIsMultithreaded The algorithm uses pairwise
+ * summation with the same order of summation in every run, which gives
+ * fully repeatable results from one run to another.
*/
real_type lp_norm (const real_type p) const;
/**
- * Maximum absolute value of the
- * elements.
+ * Maximum absolute value of the elements.
*/
real_type linfty_norm () const;
/**
- * Returns true if the given global index is
- * in the local range of this processor.
- * Since this is not a distributed
- * vector the method always returns true.
+ * Returns true if the given global index is in the local range of this
+ * processor. Since this is not a distributed vector the method always
+ * returns true.
*/
bool in_local_range (const size_type global_index) const;
std::size_t size () const;
/**
- * Return whether the vector contains only
- * elements with value zero. This function
- * is mainly for internal consistency
- * checks and should seldom be used when
- * not in debug mode since it uses quite
- * some time.
+ * Return whether the vector contains only elements with value zero. This
+ * function is mainly for internal consistency checks and should seldom be
+ * used when not in debug mode since it uses quite some time.
*/
bool all_zero () const;
/**
- * Return @p true if the vector has no
- * negative entries, i.e. all entries are
- * zero or positive. This function is
- * used, for example, to check whether
- * refinement indicators are really all
- * positive (or zero).
+ * Return @p true if the vector has no negative entries, i.e. all entries
+ * are zero or positive. This function is used, for example, to check
+ * whether refinement indicators are really all positive (or zero).
*
- * The function obviously only makes
- * sense if the template argument of this
- * class is a real type. If it is a
- * complex type, then an exception is
+ * The function obviously only makes sense if the template argument of this
+ * class is a real type. If it is a complex type, then an exception is
* thrown.
*/
bool is_non_negative () const;
/**
- * Make the @p Vector class a bit like
- * the <tt>vector<></tt> class of the C++
- * standard library by returning
- * iterators to the start and end of the
+ * Make the @p Vector class a bit like the <tt>vector<></tt> class of the
+ * C++ standard library by returning iterators to the start and end of the
* elements of this vector.
*/
iterator begin ();
/**
- * Return constant iterator to the start of
- * the vectors.
+ * Return constant iterator to the start of the vectors.
*/
const_iterator begin () const;
/**
- * Return an iterator pointing to the
- * element past the end of the array.
+ * Return an iterator pointing to the element past the end of the array.
*/
iterator end ();
/**
- * Return a constant iterator pointing to
- * the element past the end of the array.
+ * Return a constant iterator pointing to the element past the end of the
+ * array.
*/
const_iterator end () const;
//@}
*/
//@{
/**
- * Access the value of the @p ith
- * component.
+ * Access the value of the @p ith component.
*/
Number operator() (const size_type i) const;
/**
- * Access the @p ith component
- * as a writeable reference.
+ * Access the @p ith component as a writeable reference.
*/
Number &operator() (const size_type i);
/**
- * Access the value of the @p ith
- * component.
+ * Access the value of the @p ith component.
*
* Exactly the same as operator().
*/
Number operator[] (const size_type i) const;
/**
- * Access the @p ith component
- * as a writeable reference.
+ * Access the @p ith component as a writeable reference.
*
* Exactly the same as operator().
*/
Number &operator[] (const size_type i);
/**
- * A collective get operation: instead
- * of getting individual elements of a
- * vector, this function allows to get
- * a whole set of elements at once. The
- * indices of the elements to be read
- * are stated in the first argument,
- * the corresponding values are returned in the
- * second.
+ * A collective get operation: instead of getting individual elements of a
+ * vector, this function allows to get a whole set of elements at once. The
+ * indices of the elements to be read are stated in the first argument, the
+ * corresponding values are returned in the second.
*/
template <typename OtherNumber>
void extract_subvector_to (const std::vector<size_type> &indices,
std::vector<OtherNumber> &values) const;
/**
- * Just as the above, but with pointers.
- * Useful in minimizing copying of data around.
+ * Just as the above, but with pointers. Useful in minimizing copying of
+ * data around.
*/
template <typename ForwardIterator, typename OutputIterator>
void extract_subvector_to (ForwardIterator indices_begin,
//@{
/**
- * Add the given vector to the present
- * one.
+ * Add the given vector to the present one.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator += (const Vector<Number> &V);
/**
- * Subtract the given vector from the
- * present one.
+ * Subtract the given vector from the present one.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator -= (const Vector<Number> &V);
/**
- * A collective add operation:
- * This funnction adds a whole
- * set of values stored in @p
- * values to the vector
- * components specified by @p
- * indices.
+ * A collective add operation: This funnction adds a whole set of values
+ * stored in @p values to the vector components specified by @p indices.
*/
template <typename OtherNumber>
void add (const std::vector<size_type> &indices,
const std::vector<OtherNumber> &values);
/**
- * This is a second collective
- * add operation. As a
- * difference, this function
- * takes a deal.II vector of
- * values.
+ * This is a second collective add operation. As a difference, this function
+ * takes a deal.II vector of values.
*/
template <typename OtherNumber>
void add (const std::vector<size_type> &indices,
const Vector<OtherNumber> &values);
/**
- * Take an address where
- * <tt>n_elements</tt> are stored
- * contiguously and add them into
- * the vector. Handles all cases
- * which are not covered by the
- * other two <tt>add()</tt>
- * functions above.
+ * Take an address where <tt>n_elements</tt> are stored contiguously and add
+ * them into the vector. Handles all cases which are not covered by the
+ * other two <tt>add()</tt> functions above.
*/
template <typename OtherNumber>
void add (const size_type n_elements,
const OtherNumber *values);
/**
- * Addition of @p s to all
- * components. Note that @p s is a
- * scalar and not a vector.
+ * Addition of @p s to all components. Note that @p s is a scalar and not a
+ * vector.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void add (const Number s);
/**
- * Simple vector addition, equal to the
- * <tt>operator +=</tt>.
+ * Simple vector addition, equal to the <tt>operator +=</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void add (const Vector<Number> &V);
/**
- * Simple addition of a multiple of a
- * vector, i.e. <tt>*this += a*V</tt>.
+ * Simple addition of a multiple of a vector, i.e. <tt>*this += a*V</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void add (const Number a, const Vector<Number> &V);
/**
- * Multiple addition of scaled vectors,
- * i.e. <tt>*this += a*V+b*W</tt>.
+ * Multiple addition of scaled vectors, i.e. <tt>*this += a*V+b*W</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void add (const Number a, const Vector<Number> &V,
const Number b, const Vector<Number> &W);
/**
- * Scaling and simple vector addition,
- * i.e.
- * <tt>*this = s*(*this)+V</tt>.
+ * Scaling and simple vector addition, i.e. <tt>*this = s*(*this)+V</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void sadd (const Number s,
const Vector<Number> &V);
/**
- * Scaling and simple addition, i.e.
- * <tt>*this = s*(*this)+a*V</tt>.
+ * Scaling and simple addition, i.e. <tt>*this = s*(*this)+a*V</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void sadd (const Number s,
const Number a,
/**
* Scaling and multiple addition.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void sadd (const Number s,
const Number a,
const Vector<Number> &W);
/**
- * Scaling and multiple addition.
- * <tt>*this = s*(*this)+a*V + b*W + c*X</tt>.
+ * Scaling and multiple addition. <tt>*this = s*(*this)+a*V + b*W +
+ * c*X</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void sadd (const Number s,
const Number a,
const Vector<Number> &X);
/**
- * Scale each element of the
- * vector by the given factor.
+ * Scale each element of the vector by the given factor.
*
- * @deprecated This function is deprecated
- * and will be removed in a
- * future version. Use
- * <tt>operator *=</tt> and
- * <tt>operator /=</tt> instead.
+ * @deprecated This function is deprecated and will be removed in a future
+ * version. Use <tt>operator *=</tt> and <tt>operator /=</tt> instead.
*/
void scale (const Number factor) DEAL_II_DEPRECATED
{
/**
- * Scale each element of the
- * vector by a constant
- * value.
+ * Scale each element of the vector by a constant value.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator *= (const Number factor);
/**
- * Scale each element of the
- * vector by the inverse of the
- * given value.
+ * Scale each element of the vector by the inverse of the given value.
+ *
+ * @dealiiOperationIsMultithreaded
*/
Vector<Number> &operator /= (const Number factor);
/**
- * Scale each element of this
- * vector by the corresponding
- * element in the argument. This
- * function is mostly meant to
- * simulate multiplication (and
- * immediate re-assignment) by a
- * diagonal scaling matrix.
+ * Scale each element of this vector by the corresponding element in the
+ * argument. This function is mostly meant to simulate multiplication (and
+ * immediate re-assignment) by a diagonal scaling matrix.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void scale (const Vector<Number> &scaling_factors);
/**
- * Scale each element of this
- * vector by the corresponding
- * element in the argument. This
- * function is mostly meant to
- * simulate multiplication (and
- * immediate re-assignment) by a
- * diagonal scaling matrix.
+ * Scale each element of this vector by the corresponding element in the
+ * argument. This function is mostly meant to simulate multiplication (and
+ * immediate re-assignment) by a diagonal scaling matrix.
*/
template <typename Number2>
void scale (const Vector<Number2> &scaling_factors);
/**
* Assignment <tt>*this = a*u</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void equ (const Number a, const Vector<Number> &u);
/**
* Assignment <tt>*this = a*u + b*v</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void equ (const Number a, const Vector<Number> &u,
const Number b, const Vector<Number> &v);
/**
* Assignment <tt>*this = a*u + b*v + b*w</tt>.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void equ (const Number a, const Vector<Number> &u,
const Number b, const Vector<Number> &v,
const Number c, const Vector<Number> &w);
/**
- * Compute the elementwise ratio of the
- * two given vectors, that is let
- * <tt>this[i] = a[i]/b[i]</tt>. This is
- * useful for example if you want to
- * compute the cellwise ratio of true to
- * estimated error.
+ * Compute the elementwise ratio of the two given vectors, that is let
+ * <tt>this[i] = a[i]/b[i]</tt>. This is useful for example if you want to
+ * compute the cellwise ratio of true to estimated error.
*
- * This vector is appropriately
- * scaled to hold the result.
+ * This vector is appropriately scaled to hold the result.
*
- * If any of the <tt>b[i]</tt> is
- * zero, the result is
- * undefined. No attempt is made
- * to catch such situations.
+ * If any of the <tt>b[i]</tt> is zero, the result is undefined. No attempt
+ * is made to catch such situations.
+ *
+ * @dealiiOperationIsMultithreaded
*/
void ratio (const Vector<Number> &a,
const Vector<Number> &b);
/**
- * This function does nothing but is
- * there for compatibility with the
- * @p PETScWrappers::Vector class.
+ * This function does nothing but is there for compatibility with the @p
+ * PETScWrappers::Vector class.
*
- * For the PETSc vector wrapper class,
- * this function updates the ghost
- * values of the PETSc vector. This
- * is necessary after any modification
+ * For the PETSc vector wrapper class, this function updates the ghost
+ * values of the PETSc vector. This is necessary after any modification
* before reading ghost values.
*
- * However, for the implementation of
- * this class, it is immaterial and thus
+ * However, for the implementation of this class, it is immaterial and thus
* an empty function.
*/
void update_ghost_values () const;
*/
//@{
/**
- * Output of vector in user-defined
- * format. For complex-valued vectors,
- * the format should include specifiers
- * for both the real and imaginary
- * parts.
+ * Output of vector in user-defined format. For complex-valued vectors, the
+ * format should include specifiers for both the real and imaginary parts.
*/
void print (const char *format = 0) const;
/**
- * Print to a
- * stream. @p precision denotes
- * the desired precision with
- * which values shall be printed,
- * @p scientific whether
- * scientific notation shall be
- * used. If @p across is
- * @p true then the vector is
- * printed in a line, while if
- * @p false then the elements
- * are printed on a separate line
- * each.
+ * Print to a stream. @p precision denotes the desired precision with which
+ * values shall be printed, @p scientific whether scientific notation shall
+ * be used. If @p across is @p true then the vector is printed in a line,
+ * while if @p false then the elements are printed on a separate line each.
*/
void print (std::ostream &out,
const unsigned int precision = 3,
const bool across = true) const;
/**
- * Print to a
- * LogStream. <tt>width</tt> is
- * used as argument to the
- * std::setw manipulator, if
- * printing across. If @p
- * across is @p true then the
- * vector is printed in a line,
- * while if @p false then the
- * elements are printed on a
- * separate line each.
+ * Print to a LogStream. <tt>width</tt> is used as argument to the std::setw
+ * manipulator, if printing across. If @p across is @p true then the vector
+ * is printed in a line, while if @p false then the elements are printed on
+ * a separate line each.
*/
void print (LogStream &out,
const unsigned int width = 6,
const bool across = true) const;
/**
- * Write the vector en bloc to a
- * file. This is done in a binary
- * mode, so the output is neither
- * readable by humans nor
- * (probably) by other computers
- * using a different operating
- * system or number format.
+ * Write the vector en bloc to a file. This is done in a binary mode, so the
+ * output is neither readable by humans nor (probably) by other computers
+ * using a different operating system or number format.
*/
void block_write (std::ostream &out) const;
/**
- * Read a vector en block from a
- * file. This is done using the
- * inverse operations to the
- * above function, so it is
- * reasonably fast because the
+ * Read a vector en block from a file. This is done using the inverse
+ * operations to the above function, so it is reasonably fast because the
* bitstream is not interpreted.
*
- * The vector is resized if
- * necessary.
+ * The vector is resized if necessary.
*
- * A primitive form of error
- * checking is performed which
- * will recognize the bluntest
- * attempts to interpret some
- * data as a vector stored
- * bitwise to a file, but not
- * more.
+ * A primitive form of error checking is performed which will recognize the
+ * bluntest attempts to interpret some data as a vector stored bitwise to a
+ * file, but not more.
*/
void block_read (std::istream &in);
/**
- * Determine an estimate for the
- * memory consumption (in bytes)
- * of this object.
+ * Determine an estimate for the memory consumption (in bytes) of this
+ * object.
*/
std::size_t memory_consumption () const;
//@}
/**
- * Write the data of this object to
- * a stream for the purpose of serialization.
+ * Write the data of this object to a stream for the purpose of
+ * serialization.
*/
template <class Archive>
void save (Archive &ar, const unsigned int version) const;
/**
- * Read the data of this object
- * from a stream for the purpose of serialization.
+ * Read the data of this object from a stream for the purpose of
+ * serialization.
*/
template <class Archive>
void load (Archive &ar, const unsigned int version);
protected:
/**
- * Dimension. Actual number of
- * components contained in the
- * vector. Get this number by
- * calling <tt>size()</tt>.
+ * Dimension. Actual number of components contained in the vector. Get this
+ * number by calling <tt>size()</tt>.
*/
size_type vec_size;
/**
- * Amount of memory actually
- * reserved for this vector. This
- * number may be greater than
- * @p vec_size if a @p reinit was
- * called with less memory
- * requirements than the vector
- * needed last time. At present
- * @p reinit does not free
- * memory when the number of
- * needed elements is reduced.
+ * Amount of memory actually reserved for this vector. This number may be
+ * greater than @p vec_size if a @p reinit was called with less memory
+ * requirements than the vector needed last time. At present @p reinit does
+ * not free memory when the number of needed elements is reduced.
*/
size_type max_vec_size;
/**
- * Pointer to the array of
- * elements of this vector.
+ * Pointer to the array of elements of this vector.
*/
Number *val;
/**
- * Make all other vector types
- * friends.
+ * Make all other vector types friends.
*/
template <typename Number2> friend class Vector;
/**
- * LAPACK matrices need access to
- * the data.
+ * LAPACK matrices need access to the data.
*/
friend class LAPACKFullMatrix<Number>;
/**
- * VectorView will access the
- * pointer.
+ * VectorView will access the pointer.
*/
friend class VectorView<Number>;
};
max_vec_size (0),
val (0)
{
- // allocate memory. do not
- // initialize it, as we will copy
- // over to it in a second
+ // allocate memory. do not initialize it, as we will copy over to it in a
+ // second
reinit (std::distance (first, last), true);
std::copy (first, last, begin());
}
void
Vector<Number>::save (Archive &ar, const unsigned int) const
{
- // forward to serialization
- // function in the base class.
+ // forward to serialization function in the base class.
ar &static_cast<const Subscriptor &>(*this);
ar &vec_size &max_vec_size ;
void
Vector<Number>::load (Archive &ar, const unsigned int)
{
- // forward to serialization
- // function in the base class.
+ // forward to serialization function in the base class.
ar &static_cast<Subscriptor &>(*this);
ar &vec_size &max_vec_size ;
#include <deal.II/base/numbers.h>
#include <deal.II/base/parallel.h>
#include <deal.II/base/thread_management.h>
+#include <deal.II/base/multithread_info.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/block_vector.h>
const Number2 *Y,
const ResultType power,
const size_type vec_size,
- ResultType &result)
+ ResultType &result,
+ const int depth = -1)
{
if (vec_size <= 4096)
{
result = outer_results[0];
}
#ifdef DEAL_II_WITH_THREADS
- else if (vec_size > 4 * internal::Vector::minimum_parallel_grain_size)
+ else if (multithread_info.n_threads() > 1 &&
+ vec_size > 4 * internal::Vector::minimum_parallel_grain_size &&
+ depth != 0)
{
- // split the vector into smaller pieces to be
- // worked on recursively and create tasks for
- // them. Make pieces divisible by 1024.
+ // split the vector into smaller pieces to be worked on recursively
+ // and create tasks for them. Make pieces divisible by 1024.
const size_type new_size = (vec_size / 4096) * 1024;
ResultType r0, r1, r2, r3;
+
+ // find out how many recursions we should make (avoid too deep
+ // hierarchies of tasks on large vectors), max use 8 *
+ // multithread_info.n_threads()
+ int next_depth = depth;
+ if (depth == -1)
+ next_depth = 8 * multithread_info.n_threads();
+ next_depth /= 4;
+
Threads::TaskGroup<> task_group;
task_group += Threads::new_task(&accumulate<Operation,Number,Number2,
ResultType,size_type>,
- op, X, Y, power, new_size, r0);
+ op, X, Y, power, new_size, r0, next_depth);
task_group += Threads::new_task(&accumulate<Operation,Number,Number2,
ResultType,size_type>,
op, X+new_size, Y+new_size, power,
- new_size, r1);
+ new_size, r1, next_depth);
task_group += Threads::new_task(&accumulate<Operation,Number,Number2,
ResultType,size_type>,
op, X+2*new_size, Y+2*new_size, power,
- new_size, r2);
+ new_size, r2, next_depth);
task_group += Threads::new_task(&accumulate<Operation,Number,Number2,
ResultType,size_type>,
op, X+3*new_size, Y+3*new_size, power,
- vec_size-3*new_size, r3);
+ vec_size-3*new_size, r3, next_depth);
task_group.join_all();
r0 += r1;
r2 += r3;
// set up partitions. if we just use coloring without partitions, do
// nothing here, assume all cells to belong to the zero partition (that
// we otherwise use for MPI boundary cells)
- unsigned int partition = 0, start_up = 0, counter = 0;
- unsigned int start_nonboundary = numbers::invalid_unsigned_int;
- bool work = true;
+ unsigned int start_up = 0,
+ start_nonboundary = numbers::invalid_unsigned_int;
if (task_info.use_coloring_only == false)
{
start_nonboundary =
true, connectivity);
// Create cell-block partitioning.
+ unsigned int partition = 0, counter = 0;
+ bool work = true;
// For each block of cells, this variable saves to which partitions the
// block belongs. Initialize all to n_macro_cells to mark them as not
}
#endif
AssertDimension(counter,size_info.n_active_cells);
- task_info.evens = (partition+1)>>1;
- task_info.odds = (partition)>>1;
+ task_info.evens = (partition+1)/2;
+ task_info.odds = (partition)/2;
task_info.n_blocked_workers = task_info.odds-
(task_info.odds+task_info.evens+1)%2;
task_info.n_workers = task_info.partition_color_blocks_data.size()-1-
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/template_constraints.h>
#include <deal.II/base/symmetric_tensor.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/smartpointer.h>
#include <deal.II/matrix_free/matrix_free.h>
+#include <deal.II/matrix_free/shape_info.h>
+#include <deal.II/matrix_free/mapping_fe_evaluation.h>
DEAL_II_NAMESPACE_OPEN
+// forward declarations
namespace internal
{
DeclException0 (ExcAccessToUninitializedField);
-
- template <typename FEEval>
- void do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval>
- void do_integrate (FEEval &, const bool, const bool);
}
/**
* This is the base class for the FEEvaluation classes. This class is a base
- * class and needs usually not be called in user code. Use one of the derived
- * classes FEEvaluationGeneral, FEEvaluation or FEEvaluationGL instead. It
+ * class and needs usually not be called in user code. It does not have any
+ * public constructor. The usage is through the class FEEvaluation instead. It
* implements a reinit method that is used to set pointers so that operations
* on quadrature points can be performed quickly, access functions to vectors
* for the @p read_dof_values, @p set_dof_values, and @p
* distributed_local_to_global functions, as well as methods to access values
* and gradients of finite element functions.
*
- * This class has five template arguments:
+ * This class has three template arguments:
*
* @param dim Dimension in which this class is to be used
*
- * @param dofs_per_cell Number of degrees of freedom of the FE per cell,
- * usually (fe_degree+1)^dim for elements based on a tensor
- * product
- *
- * @param n_q_points Number of points in the quadrature formula, usually
- * (fe_degree+1)^dim for tensor-product quadrature formulas
- *
* @param n_components Number of vector components when solving a system of
* PDEs. If the same operation is applied to several
* components of a PDE (e.g. a vector Laplace equation), they
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
class FEEvaluationBase
{
public:
typedef Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
/**
* @name 1: General operations
*/
internal::MatrixFreeFunctions::CellType get_cell_type() const;
+ /**
+ * Returns a reference to the ShapeInfo object currently in use.
+ */
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+ get_shape_info() const;
+
+ /**
+ * Fills the JxW values currently used.
+ */
+ void
+ fill_JxW_values(AlignedVector<VectorizedArray<Number> > &JxW_values) const;
+
//@}
/**
* ConstraintMatrix::distribute. When accessing vector entries during the
* solution of linear systems, the temporary solution should always have
* homogeneous constraints and this method is the correct one.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on).
*/
template <typename VectorType>
void read_dof_values (const VectorType &src);
* function is also necessary when inhomogeneous constraints are to be used,
* as MatrixFree can only handle homogeneous constraints. Note that if
* vectorization is enabled, the DoF values for several cells are set.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template <typename VectorType>
void read_dof_values_plain (const VectorType &src);
* Takes the values stored internally on dof values of the current cell and
* sums them into the vector @p dst. The function also applies constraints
* during the write operation. The functionality is hence similar to the
- * function ConstraintMatrix::distribute_local_to_global. Note that if
- * vectorization is enabled, the DoF values for several cells are used.
+ * function ConstraintMatrix::distribute_local_to_global. If vectorization
+ * is enabled, the DoF values for several cells are used.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template<typename VectorType>
void distribute_local_to_global (VectorType &dst) const;
* and sums them into the collection of vectors vector @p dst, starting at
* index @p first_index. The function also applies constraints during the
* write operation. The functionality is hence similar to the function
- * ConstraintMatrix::distribute_local_to_global. Note that if vectorization
- * is enabled, the DoF values for several cells are used.
+ * ConstraintMatrix::distribute_local_to_global. If vectorization is
+ * enabled, the DoF values for several cells are used.
*/
template<typename VectorType>
void distribute_local_to_global (std::vector<VectorType> &dst,
* during the write operation. The functionality is hence similar to the
* function ConstraintMatrix::distribute_local_to_global. Note that if
* vectorization is enabled, the DoF values for several cells are used.
+ *
+ * If the class was constructed through a MappingFEEvaluation object, only
+ * one single cell is used by this class and this function extracts the
+ * values of the underlying components on this cell. This call is slower
+ * than the ones done through a MatrixFree object and lead to a structure
+ * that does not effectively use vectorization in the evaluate routines
+ * based on these values (instead, VectorizedArray<Number>::n_array_elements
+ * same copies are worked on). In that case, no constraints can be
+ * processed as these are not available here.
*/
template<typename VectorType>
void set_dof_values (VectorType &dst) const;
* select the appropriate components.
*/
FEEvaluationBase (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluationBase (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationBase (const FEEvaluationBase &other);
/**
* A unified function to read from and write into vectors based on the given
void read_dof_values_plain (const VectorType *src_data[]);
/**
- * Internal data fields that store the values. Since all array lengths are
- * known at compile time and since they are rarely more than a few
- * kilobytes, allocate them on the stack. This makes it possible to cheaply
- * set up a FEEvaluation object and write thread-safe programs by letting
- * each thread own a private object of this type.
+ * Internal data fields that store the values. Derived classes will know the
+ * length of all arrays at compile time and allocate the memory on the
+ * stack. This makes it possible to cheaply set up a FEEvaluation object and
+ * write thread-safe programs by letting each thread own a private object of
+ * this type. In this base class, only pointers to the actual data are
+ * stored.
*
* This field stores the values for local degrees of freedom (e.g. after
* reading out from a vector but before applying unit cell transformations
* or before distributing them into a result vector). The methods
* get_dof_value() and submit_dof_value() read from or write to this field.
*/
- VectorizedArray<Number> values_dofs[n_components][dofs_per_cell>0?dofs_per_cell:1];
+ VectorizedArray<Number>* values_dofs[n_components];
/**
* This field stores the values of the finite element function on quadrature
* integrating. The methods get_value() and submit_value() access this
* field.
*/
- VectorizedArray<Number> values_quad[n_components][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* values_quad[n_components];
/**
* This field stores the gradients of the finite element function on
* some specializations like get_symmetric_gradient() or get_divergence())
* access this field.
*/
- VectorizedArray<Number> gradients_quad[n_components][dim][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* gradients_quad[n_components][dim];
/**
* This field stores the Hessians of the finite element function on
* quadrature points after applying unit cell transformations. The methods
* get_hessian(), get_laplacian(), get_hessian_diagonal() access this field.
*/
- VectorizedArray<Number> hessians_quad[n_components][(dim*(dim+1))/2][n_q_points>0?n_q_points:1];
+ VectorizedArray<Number>* hessians_quad[n_components][(dim*(dim+1))/2];
/**
* Stores the number of the quadrature formula of the present cell.
const unsigned int active_quad_index;
/**
- * Stores a reference to the underlying data.
+ * Stores a pointer to the underlying data.
*/
- const MatrixFree<dim,Number> &matrix_info;
+ const MatrixFree<dim,Number> *matrix_info;
/**
- * Stores a reference to the underlying DoF indices and constraint
+ * Stores a pointer to the underlying DoF indices and constraint
* description for the component specified at construction. Also contained
* in matrix_info, but it simplifies code if we store a reference to it.
*/
- const internal::MatrixFreeFunctions::DoFInfo &dof_info;
+ const internal::MatrixFreeFunctions::DoFInfo *dof_info;
/**
- * Stores a reference to the underlying transformation data from unit to
+ * Stores a pointer to the underlying transformation data from unit to
* real cells for the given quadrature formula specified at construction.
* Also contained in matrix_info, but it simplifies code if we store a
* reference to it.
*/
- const internal::MatrixFreeFunctions::MappingInfo<dim,Number> &mapping_info;
+ const internal::MatrixFreeFunctions::MappingInfo<dim,Number> *mapping_info;
+
+ /**
+ * In case the class is initialized from MappingFEEvaluation instead of
+ * MatrixFree, this data structure holds the evaluated shape data.
+ */
+ std_cxx1x::shared_ptr<internal::MatrixFreeFunctions::ShapeInfo<Number> > stored_shape_info;
/**
- * Stores a reference to the unit cell data, i.e., values, gradients and
+ * Stores a pointer to the unit cell shape data, i.e., values, gradients and
* Hessians in 1D at the quadrature points that constitute the tensor
* product. Also contained in matrix_info, but it simplifies code if we
* store a reference to it.
*/
- const internal::MatrixFreeFunctions::ShapeInfo<Number> &data;
+ const internal::MatrixFreeFunctions::ShapeInfo<Number> *data;
/**
* A pointer to the Cartesian Jacobian information of the present cell. Only
* stared. Used to control exceptions when uninitialized data is used.
*/
bool gradients_quad_submitted;
+
+ /**
+ * Geometry data generated by FEValues on the fly.
+ */
+ SmartPointer<const MappingFEEvaluation<dim,Number> > mapped_geometry;
+
+ /**
+ * A pointer to the underlying DoFHandler.
+ */
+ const DoFHandler<dim> *dof_handler;
+
+ /**
+ * For a DoFHandler with more than one finite element, select at which
+ * component this data structure should start.
+ */
+ const unsigned int first_selected_component;
+
+ /**
+ * A temporary data structure necessary to read degrees of freedom when no
+ * MatrixFree object was given at initialization.
+ */
+ mutable std::vector<types::global_dof_index> local_dof_indices;
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
-class FEEvaluationAccess :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+template <int dim, int n_components_, typename Number>
+class FEEvaluationAccess : public FEEvaluationBase<dim,n_components_,Number>
{
public:
typedef Number number_type;
typedef Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,
- Number> BaseClass;
+ typedef FEEvaluationBase<dim,n_components_, Number> BaseClass;
protected:
/**
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
-class FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number> :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number>
+template <int dim, typename Number>
+class FEEvaluationAccess<dim,1,Number> : public FEEvaluationBase<dim,1,Number>
{
public:
typedef Number number_type;
typedef VectorizedArray<Number> value_type;
typedef Tensor<1,dim,VectorizedArray<Number> > gradient_type;
static const unsigned int dimension = dim;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,1,Number> BaseClass;
+ typedef FEEvaluationBase<dim,1,Number> BaseClass;
/**
* Returns the value stored for the local degree of freedom with index @p
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
*
* @author Katharina Kormann and Martin Kronbichler, 2010, 2011
*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
-class FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number> :
- public FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number>
+template <int dim, typename Number>
+class FEEvaluationAccess<dim,dim,Number> : public FEEvaluationBase<dim,dim,Number>
{
public:
typedef Number number_type;
typedef Tensor<2,dim,VectorizedArray<Number> > gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = dim;
- static const unsigned int dofs_per_cell = dofs_per_cell_;
- static const unsigned int n_q_points = n_q_points_;
- typedef FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,dim,Number> BaseClass;
+ typedef FEEvaluationBase<dim,dim,Number> BaseClass;
/**
* Returns the gradient of a finite element function at quadrature point
* the appropriate components.
*/
FEEvaluationAccess (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int fe_no,
+ const unsigned int quad_no,
+ const unsigned int dofs_per_cell,
+ const unsigned int n_q_points);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ * With this initialization, no call to a reinit method of this
+ * class. Instead, it is enough if the geometry is initialized to a given
+ * cell iterator. Moreover, beware that a kernel using this method does not
+ * vectorize over several elements (which is most efficient for vector
+ * operations), but only possibly within the element if the
+ * evaluate/integrate routines are combined (e.g. for matrix assembly).
+ */
+ FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluationAccess (const FEEvaluationAccess &other);
};
* The class that provides all functions necessary to evaluate functions at
* quadrature points and cell integrations. In functionality, this class is
* similar to FEValues<dim>, however, it includes a lot of specialized
- * functions that make it much faster (between 5 and 500 times as fast,
- * depending on the polynomial order). Access to the data fields is provided
- * through functionality in the class FEEvaluationAccess.
+ * functions that make it much faster (between 5 and 500, depending on the
+ * polynomial order).
+ *
+ * This class can be used in two different ways. The first way is to
+ * initialize it from a MatrixFree object that caches everything related to
+ * the degrees of freedom and the mapping information. This way, it is
+ * possible to use vectorization for applying a vector operation for several
+ * cells at once. The second form of usage is to initialize it from geometry
+ * information generated by FEValues, which is stored in the class
+ * MappingFEEvaluation. Here, the operations can only work on a single cell, but
+ * possibly be vectorized by combining several operations (e.g. when
+ * performing matrix assembly).
*
- * This class is designed for general local finite element operations based on
- * tensor products of 1D polynomials and quadrature points. Often, there are
- * some symmetries or zeros in the unit cell data that allow for a more
- * efficient operator application. FEEvaluation is specialized to standard
- * FE_Q/FE_DGQ elements and quadrature points symmetric around 0.5 (like Gauss
- * quadrature), and hence the most common situation. FEEvaluationGL is a
- * specialization for elements where quadrature formula and support points are
- * chosen so that a orthogonal relation between the values holds. This is the
- * case for FE_Q based on Gauss-Lobatto support points with Gauss-Lobatto
- * quadrature formula of the same order.
+ * This class contains specialized evaluation routines for several elements,
+ * including standard FE_Q or FE_DGQ elements and quadrature points symmetric
+ * around 0.5 (like Gauss quadrature), FE_DGP elements based on truncated
+ * tensor products as well as the faster case of Gauss-Lobatto elements with
+ * Gauss-Lobatto quadrature which give diagonal mass matrices and quicker
+ * evaluation internally. Note that many of the operations available through
+ * this class are inherited from the base class FEEvaluationBase, in
+ * particular reading from and writing to vectors. Also, the class inherits
+ * from FEEvaluationAccess that implements access to values, gradients and
+ * Hessians of the finite element function on quadrature points.
+ *
+ * This class assumes that shape functions of the FiniteElement under
+ * consideration do <em>not</em> depend on the actual shape of the cells in
+ * real space. Currently, other finite elements cannot be treated with the
+ * matrix-free concept.
*
* This class has five template arguments:
*
* fe_degree+1 degrees of freedom per coordinate direction
*
* @param n_q_points_1d Number of points in the quadrature formula in 1D,
- * usually chosen as fe_degree+1
+ * usually chosen as fe_degree+1
*
* @param n_components Number of vector components when solving a system of
* PDEs. If the same operation is applied to several
*/
template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
int n_components_ = 1, typename Number = double >
-class FEEvaluationGeneral :
- public FEEvaluationAccess<dim,
- Utilities::fixed_int_power<fe_degree+1,dim>::value,
- Utilities::fixed_int_power<n_q_points_1d,dim>::value,
- n_components_,Number>
+class FEEvaluation : public FEEvaluationAccess<dim,n_components_,Number>
{
public:
- typedef FEEvaluationAccess<dim,
- Utilities::fixed_int_power<fe_degree+1,dim>::value,
- Utilities::fixed_int_power<n_q_points_1d,dim>::value,
- n_components_, Number> BaseClass;
+ typedef FEEvaluationAccess<dim,n_components_,Number> BaseClass;
typedef Number number_type;
typedef typename BaseClass::value_type value_type;
typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
- static const unsigned int n_q_points = BaseClass::n_q_points;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
+ static const unsigned int tensor_dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
/**
* Constructor. Takes all data stored in MatrixFree. If applied to problems
* selected during construction of @p matrix_free, @p fe_no and @p quad_no
* allow to select the appropriate components.
*/
- FEEvaluationGeneral (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ FEEvaluation (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0);
+
+ /**
+ * Copy constructor
+ */
+ FEEvaluation (const FEEvaluation &other);
+
+ /**
+ * Constructor that comes with reduced functionality and works similar as
+ * FEValues. The user has to provide a structure of type MappingFEEvaluation
+ * and a DoFHandler in order to allow for reading out the finite element
+ * data. It uses the data provided by dof_handler.get_fe(). If the element
+ * is vector-valued, the optional argument allows to specify the index of
+ * the base element (as long as the element is primitive, non-primitive are
+ * not supported currently).
+ *
+ * With initialization from a FEValues object, no call to a reinit method of
+ * this class is necessary. Instead, it is enough if the geometry is
+ * initialized to a given cell iterator. It can also read from or write to
+ * vectors in the standard way for DoFHandler<dim>::active_cell_iterator
+ * types (which is less efficient with MPI since index translation has to be
+ * done), but of course only for one cell at a time. Hence, a kernel using
+ * this method does not vectorize over several elements (which is most
+ * efficient for vector operations), but only possibly within the element if
+ * the evaluate/integrate routines are combined (e.g. for computing cell
+ * matrices).
+ */
+ FEEvaluation (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0);
/**
* Evaluates the function values, the gradients, and the Laplacians of the
* FE function given at the DoF values in the input vector at the quadrature
- * points. The function arguments specify which parts shall actually be
- * computed. Needs to be called before the functions @p get_value(), @p
- * get_gradient() or @p get_laplacian return useful information.
+ * points on the unit cell. The function arguments specify which parts
+ * shall actually be computed. Needs to be called before the functions @p
+ * get_value(), @p get_gradient() or @p get_laplacian give useful
+ * information (unless these values have been set manually).
*/
void evaluate (const bool evaluate_val,
const bool evaluate_grad,
Point<dim,VectorizedArray<Number> >
quadrature_point (const unsigned int q_point) const;
-protected:
+ /**
+ * The number of scalar degrees of freedom on the cell. Usually close to
+ * tensor_dofs_per_cell, but depends on the actual element selected and is
+ * thus not static.
+ */
+ const unsigned int dofs_per_cell;
+private:
/**
- * Internal function that applies the function values of the tensor product
- * in a given coordinate direction (first template argument), from
- * polynomials to values on quadrature points (second flag set to true) or
- * in an integration loop from values on quadrature points to values tested
- * by different test function (second flag set to false), and if the result
- * is to be added to previous content in the data fields or not.
+ * Internally stored variables for the different data fields.
*/
- template <int direction, bool dof_to_quad, bool add>
- void apply_values (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
+ VectorizedArray<Number> my_data_array[n_components*(tensor_dofs_per_cell+1+(dim*dim+2*dim+1)*n_q_points)];
/**
- * Internal function that applies the gradient operation of the tensor
- * product in a given coordinate direction (first template argument), from
- * polynomials to values on quadrature points (second flag set to true) or
- * in an integration loop from values on quadrature points to values tested
- * by different test function (second flag set to false), and if the result
- * is to be added to previous content in the data fields or not.
+ * Checks if the template arguments regarding degree of the element
+ * corresponds to the actual element used at initialization.
*/
- template <int direction, bool dof_to_quad, bool add>
- void apply_gradients (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
+ void check_template_arguments(const unsigned int fe_no);
/**
- * Internal function that applies the second derivative operation (Hessian)
- * of the tensor product in a given coordinate direction (first template
- * argument), from polynomials to values on quadrature points (second flag
- * set to true) or in an integration loop from values on quadrature points
- * to values tested by different test function (second flag set to false),
- * and if the result is to be added to previous content in the data fields
- * or not.
+ * Sets the pointers of the base class to my_data_array.
*/
- template <int direction, bool dof_to_quad, bool add>
- void apply_hessians (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
+ void set_data_pointers();
+
+ /**
+ * Function pointer for the evaluate function
+ */
+ void (*evaluate_funct) (const internal::MatrixFreeFunctions::ShapeInfo<Number> &,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl);
/**
- * Friend declaration.
+ * Function pointer for the integrate function
*/
- template <typename FEEval> friend void
- internal::do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval> friend void
- internal::do_integrate (FEEval &, const bool, const bool);
+ void (*integrate_funct)(const internal::MatrixFreeFunctions::ShapeInfo<Number> &,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ const bool evaluate_val,
+ const bool evaluate_grad);
};
/**
- * The class that provides all functions necessary to evaluate functions at
- * quadrature points and cell integrations. In functionality, this class is
- * similar to FEValues<dim>, however, it includes a lot of specialized
- * functions that make it much faster (between 5 and 500, depending on the
- * polynomial order).
- *
- * This class is a specialization of FEEvaluationGeneral designed for standard
- * FE_Q or FE_DGQ elements and quadrature points symmetric around 0.5 (like
- * Gauss quadrature), and hence the most common situation. Note that many of
- * the operations available through this class are inherited from the base
- * class FEEvaluationBase, in particular reading from and writing to
- * vectors. Also, the class inherits from FEEvaluationAccess that implements
- * access to values, gradients and Hessians of the finite element function on
- * quadrature points.
- *
- * This class assumes that shape functions of the FiniteElement under
- * consideration do <em>not</em> depend on the actual shape of the cells in
- * real space. Currently, other finite elements cannot be treated with the
- * matrix-free concept.
- *
- * This class has five template arguments:
- *
- * @param dim Dimension in which this class is to be used
- *
- * @param fe_degree Degree of the tensor product finite element with
- * fe_degree+1 degrees of freedom per coordinate direction
- *
- * @param n_q_points_1d Number of points in the quadrature formula in 1D,
- * usually chosen as fe_degree+1
- *
- * @param n_components Number of vector components when solving a system of
- * PDEs. If the same operation is applied to several
- * components of a PDE (e.g. a vector Laplace equation), they
- * can be applied simultaneously with one call (and often
- * more efficiently)
- *
- * @param Number Number format, usually @p double or @p float
- *
- * @author Katharina Kormann and Martin Kronbichler, 2010, 2011
+ * Deprecated. Functionality has been merged into FEEvaluation. Use class
+ * FEEvaluation instead.
*/
template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
int n_components_ = 1, typename Number = double >
-class FEEvaluation :
- public FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
+class FEEvaluationGeneral : public FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_,Number>
{
public:
- typedef FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number> BaseClass;
+ typedef FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number> BaseClass;
typedef Number number_type;
typedef typename BaseClass::value_type value_type;
typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
- static const unsigned int n_q_points = BaseClass::n_q_points;
-
- /**
- * Constructor. Takes all data stored in MatrixFree. If applied to problems
- * with more than one finite element or more than one quadrature formula
- * selected during construction of @p matrix_free, @p fe_no and @p quad_no
- * allow to select the appropriate components.
- */
- FEEvaluation (const MatrixFree<dim,Number> &matrix_free,
- const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
-
- /**
- * Evaluates the function values, the gradients, and the Laplacians of the
- * FE function given at the DoF values in the input vector at the quadrature
- * points on the unit cell. The function arguments specify which parts
- * shall actually be computed. Needs to be called before the functions @p
- * get_value(), @p get_gradient() or @p get_laplacian give useful
- * information (unless these values have been set manually).
- */
- void evaluate (const bool evaluate_val,
- const bool evaluate_grad,
- const bool evaluate_hess = false);
-
- /**
- * This function takes the values and/or gradients that are stored on
- * quadrature points, tests them by all the basis functions/gradients on the
- * cell and performs the cell integration. The two function arguments @p
- * integrate_val and @p integrate_grad are used to enable/disable some of
- * values or gradients.
- */
- void integrate (const bool integrate_val,
- const bool integrate_grad);
-
-protected:
-
- /**
- * Internal function that applies the function values of the tensor product
- * in a given coordinate direction (first template argument), from
- * polynomials to values on quadrature points (second flag set to true) or
- * in an integration loop from values on quadrature points to values tested
- * by different test function (second flag set to false), and if the result
- * is to be added to previous content in the data fields or not.
- */
- template <int direction, bool dof_to_quad, bool add>
- void apply_values (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
/**
- * Internal function that applies the gradient operation of the tensor
- * product in a given coordinate direction (first template argument), from
- * polynomials to values on quadrature points (second flag set to true) or
- * in an integration loop from values on quadrature points to values tested
- * by different test function (second flag set to false), and if the result
- * is to be added to previous content in the data fields or not.
+ * Constructor.
*/
- template <int direction, bool dof_to_quad, bool add>
- void apply_gradients (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
-
- /**
- * Internal function that applies the second derivative operation (Hessian)
- * of the tensor product in a given coordinate direction (first template
- * argument), from polynomials to values on quadrature points (second flag
- * set to true) or in an integration loop from values on quadrature points
- * to values tested by different test function (second flag set to false),
- * and if the result is to be added to previous content in the data fields
- * or not.
- */
- template <int direction, bool dof_to_quad, bool add>
- void apply_hessians (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
-
- VectorizedArray<Number> shape_val_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
- VectorizedArray<Number> shape_gra_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
- VectorizedArray<Number> shape_hes_evenodd[fe_degree+1][(n_q_points_1d+1)/2];
+ FEEvaluationGeneral (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (matrix_free, fe_no, quad_no)
+ {}
/**
- * Friend declarations.
+ * Constructor.
*/
- template <typename FEEval> friend void
- internal::do_evaluate (FEEval &, const bool, const bool, const bool);
- template <typename FEEval> friend void
- internal::do_integrate (FEEval &, const bool, const bool);
+ FEEvaluationGeneral (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+ {}
};
/**
- * The class that provides all functions necessary to evaluate functions at
- * quadrature points and cell integrations. In functionality, this class is
- * similar to FEValues<dim>, however, it includes a lot of specialized
- * functions that make it much faster (between 5 and 500, depending on the
- * polynomial order).
- *
- * This class is a specialization of FEEvaluation for elements where
- * quadrature formula and support points are chosen so that a orthonormal
- * relation between the values holds. This is the case for FE_Q based on
- * Gauss-Lobatto support points with Gauss-Lobatto quadrature formula of the
- * same order (QGaussLobatto). In that case, application of values is trivial
- * (as the transformation is the identity matrix), and application of
- * gradients is considerably simpler (since all value applications in
- * directions other than the gradient direction are again identity
- * operations).
- *
- * This class has four template arguments:
- *
- * @param dim Dimension in which this class is to be used
- *
- * @param fe_degree Degree of the tensor product finite element with
- * fe_degree+1 degrees of freedom per coordinate
- * direction. The quadrature formula is tied to the choice of
- * the element by setting n_q_points_1d = fe_degree+1, which
- * gives a diagonal mass matrix
- *
- * @param n_components Number of vector components when solving a system of
- * PDEs. If the same operation is applied to several
- * components of a PDE (e.g. a vector Laplace equation), they
- * can be applied simultaneously with one call (and often
- * more efficiently)
- *
- * @param Number Number format, usually @p double or @p float
- *
- * @author Katharina Kormann and Martin Kronbichler, 2010, 2011
+ * Deprecated. Functionality has been merged into FEEvaluation. Use class
+ * FEEvaluation instead.
*/
template <int dim, int fe_degree, int n_components_ = 1, typename Number = double >
class FEEvaluationGL :
typedef typename BaseClass::gradient_type gradient_type;
static const unsigned int dimension = dim;
static const unsigned int n_components = n_components_;
- static const unsigned int dofs_per_cell = BaseClass::dofs_per_cell;
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
static const unsigned int n_q_points = BaseClass::n_q_points;
/**
- * Constructor. Takes all data stored in MatrixFree. If applied to problems
- * with more than one finite element or more than one quadrature formula
- * selected during construction of @p matrix_free, @p fe_no and @p quad_no
- * allow to select the appropriate components.
+ * Constructor.
*/
FEEvaluationGL (const MatrixFree<dim,Number> &matrix_free,
const unsigned int fe_no = 0,
- const unsigned int quad_no = 0);
+ const unsigned int quad_no = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (matrix_free, fe_no, quad_no)
+ {}
/**
- * Evaluates the function values, the gradients, and the Hessians of the FE
- * function given at the DoF values in the input vector at the quadrature
- * points of the unit cell. The function arguments specify which parts shall
- * actually be computed. Needs to be called before the functions @p
- * get_value(), @p get_gradient() or @p get_laplacian give useful
- * information (unless these values have been set manually).
+ * Constructor.
*/
- void evaluate (const bool evaluate_val,
- const bool evaluate_grad,
- const bool evaluate_lapl = false);
+ FEEvaluationGL (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+ {}
+};
+
+
+
+namespace internal
+{
+ namespace MatrixFreeFunctions
+ {
+ // a helper function to compute the number of DoFs of a DGP element at compile
+ // time, depending on the degree
+ template <int dim, int degree>
+ struct DGP_dofs_per_cell
+ {
+ // this division is always without remainder
+ static const unsigned int value =
+ (DGP_dofs_per_cell<dim-1,degree>::value * (degree+dim)) / dim;
+ };
+
+ // base specialization: 1d elements have 'degree+1' degrees of freedom
+ template <int degree>
+ struct DGP_dofs_per_cell<1,degree>
+ {
+ static const unsigned int value = degree+1;
+ };
+ }
+}
+
+
+
+/**
+ * Functionality has been merged into FEEvaluation. Use class FEEvaluation
+ * instead.
+ */
+template <int dim, int fe_degree, int n_q_points_1d = fe_degree+1,
+ int n_components_ = 1, typename Number = double >
+class FEEvaluationDGP :
+ public FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
+{
+public:
+ typedef FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number> BaseClass;
+ typedef Number number_type;
+ typedef typename BaseClass::value_type value_type;
+ typedef typename BaseClass::gradient_type gradient_type;
+ static const unsigned int dimension = dim;
+ static const unsigned int n_components = n_components_;
+ static const unsigned int dofs_per_cell = internal::MatrixFreeFunctions::DGP_dofs_per_cell<dim,fe_degree>::value;
+ static const unsigned int n_q_points = BaseClass::n_q_points;
/**
- * This function takes the values and/or gradients that are stored on
- * quadrature points, tests them by all the basis functions/gradients on the
- * cell and performs the cell integration. The two function arguments @p
- * integrate_val and @p integrate_grad are used to enable/disable some of
- * values or gradients.
+ * Constructor.
*/
- void integrate (const bool integrate_val,
- const bool integrate_grad);
+ FEEvaluationDGP (const MatrixFree<dim,Number> &matrix_free,
+ const unsigned int fe_no = 0,
+ const unsigned int quad_no = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (matrix_free, fe_no, quad_no)
+ {}
-protected:
/**
- * Internal function that applies the gradient operation of the tensor
- * product in a given coordinate direction (first template argument), from
- * polynomials to values on quadrature points (second flag set to true) or
- * in an integration loop from values on quadrature points to values tested
- * by different test function (second flag set to false), and if the result
- * is to be added to some previous results or not.
+ * Constructor.
*/
- template <int direction, bool dof_to_quad, bool add>
- void apply_gradients (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out []);
+ FEEvaluationDGP (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component = 0) DEAL_II_DEPRECATED
+ :
+ BaseClass (geometry, dof_handler, first_selected_component)
+ {}
};
-
/*----------------------- Inline functions ----------------------------------*/
#ifndef DOXYGEN
+
/*----------------------- FEEvaluationBase ----------------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::FEEvaluationBase (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no_in,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points)
:
quad_no (quad_no_in),
n_fe_components (data_in.get_dof_info(fe_no_in).n_components),
- active_fe_index (data_in.get_dof_info(fe_no_in).fe_index_from_dofs_per_cell
- (dofs_per_cell_ * n_fe_components)),
+ active_fe_index (data_in.get_dof_info(fe_no_in).fe_index_from_degree
+ (fe_degree)),
active_quad_index (data_in.get_mapping_info().
mapping_data_gen[quad_no_in].
- quad_index_from_n_q_points(n_q_points_)),
- matrix_info (data_in),
- dof_info (data_in.get_dof_info(fe_no_in)),
- mapping_info (data_in.get_mapping_info()),
- data (data_in.get_shape_info
+ quad_index_from_n_q_points(n_q_points)),
+ matrix_info (&data_in),
+ dof_info (&data_in.get_dof_info(fe_no_in)),
+ mapping_info (&data_in.get_mapping_info()),
+ data (&data_in.get_shape_info
(fe_no_in, quad_no_in, active_fe_index,
active_quad_index)),
cartesian_data (0),
jacobian (0),
J_value (0),
- quadrature_weights (mapping_info.mapping_data_gen[quad_no].
+ quadrature_weights (mapping_info->mapping_data_gen[quad_no].
quadrature_weights[active_quad_index].begin()),
quadrature_points (0),
jacobian_grad (0),
jacobian_grad_upper(0),
cell (numbers::invalid_unsigned_int),
cell_type (internal::MatrixFreeFunctions::undefined),
- cell_data_number (0)
+ cell_data_number (0),
+ dof_handler (0),
+ first_selected_component (0)
{
- Assert (matrix_info.mapping_initialized() == true,
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+ Assert (matrix_info->mapping_initialized() == true,
ExcNotInitialized());
- AssertDimension (matrix_info.get_size_info().vectorization_length,
+ AssertDimension (matrix_info->get_size_info().vectorization_length,
VectorizedArray<Number>::n_array_elements);
+ AssertDimension (data->dofs_per_cell,
+ dof_info->dofs_per_cell[active_fe_index]/n_fe_components);
+ AssertDimension (data->n_q_points,
+ mapping_info->mapping_data_gen[quad_no].n_q_points[active_quad_index]);
Assert (n_fe_components == 1 ||
n_components == 1 ||
n_components == n_fe_components,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
-void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
-::reinit (const unsigned int cell_in)
+FEEvaluationBase<dim,n_components_,Number>
+::FEEvaluationBase (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler_in,
+ const unsigned int first_selected_component)
+ :
+ quad_no (-1),
+ n_fe_components (n_components_),
+ active_fe_index (-1),
+ active_quad_index (-1),
+ matrix_info (0),
+ dof_info (0),
+ mapping_info (0),
+ stored_shape_info (new internal::MatrixFreeFunctions::ShapeInfo<Number>(geometry.get_quadrature(), dof_handler_in.get_fe(), dof_handler_in.get_fe().component_to_base_index(first_selected_component).first)),
+ data (stored_shape_info.get()),
+ cartesian_data (0),
+ jacobian (geometry.get_inverse_jacobians().begin()),
+ J_value (geometry.get_JxW_values().begin()),
+ quadrature_weights (0),
+ quadrature_points (geometry.get_quadrature_points().begin()),
+ jacobian_grad (0),
+ jacobian_grad_upper(0),
+ cell (0),
+ cell_type (internal::MatrixFreeFunctions::general),
+ cell_data_number (0),
+ mapped_geometry (&geometry),
+ dof_handler (&dof_handler_in),
+ first_selected_component (first_selected_component)
{
- AssertIndexRange (cell_in, dof_info.row_starts.size()-1);
- AssertDimension (((dof_info.cell_active_fe_index.size() > 0) ?
- dof_info.cell_active_fe_index[cell_in] : 0),
- active_fe_index);
- cell = cell_in;
- cell_type = mapping_info.get_cell_type(cell);
- cell_data_number = mapping_info.get_cell_data_index(cell);
-
- if (mapping_info.quadrature_points_initialized == true)
+ const unsigned int base_element_number =
+ dof_handler_in.get_fe().component_to_base_index(first_selected_component).first;
+ for (unsigned int c=0; c<n_components_; ++c)
{
- AssertIndexRange (cell_data_number, mapping_info.
- mapping_data_gen[quad_no].rowstart_q_points.size());
- const unsigned int index = mapping_info.mapping_data_gen[quad_no].
- rowstart_q_points[cell];
- AssertIndexRange (index, mapping_info.mapping_data_gen[quad_no].
- quadrature_points.size());
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+ Assert(dof_handler->get_fe().element_multiplicity(base_element_number) == 1 ||
+ dof_handler->get_fe().element_multiplicity(base_element_number)-first_selected_component >= n_components_,
+ ExcMessage("The underlying element must at least contain as many "
+ "components as requested by this class"));
+}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationBase<dim,n_components_,Number>
+::FEEvaluationBase (const FEEvaluationBase<dim,n_components_,Number> &other)
+ :
+ quad_no (other.quad_no),
+ n_fe_components (other.n_fe_components),
+ active_fe_index (other.active_fe_index),
+ active_quad_index (other.active_quad_index),
+ matrix_info (other.matrix_info),
+ dof_info (other.dof_info),
+ mapping_info (other.mapping_info),
+ stored_shape_info (other.stored_shape_info),
+ data (other.data),
+ cartesian_data (other.cartesian_data),
+ jacobian (other.jacobian),
+ J_value (other.J_value),
+ quadrature_weights (other.quadrature_weights),
+ quadrature_points (other.quadrature_points),
+ jacobian_grad (other.jacobian_grad),
+ jacobian_grad_upper(other.jacobian_grad_upper),
+ cell (other.cell),
+ cell_type (other.cell_type),
+ cell_data_number (other.cell_data_number),
+ mapped_geometry (other.mapped_geometry),
+ dof_handler (other.dof_handler),
+ first_selected_component (other.first_selected_component)
+{
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ values_dofs[c] = 0;
+ values_quad[c] = 0;
+ for (unsigned int d=0; d<dim; ++d)
+ gradients_quad[c][d] = 0;
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ hessians_quad[c][d] = 0;
+ }
+}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+void
+FEEvaluationBase<dim,n_components_,Number>::reinit (const unsigned int cell_in)
+{
+ Assert (mapped_geometry == 0, ExcMessage("FEEvaluation was initialized without a matrix-free object. Integer indexing is not possible"));
+ if (mapped_geometry != 0)
+ return;
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (mapping_info != 0, ExcNotInitialized());
+ AssertIndexRange (cell_in, dof_info->row_starts.size()-1);
+ AssertDimension (((dof_info->cell_active_fe_index.size() > 0) ?
+ dof_info->cell_active_fe_index[cell_in] : 0),
+ active_fe_index);
+ cell = cell_in;
+ cell_type = mapping_info->get_cell_type(cell);
+ cell_data_number = mapping_info->get_cell_data_index(cell);
+
+ if (mapping_info->quadrature_points_initialized == true)
+ {
+ AssertIndexRange (cell_data_number, mapping_info->
+ mapping_data_gen[quad_no].rowstart_q_points.size());
+ const unsigned int index = mapping_info->mapping_data_gen[quad_no].
+ rowstart_q_points[cell];
+ AssertIndexRange (index, mapping_info->mapping_data_gen[quad_no].
+ quadrature_points.size());
quadrature_points =
- &mapping_info.mapping_data_gen[quad_no].quadrature_points[index];
+ &mapping_info->mapping_data_gen[quad_no].quadrature_points[index];
}
if (cell_type == internal::MatrixFreeFunctions::cartesian)
{
- cartesian_data = &mapping_info.cartesian_data[cell_data_number].first;
- J_value = &mapping_info.cartesian_data[cell_data_number].second;
+ cartesian_data = &mapping_info->cartesian_data[cell_data_number].first;
+ J_value = &mapping_info->cartesian_data[cell_data_number].second;
}
else if (cell_type == internal::MatrixFreeFunctions::affine)
{
- jacobian = &mapping_info.affine_data[cell_data_number].first;
- J_value = &mapping_info.affine_data[cell_data_number].second;
+ jacobian = &mapping_info->affine_data[cell_data_number].first;
+ J_value = &mapping_info->affine_data[cell_data_number].second;
}
else
{
- const unsigned int rowstart = mapping_info.
+ const unsigned int rowstart = mapping_info->
mapping_data_gen[quad_no].rowstart_jacobians[cell_data_number];
- AssertIndexRange (rowstart, mapping_info.
+ AssertIndexRange (rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians.size());
jacobian =
- &mapping_info.mapping_data_gen[quad_no].jacobians[rowstart];
- if (mapping_info.JxW_values_initialized == true)
+ &mapping_info->mapping_data_gen[quad_no].jacobians[rowstart];
+ if (mapping_info->JxW_values_initialized == true)
{
- AssertIndexRange (rowstart, mapping_info.
+ AssertIndexRange (rowstart, mapping_info->
mapping_data_gen[quad_no].JxW_values.size());
- J_value = &(mapping_info.mapping_data_gen[quad_no].
+ J_value = &(mapping_info->mapping_data_gen[quad_no].
JxW_values[rowstart]);
}
- if (mapping_info.second_derivatives_initialized == true)
+ if (mapping_info->second_derivatives_initialized == true)
{
- AssertIndexRange(rowstart, mapping_info.
+ AssertIndexRange(rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians_grad_diag.size());
- jacobian_grad = &mapping_info.mapping_data_gen[quad_no].
+ jacobian_grad = &mapping_info->mapping_data_gen[quad_no].
jacobians_grad_diag[rowstart];
- AssertIndexRange(rowstart, mapping_info.
+ AssertIndexRange(rowstart, mapping_info->
mapping_data_gen[quad_no].jacobians_grad_upper.size());
- jacobian_grad_upper = &mapping_info.mapping_data_gen[quad_no].
+ jacobian_grad_upper = &mapping_info->mapping_data_gen[quad_no].
jacobians_grad_upper[rowstart];
}
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
unsigned int
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_cell_data_number () const
{
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
internal::MatrixFreeFunctions::CellType
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
-::get_cell_type () const
+FEEvaluationBase<dim,n_components_,Number>::get_cell_type () const
{
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
return cell_type;
+template <int dim, int n_components_, typename Number>
+inline
+const internal::MatrixFreeFunctions::ShapeInfo<Number> &
+FEEvaluationBase<dim,n_components_,Number>::get_shape_info() const
+{
+ Assert(data != 0, ExcInternalError());
+ return *data;
+}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+void
+FEEvaluationBase<dim,n_components_,Number>
+::fill_JxW_values(AlignedVector<VectorizedArray<Number> > &JxW_values) const
+{
+ AssertDimension(JxW_values.size(), data->n_q_points);
+ Assert (this->J_value != 0, ExcNotImplemented());
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian ||
+ this->cell_type == internal::MatrixFreeFunctions::affine)
+ {
+ Assert (this->mapping_info != 0, ExcNotImplemented());
+ VectorizedArray<Number> J = this->J_value[0];
+ for (unsigned int q=0; q<this->data->n_q_points; ++q)
+ JxW_values[q] = J * this->quadrature_weights[q];
+ }
+ else
+ for (unsigned int q=0; q<data->n_q_points; ++q)
+ JxW_values[q] = this->J_value[q];
+}
+
+
+
namespace internal
{
// write access to generic vectors that have operator ().
res = vector_access (const_cast<const VectorType &>(vec), index);
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ res = const_cast<const VectorType &>(vec)(index);
+ }
+
void pre_constraints (const Number &,
Number &res) const
{
vector_access (vec, index) += res;
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ vec(index) += res;
+ }
+
void pre_constraints (const Number &input,
Number &res) const
{
vector_access (vec, index) = res;
}
+ template <typename VectorType>
+ void process_dof_global (const types::global_dof_index index,
+ VectorType &vec,
+ Number &res) const
+ {
+ vec(index) = res;
+ }
+
void pre_constraints (const Number &,
Number &) const
{
-
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType, typename VectorOperation>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_write_operation (const VectorOperation &operation,
VectorType *src[]) const
{
// into the local data field or write local data into the vector. Certain
// operations are no-ops for the given use case.
- Assert (matrix_info.indices_initialized() == true,
+ // Case 1: No MatrixFree object given, simple case because we do not need to
+ // process constraints and need not care about vectorization
+ if (matrix_info == 0)
+ {
+ Assert (dof_handler != 0, ExcNotInitialized());
+ typename DoFHandler<dim>::cell_iterator cell (&dof_handler->get_tria(),
+ mapped_geometry->get_cell()->level(),
+ mapped_geometry->get_cell()->index(),
+ dof_handler);
+ local_dof_indices.resize(dof_handler->get_fe().dofs_per_cell);
+ cell->get_dof_indices(local_dof_indices);
+
+ unsigned int index = first_selected_component * this->data->dofs_per_cell;
+ for (unsigned int comp = 0; comp<n_components; ++comp)
+ {
+ for (unsigned int i=0; i<this->data->dofs_per_cell; ++i, ++index)
+ {
+ operation.process_dof_global(local_dof_indices[this->data->lexicographic_numbering[index]],
+ *src[0], values_dofs[comp][i][0]);
+ for (unsigned int v=1; v<VectorizedArray<Number>::n_array_elements; ++v)
+ operation.process_empty(values_dofs[comp][i][v]);
+ }
+ }
+ return;
+ }
+
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (matrix_info->indices_initialized() == true,
ExcNotInitialized());
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
// loop over all local dofs. ind_local holds local number on cell, index
// iterates over the elements of index_local_to_global and dof_indices
// points to the global indices stored in index_local_to_global
- const unsigned int *dof_indices = dof_info.begin_indices(cell);
+ const unsigned int *dof_indices = dof_info->begin_indices(cell);
const std::pair<unsigned short,unsigned short> *indicators =
- dof_info.begin_indicators(cell);
+ dof_info->begin_indicators(cell);
const std::pair<unsigned short,unsigned short> *indicators_end =
- dof_info.end_indicators(cell);
+ dof_info->end_indicators(cell);
unsigned int ind_local = 0;
+ const unsigned int dofs_per_cell = this->data->dofs_per_cell;
- const unsigned int n_irreg_components_filled = dof_info.row_starts[cell][2];
+ const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
const bool at_irregular_cell = n_irreg_components_filled > 0;
// scalar case (or case when all components have the same degrees of freedom
const unsigned int n_local_dofs =
VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::check_vector_compatibility (*src[comp], dof_info);
+ internal::check_vector_compatibility (*src[comp], *dof_info);
Number *local_data [n_components];
for (unsigned int comp=0; comp<n_components; ++comp)
local_data[comp] =
value[comp]);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
operation.process_constraint (*dof_indices, *data_val,
}
else
{
- // no constraint at all: loop bounds are known, compiler can
- // unroll without checks
- AssertDimension (dof_info.end_indices(cell)-dof_indices,
+ // no constraint at all: compiler can unroll at least the
+ // vectorization loop
+ AssertDimension (dof_info->end_indices(cell)-dof_indices,
static_cast<int>(n_local_dofs));
- for (unsigned int j=0; j<n_local_dofs; ++j)
- for (unsigned int comp=0; comp<n_components; ++comp)
- operation.process_dof (dof_indices[j], *src[comp],
- local_data[comp][j]);
+ for (unsigned int j=0; j<n_local_dofs; j+=VectorizedArray<Number>::n_array_elements)
+ for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
+ for (unsigned int comp=0; comp<n_components; ++comp)
+ operation.process_dof (dof_indices[j+v], *src[comp],
+ local_data[comp][j+v]);
}
}
value[comp]);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
for (unsigned int comp=0; comp<n_components; ++comp)
}
for (; ind_local<n_local_dofs; ++dof_indices)
{
- Assert (dof_indices != dof_info.end_indices(cell),
+ Assert (dof_indices != dof_info->end_indices(cell),
ExcInternalError());
// non-constrained case: copy the data from the global vector,
// the first component, then all entries to the second one, and so
// on. This is ensured by the way MatrixFree reads out the indices.
{
- internal::check_vector_compatibility (*src[0], dof_info);
+ internal::check_vector_compatibility (*src[0], *dof_info);
Assert (n_fe_components == n_components_, ExcNotImplemented());
const unsigned int n_local_dofs =
dofs_per_cell*VectorizedArray<Number>::n_array_elements * n_components;
operation.pre_constraints (local_data[ind_local], value);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
operation.process_constraint (*dof_indices, *data_val,
for (; ind_local<n_local_dofs; ++dof_indices, ++ind_local)
operation.process_dof (*dof_indices, *src[0],
local_data[ind_local]);
- Assert (dof_indices == dof_info.end_indices(cell),
+ Assert (dof_indices == dof_info->end_indices(cell),
ExcInternalError());
}
else
{
- // no constraint at all: loop bounds are known, compiler can
- // unroll without checks
- AssertDimension (dof_info.end_indices(cell)-dof_indices,
+ // no constraint at all: compiler can unroll at least the
+ // vectorization loop
+ AssertDimension (dof_info->end_indices(cell)-dof_indices,
static_cast<int>(n_local_dofs));
- for (unsigned int j=0; j<n_local_dofs; ++j)
- operation.process_dof (dof_indices[j], *src[0],
- local_data[j]);
+ for (unsigned int j=0; j<n_local_dofs; j+=VectorizedArray<Number>::n_array_elements)
+ for (unsigned int v=0; v<VectorizedArray<Number>::n_array_elements; ++v)
+ operation.process_dof (dof_indices[j+v], *src[0],
+ local_data[j+v]);
}
}
operation.pre_constraints (local_data[ind_local], value);
const Number *data_val =
- matrix_info.constraint_pool_begin(indicators->second);
+ matrix_info->constraint_pool_begin(indicators->second);
const Number *end_pool =
- matrix_info.constraint_pool_end(indicators->second);
+ matrix_info->constraint_pool_end(indicators->second);
for ( ; data_val != end_pool; ++data_val, ++dof_indices)
operation.process_constraint (*dof_indices, *data_val,
}
for (; ind_local<n_local_dofs; ++dof_indices)
{
- Assert (dof_indices != dof_info.end_indices(cell),
+ Assert (dof_indices != dof_info->end_indices(cell),
ExcInternalError());
// non-constrained case: copy the data from the global vector,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const VectorType &src)
{
// select between block vectors and non-block vectors. Note that the number
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const std::vector<VectorType> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values (const std::vector<VectorType *> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const VectorType &src)
{
// select between block vectors and non-block vectors. Note that the number
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const std::vector<VectorType> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const std::vector<VectorType *> &src,
const unsigned int first_index)
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (VectorType &dst) const
{
Assert (dof_values_initialized==true,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (std::vector<VectorType> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::distribute_local_to_global (std::vector<VectorType *> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (VectorType &dst) const
{
Assert (dof_values_initialized==true,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (std::vector<VectorType> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::set_dof_values (std::vector<VectorType *> &dst,
const unsigned int first_index) const
{
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
template<typename VectorType>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::read_dof_values_plain (const VectorType *src[])
{
+ // Case without MatrixFree initialization object
+ if (matrix_info == 0)
+ {
+ internal::VectorReader<Number> reader;
+ read_write_operation (reader, src);
+ return;
+ }
+
// this is different from the other three operations because we do not use
// constraints here, so this is a separate function.
- Assert (matrix_info.indices_initialized() == true,
+ Assert (dof_info != 0, ExcNotInitialized());
+ Assert (matrix_info->indices_initialized() == true,
ExcNotInitialized());
Assert (cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- Assert (dof_info.store_plain_indices == true, ExcNotInitialized());
+ Assert (dof_info->store_plain_indices == true, ExcNotInitialized());
// loop over all local dofs. ind_local holds local number on cell, index
// iterates over the elements of index_local_to_global and dof_indices
// points to the global indices stored in index_local_to_global
- const unsigned int *dof_indices = dof_info.begin_indices_plain(cell);
+ const unsigned int *dof_indices = dof_info->begin_indices_plain(cell);
+ const unsigned int dofs_per_cell = this->data->dofs_per_cell;
- const unsigned int n_irreg_components_filled = dof_info.row_starts[cell][2];
+ const unsigned int n_irreg_components_filled = dof_info->row_starts[cell][2];
const bool at_irregular_cell = n_irreg_components_filled > 0;
// scalar case (or case when all components have the same degrees of freedom
const unsigned int n_local_dofs =
VectorizedArray<Number>::n_array_elements * dofs_per_cell;
for (unsigned int comp=0; comp<n_components; ++comp)
- internal::check_vector_compatibility (*src[comp], dof_info);
+ internal::check_vector_compatibility (*src[comp], *dof_info);
Number *local_src_number [n_components];
for (unsigned int comp=0; comp<n_components; ++comp)
local_src_number[comp] = &values_dofs[comp][0][0];
// the first component, then all entries to the second one, and so
// on. This is ensured by the way MatrixFree reads out the indices.
{
- internal::check_vector_compatibility (*src[0], dof_info);
+ internal::check_vector_compatibility (*src[0], *dof_info);
Assert (n_fe_components == n_components_, ExcNotImplemented());
const unsigned int n_local_dofs =
dofs_per_cell * VectorizedArray<Number>::n_array_elements * n_components;
/*------------------------------ access to data fields ----------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_dof_values () const
{
return &values_dofs[0][0];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_dof_values ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_values () const
{
Assert (values_quad_initialized || values_quad_submitted,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_values ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_gradients () const
{
Assert (gradients_quad_initialized || gradients_quad_submitted,
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_gradients ()
{
#ifdef DEBUG
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
const VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_hessians () const
{
Assert (hessians_quad_initialized, ExcNotInitialized());
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components, typename Number>
+template <int dim, int n_components, typename Number>
inline
VectorizedArray<Number> *
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components,Number>::
+FEEvaluationBase<dim,n_components,Number>::
begin_hessians ()
{
return &hessians_quad[0][0][0];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_dof_value (const unsigned int dof) const
{
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; comp++)
return_value[comp] = this->values_dofs[comp][dof];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; comp++)
return_value[comp] = this->values_quad[comp][q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_gradient (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > grad_out (false);
{
// compute tmp = hess_unit(u) * J^T. do this manually because we do not
// store the lower diagonal because of symmetry
- template <int dim, int n_q_points, typename Number>
+ template <typename Number>
+ inline
+ void
+ hessian_unit_times_jac (const Tensor<2,1,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[1],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[1][1])
+ {
+ tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
+ }
+
+ template <typename Number>
inline
void
- hessian_unit_times_jac (const Tensor<2,dim,VectorizedArray<Number> > &jac,
- const VectorizedArray<Number> hessians_quad[][n_q_points],
- const unsigned int q_point,
- VectorizedArray<Number> tmp[dim][dim])
+ hessian_unit_times_jac (const Tensor<2,2,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[3],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[2][2])
{
- for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int d=0; d<2; ++d)
{
- switch (dim)
- {
- case 1:
- tmp[0][0] = jac[0][0] * hessians_quad[0][q_point];
- break;
- case 2:
- tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
- jac[d][1] * hessians_quad[2][q_point]);
- tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
- jac[d][1] * hessians_quad[1][q_point]);
- break;
- case 3:
- tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
- jac[d][1] * hessians_quad[3][q_point] +
- jac[d][2] * hessians_quad[4][q_point]);
- tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
- jac[d][1] * hessians_quad[1][q_point] +
- jac[d][2] * hessians_quad[5][q_point]);
- tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
- jac[d][1] * hessians_quad[5][q_point] +
- jac[d][2] * hessians_quad[2][q_point]);
- break;
- default:
- Assert (false, ExcNotImplemented());
- }
+ tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
+ jac[d][1] * hessians_quad[2][q_point]);
+ tmp[1][d] = (jac[d][0] * hessians_quad[2][q_point] +
+ jac[d][1] * hessians_quad[1][q_point]);
+ }
+ }
+
+ template <typename Number>
+ inline
+ void
+ hessian_unit_times_jac (const Tensor<2,3,VectorizedArray<Number> > &jac,
+ const VectorizedArray<Number> *const hessians_quad[6],
+ const unsigned int q_point,
+ VectorizedArray<Number> (&tmp)[3][3])
+ {
+ for (unsigned int d=0; d<3; ++d)
+ {
+ tmp[0][d] = (jac[d][0] * hessians_quad[0][q_point] +
+ jac[d][1] * hessians_quad[3][q_point] +
+ jac[d][2] * hessians_quad[4][q_point]);
+ tmp[1][d] = (jac[d][0] * hessians_quad[3][q_point] +
+ jac[d][1] * hessians_quad[1][q_point] +
+ jac[d][2] * hessians_quad[5][q_point]);
+ tmp[2][d] = (jac[d][0] * hessians_quad[4][q_point] +
+ jac[d][1] * hessians_quad[5][q_point] +
+ jac[d][2] * hessians_quad[2][q_point]);
}
}
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<2,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<2,dim,VectorizedArray<Number> > hessian_out [n_components];
// cell with general Jacobian
else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- Assert (this->mapping_info.second_derivatives_initialized == true,
+ Assert (this->mapping_info->second_derivatives_initialized == true,
ExcNotInitialized());
const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > hessian_out (false);
// cell with general Jacobian
else if (this->cell_type == internal::MatrixFreeFunctions::general)
{
- Assert (this->mapping_info.second_derivatives_initialized == true,
+ Assert (this->mapping_info->second_derivatives_initialized == true,
ExcNotInitialized());
const Tensor<2,dim,VectorizedArray<Number> > &jac = jacobian[q_point];
const Tensor<2,dim,VectorizedArray<Number> > &jac_grad = jacobian_grad[q_point];
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::get_laplacian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,n_components_,VectorizedArray<Number> > laplacian_out (false);
const Tensor<1,n_components_,Tensor<1,dim,VectorizedArray<Number> > > hess_diag
= get_hessian_diagonal(q_point);
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_dof_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
#endif
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
for (unsigned int comp=0; comp<n_components; comp++)
this->values_dofs[comp][dof] = val_in[comp];
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_value (const Tensor<1,n_components_,VectorizedArray<Number> > val_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->values_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::general)
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
void
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::submit_gradient (const Tensor<1,n_components_,
Tensor<1,dim,VectorizedArray<Number> > >grad_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
Tensor<1,n_components_,VectorizedArray<Number> >
-FEEvaluationBase<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationBase<dim,n_components_,Number>
::integrate_value () const
{
#ifdef DEBUG
Tensor<1,n_components_,VectorizedArray<Number> > return_value (false);
for (unsigned int comp=0; comp<n_components; ++comp)
return_value[comp] = this->values_quad[comp][0];
+ const unsigned int n_q_points = this->data->n_q_points;
for (unsigned int q=1; q<n_q_points; ++q)
for (unsigned int comp=0; comp<n_components; ++comp)
return_value[comp] += this->values_quad[comp][q];
/*----------------------- FEEvaluationAccess --------------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_,
- int n_components_, typename Number>
+template <int dim, int n_components_, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,n_components_,Number>
+FEEvaluationAccess<dim,n_components_,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points)
+ :
+ FEEvaluationBase <dim,n_components_,Number>
+ (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
+{}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationAccess<dim,n_components_,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ FEEvaluationBase <dim,n_components_,Number> (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, int n_components_, typename Number>
+inline
+FEEvaluationAccess<dim,n_components_,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,n_components_,Number> &other)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,n_components_,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,n_components_,Number>(other)
{}
/*-------------------- FEEvaluationAccess scalar ----------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,1,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,1,Number>
+ (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
{}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,1,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ FEEvaluationBase <dim,1,Number> (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,1,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,1,Number>&other)
+ :
+ FEEvaluationBase <dim,1,Number>(other)
+{}
+
+
+
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_dof_value (const unsigned int dof) const
{
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
return this->values_dofs[0][dof];
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_value (const unsigned int q_point) const
{
Assert (this->values_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return this->values_quad[0][q_point];
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_gradient (const unsigned int q_point) const
{
// could use the base class gradient, but that involves too many inefficient
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
Tensor<1,dim,VectorizedArray<Number> > grad_out (false);
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_hessian (const unsigned int q_point) const
{
return BaseClass::get_hessian(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
return BaseClass::get_hessian_diagonal(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::get_laplacian (const unsigned int q_point) const
{
return BaseClass::get_laplacian(q_point)[0];
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_dof_value (const VectorizedArray<Number> val_in,
const unsigned int dof)
{
#ifdef DEBUG
this->dof_values_initialized = true;
- AssertIndexRange (dof, dofs_per_cell);
+ AssertIndexRange (dof, this->data->dofs_per_cell);
#endif
this->values_dofs[0][dof] = val_in;
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_value (const VectorizedArray<Number> val_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->values_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::general)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::submit_gradient (const Tensor<1,dim,VectorizedArray<Number> > grad_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,1,Number>
+FEEvaluationAccess<dim,1,Number>
::integrate_value () const
{
return BaseClass::integrate_value()[0];
/*----------------- FEEvaluationAccess vector-valued ------------------------*/
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::FEEvaluationAccess (const MatrixFree<dim,Number> &data_in,
const unsigned int fe_no,
- const unsigned int quad_no_in)
+ const unsigned int quad_no_in,
+ const unsigned int fe_degree,
+ const unsigned int n_q_points)
+ :
+ FEEvaluationBase <dim,dim,Number>
+ (data_in, fe_no, quad_no_in, fe_degree, n_q_points)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,dim,Number>
+::FEEvaluationAccess (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ FEEvaluationBase <dim,dim,Number> (geometry, dof_handler, first_selected_component)
+{}
+
+
+
+template <int dim, typename Number>
+inline
+FEEvaluationAccess<dim,dim,Number>
+::FEEvaluationAccess (const FEEvaluationAccess<dim,dim,Number>&other)
:
- FEEvaluationBase <dim,dofs_per_cell_,n_q_points_,dim,Number>
- (data_in, fe_no, quad_no_in)
+ FEEvaluationBase <dim,dim,Number>(other)
{}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_gradient (const unsigned int q_point) const
{
return BaseClass::get_gradient (q_point);
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
VectorizedArray<Number>
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_divergence (const unsigned int q_point) const
{
Assert (this->gradients_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
VectorizedArray<Number> divergence;
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
SymmetricTensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_symmetric_gradient (const unsigned int q_point) const
{
// copy from generic function into dim-specialization function
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<1,dim==2?1:dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_curl (const unsigned int q_point) const
{
// copy from generic function into dim-specialization function
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<2,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_hessian_diagonal (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return BaseClass::get_hessian_diagonal (q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
Tensor<3,dim,VectorizedArray<Number> >
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::get_hessian (const unsigned int q_point) const
{
Assert (this->hessians_quad_initialized==true,
internal::ExcAccessToUninitializedField());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
return BaseClass::get_hessian(q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_gradient (const Tensor<2,dim,VectorizedArray<Number> > grad_in,
const unsigned int q_point)
{
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_gradient (const Tensor<1,dim,Tensor<1,dim,VectorizedArray<Number> > >
grad_in,
const unsigned int q_point)
BaseClass::submit_gradient(grad_in, q_point);
}
-template <int dim, int dofs_per_cell_, int n_q_points_,
- typename Number>
+
+
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_divergence (const VectorizedArray<Number> div_in,
const unsigned int q_point)
{
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_symmetric_gradient(const SymmetricTensor<2,dim,VectorizedArray<Number> >
sym_grad,
const unsigned int q_point)
// that saves some operations
#ifdef DEBUG
Assert (this->cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- AssertIndexRange (q_point, n_q_points);
+ AssertIndexRange (q_point, this->data->n_q_points);
this->gradients_quad_submitted = true;
#endif
if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
-template <int dim, int dofs_per_cell_, int n_q_points_, typename Number>
+template <int dim, typename Number>
inline
void
-FEEvaluationAccess<dim,dofs_per_cell_,n_q_points_,dim,Number>
+FEEvaluationAccess<dim,dim,Number>
::submit_curl (const Tensor<1,dim==2?1:dim,VectorizedArray<Number> > curl,
const unsigned int q_point)
{
-/*----------------------- FEEvaluationGeneral -------------------------------*/
-
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-inline
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::FEEvaluationGeneral (const MatrixFree<dim,Number> &data_in,
- const unsigned int fe_no,
- const unsigned int quad_no)
- :
- BaseClass (data_in, fe_no, quad_no)
+namespace internal
{
-#ifdef DEBUG
- // print error message when the dimensions do not match. Propose a possible
- // fix
- if (dofs_per_cell != this->data.dofs_per_cell ||
- n_q_points != this->data.n_q_points)
+ /**
+ * In this namespace, the evaluator routines that evaluate the tensor
+ * products are implemented.
+ */
+ enum EvaluatorVariant
{
- std::string message =
- "-------------------------------------------------------\n";
- message += "Illegal arguments in constructor/wrong template arguments!\n";
- message += " Called --> FEEvaluation<dim,";
- message += Utilities::int_to_string(fe_degree) + ",";
- message += Utilities::int_to_string(n_q_points_1d);
- message += "," + Utilities::int_to_string(n_components);
- message += ",Number>(data, ";
- message += Utilities::int_to_string(fe_no) + ", ";
- message += Utilities::int_to_string(quad_no) + ")\n";
+ evaluate_general,
+ evaluate_symmetric,
+ evaluate_evenodd
+ };
- // check whether some other vector component has the correct number of
- // points
- unsigned int proposed_dof_comp = numbers::invalid_unsigned_int,
- proposed_quad_comp = numbers::invalid_unsigned_int;
- if (dofs_per_cell == this->matrix_info.get_dof_info(fe_no).dofs_per_cell[this->active_fe_index])
- proposed_dof_comp = fe_no;
- else
- for (unsigned int no=0; no<this->matrix_info.n_components(); ++no)
- if (this->matrix_info.get_dof_info(no).dofs_per_cell[this->active_fe_index]
- == dofs_per_cell)
- {
- proposed_dof_comp = no;
- break;
- }
- if (n_q_points ==
- this->mapping_info.mapping_data_gen[quad_no].n_q_points[this->active_quad_index])
- proposed_quad_comp = quad_no;
- else
- for (unsigned int no=0; no<this->mapping_info.mapping_data_gen.size(); ++no)
- if (this->mapping_info.mapping_data_gen[no].n_q_points[this->active_quad_index]
- == n_q_points)
- {
- proposed_quad_comp = no;
- break;
- }
- if (proposed_dof_comp != numbers::invalid_unsigned_int &&
- proposed_quad_comp != numbers::invalid_unsigned_int)
- {
- if (proposed_dof_comp != fe_no)
- message += "Wrong vector component selection:\n";
- else
- message += "Wrong quadrature formula selection:\n";
- message += " Did you mean FEEvaluation<dim,";
- message += Utilities::int_to_string(fe_degree) + ",";
- message += Utilities::int_to_string(n_q_points_1d);
- message += "," + Utilities::int_to_string(n_components);
- message += ",Number>(data, ";
- message += Utilities::int_to_string(proposed_dof_comp) + ", ";
- message += Utilities::int_to_string(proposed_quad_comp) + ")?\n";
- std::string correct_pos;
- if (proposed_dof_comp != fe_no)
- correct_pos = " ^ ";
- else
- correct_pos = " ";
- if (proposed_quad_comp != quad_no)
- correct_pos += " ^\n";
- else
- correct_pos += " \n";
- message += " " + correct_pos;
- }
- // ok, did not find the numbers specified by the template arguments in
- // the given list. Suggest correct template arguments
- const unsigned int proposed_fe_degree = static_cast<unsigned int>(std::pow(1.001*this->data.dofs_per_cell,1./dim))-1;
- const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data.n_q_points,1./dim));
- message += "Wrong template arguments:\n";
- message += " Did you mean FEEvaluation<dim,";
- message += Utilities::int_to_string(proposed_fe_degree) + ",";
- message += Utilities::int_to_string(proposed_n_q_points_1d);
- message += "," + Utilities::int_to_string(n_components);
- message += ",Number>(data, ";
- message += Utilities::int_to_string(fe_no) + ", ";
- message += Utilities::int_to_string(quad_no) + ")?\n";
- std::string correct_pos;
- if (proposed_fe_degree != fe_degree)
- correct_pos = " ^";
- else
- correct_pos = " ";
- if (proposed_n_q_points_1d != n_q_points_1d)
- correct_pos += " ^\n";
- else
- correct_pos += " \n";
- message += " " + correct_pos;
+ /**
+ * Generic evaluator framework
+ */
+ template <EvaluatorVariant variant, int dim, int fe_degree, int n_q_points_1d,
+ typename Number>
+ struct EvaluatorTensorProduct
+ {};
- Assert (dofs_per_cell == this->data.dofs_per_cell &&
- n_q_points == this->data.n_q_points,
- ExcMessage(message));
+ /**
+ * Internal evaluator for 1d-3d shape function using the tensor product form
+ * of the basis functions
+ */
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ struct EvaluatorTensorProduct<evaluate_general,dim,fe_degree,n_q_points_1d,Number>
+ {
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
+
+ /**
+ * Empty constructor. Does nothing. Be careful when using 'values' and
+ * related methods because they need to be filled with the other pointer
+ */
+ EvaluatorTensorProduct ()
+ :
+ shape_values (0),
+ shape_gradients (0),
+ shape_hessians (0)
+ {}
+
+ /**
+ * Constructor, taking the data from ShapeInfo
+ */
+ EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
+ const AlignedVector<Number> &shape_gradients,
+ const AlignedVector<Number> &shape_hessians)
+ :
+ shape_values (shape_values.begin()),
+ shape_gradients (shape_gradients.begin()),
+ shape_hessians (shape_hessians.begin())
+ {}
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ values (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add>(shape_values, in, out);
}
- AssertDimension (n_q_points,
- this->mapping_info.mapping_data_gen[this->quad_no].
- n_q_points[this->active_quad_index]);
- AssertDimension (dofs_per_cell * this->n_fe_components,
- this->dof_info.dofs_per_cell[this->active_fe_index]);
-#endif
-}
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ gradients (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add>(shape_gradients, in, out);
+ }
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ hessians (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add>(shape_hessians, in, out);
+ }
+
+ template <int direction, bool dof_to_quad, bool add>
+ static void apply (const Number *shape_data,
+ const Number in [],
+ Number out []);
+
+ const Number * shape_values;
+ const Number * shape_gradients;
+ const Number * shape_hessians;
+ };
-namespace internal
-{
// evaluates the given shape data in 1d-3d using the tensor product
// form. does not use a particular layout of entries in the matrices
// like the functions below and corresponds to a usual matrix-matrix
// product
- template <int dim, int fe_degree, int n_q_points_1d, typename Number,
- int direction, bool dof_to_quad, bool add>
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ template <int direction, bool dof_to_quad, bool add>
inline
void
- apply_tensor_product (const Number *shape_data,
- const Number in [],
- Number out [])
+ EvaluatorTensorProduct<evaluate_general,dim,fe_degree,n_q_points_1d,Number>
+ ::apply (const Number *shape_data,
+ const Number in [],
+ Number out [])
{
AssertIndexRange (direction, dim);
const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
out += nn;
break;
case 1:
+ ++in;
+ ++out;
+ // faces 2 and 3 in 3D use local coordinate system zx, which
+ // is the other way around compared to the tensor
+ // product. Need to take that into account.
+ if (dim == 3)
+ {
+ if (dof_to_quad)
+ out += fe_degree;
+ else
+ in += fe_degree;
+ }
+ break;
case 2:
++in;
++out;
Assert (false, ExcNotImplemented());
}
}
- if (face_direction == 1)
+ if (face_direction == 1 && dim == 3)
{
in += mm*(mm-1);
out += nn*(nn-1);
+ // adjust for local coordinate system zx
+ if (dof_to_quad)
+ out -= (fe_degree+1)*(fe_degree+1)-1;
+ else
+ in -= (fe_degree+1)*(fe_degree+1)-1;
}
}
}
- // This method specializes the general application of tensor-product based
+ // This class specializes the general application of tensor-product based
// elements for "symmetric" finite elements, i.e., when the shape functions
- // are symmetric about 0.5 and the quadrature points are, too. In that case,
- // the 1D shape values read (sorted lexicographically, rows run over 1D
- // dofs, columns over quadrature points):
+ // are symmetric about 0.5 and the quadrature points are, too.
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ struct EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
+ {
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
+
+ /**
+ * Constructor, taking the data from ShapeInfo
+ */
+ EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
+ const AlignedVector<Number> &shape_gradients,
+ const AlignedVector<Number> &shape_hessians)
+ :
+ shape_values (shape_values.begin()),
+ shape_gradients (shape_gradients.begin()),
+ shape_hessians (shape_hessians.begin())
+ {}
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ values (const Number in [],
+ Number out[]) const;
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ gradients (const Number in [],
+ Number out[]) const;
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ hessians (const Number in [],
+ Number out[]) const;
+
+ const Number * shape_values;
+ const Number * shape_gradients;
+ const Number * shape_hessians;
+ };
+
+
+
+ // In this case, the 1D shape values read (sorted lexicographically, rows
+ // run over 1D dofs, columns over quadrature points):
// Q2 --> [ 0.687 0 -0.087 ]
// [ 0.4 1 0.4 ]
// [-0.087 0 0.687 ]
// In these matrices, we want to use avoid computations involving zeros and
// ones and in addition use the symmetry in entries to reduce the number of
// read operations.
- template <int dim, int fe_degree, int n_q_points_1d, typename Number,
- int direction, bool dof_to_quad, bool add>
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ template <int direction, bool dof_to_quad, bool add>
inline
void
- apply_tensor_product_values (const Number *shape_values,
- const Number in [],
- Number out [])
+ EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
+ ::values (const Number in [],
+ Number out []) const
{
AssertIndexRange (direction, dim);
const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
- // evaluates the given shape data in 1d-3d using the tensor product
- // form assuming the symmetries of unit cell shape gradients for
- // finite elements in FEEvaluation
-
// For the specialized loop used for the gradient computation in
// here, the 1D shape values read (sorted lexicographically, rows
// run over 1D dofs, columns over quadrature points):
// In these matrices, we want to use avoid computations involving
// zeros and ones and in addition use the symmetry in entries to
// reduce the number of read operations.
- template <int dim, int fe_degree, int n_q_points_1d, typename Number,
- int direction, bool dof_to_quad, bool add>
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ template <int direction, bool dof_to_quad, bool add>
inline
void
- apply_tensor_product_gradients (const Number *shape_gradients,
- const Number in [],
- Number out [])
+ EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
+ ::gradients (const Number in [],
+ Number out []) const
{
AssertIndexRange (direction, dim);
const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
// evaluates the given shape data in 1d-3d using the tensor product
// form assuming the symmetries of unit cell shape hessians for
// finite elements in FEEvaluation
- template <int dim, int fe_degree, int n_q_points_1d, typename Number,
- int direction, bool dof_to_quad, bool add>
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ template <int direction, bool dof_to_quad, bool add>
inline
void
- apply_tensor_product_hessians (const Number *shape_hessians,
- const Number in [],
- Number out [])
+ EvaluatorTensorProduct<evaluate_symmetric,dim,fe_degree,n_q_points_1d,Number>
+ ::hessians (const Number in [],
+ Number out []) const
{
AssertIndexRange (direction, dim);
const int mm = dof_to_quad ? (fe_degree+1) : n_q_points_1d,
- // This method implements a different approach to the symmetric case for
+ // This class implements a different approach to the symmetric case for
// values, gradients, and Hessians also treated with the above functions: It
// is possible to reduce the cost per dimension from N^2 to N^2/2, where N
// is the number of 1D dofs (there are only N^2/2 different entries in the
// experiments in the book say that the method is not efficient for N<20, it
// is more efficient in the context where the loop bounds are compile-time
// constants (templates).
- template <int dim, int fe_degree, int n_q_points_1d, typename Number,
- int direction, bool dof_to_quad, bool add, int type>
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ struct EvaluatorTensorProduct<evaluate_evenodd,dim,fe_degree,n_q_points_1d,Number>
+ {
+ static const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ static const unsigned int n_q_points = Utilities::fixed_int_power<n_q_points_1d,dim>::value;
+
+ /**
+ * Empty constructor. Does nothing. Be careful when using 'values' and
+ * related methods because they need to be filled with the other pointer
+ */
+ EvaluatorTensorProduct ()
+ :
+ shape_values (0),
+ shape_gradients (0),
+ shape_hessians (0)
+ {}
+
+ /**
+ * Constructor, taking the data from ShapeInfo (using the even-odd
+ * variants stored there)
+ */
+ EvaluatorTensorProduct (const AlignedVector<Number> &shape_values,
+ const AlignedVector<Number> &shape_gradients,
+ const AlignedVector<Number> &shape_hessians)
+ :
+ shape_values (shape_values.begin()),
+ shape_gradients (shape_gradients.begin()),
+ shape_hessians (shape_hessians.begin())
+ {}
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ values (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add,0>(shape_values, in, out);
+ }
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ gradients (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add,1>(shape_gradients, in, out);
+ }
+
+ template <int direction, bool dof_to_quad, bool add>
+ void
+ hessians (const Number in [],
+ Number out[]) const
+ {
+ apply<direction,dof_to_quad,add,2>(shape_hessians, in, out);
+ }
+
+ template <int direction, bool dof_to_quad, bool add, int type>
+ static void apply (const Number *shape_data,
+ const Number in [],
+ Number out []);
+
+ const Number * shape_values;
+ const Number * shape_gradients;
+ const Number * shape_hessians;
+ };
+
+
+
+ template <int dim, int fe_degree, int n_q_points_1d, typename Number>
+ template <int direction, bool dof_to_quad, bool add, int type>
inline
void
- apply_tensor_product_evenodd (const Number shapes [][(n_q_points_1d+1)/2],
- const Number in [],
- Number out [])
+ EvaluatorTensorProduct<evaluate_evenodd,dim,fe_degree,n_q_points_1d,Number>
+ ::apply (const Number *shapes,
+ const Number in [],
+ Number out [])
{
AssertIndexRange (type, 3);
AssertIndexRange (direction, dim);
const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
const int stride = Utilities::fixed_int_power<nn,direction>::value;
+ const int offset = (n_q_points_1d+1)/2;
+
// this code may look very inefficient at first sight due to the many
// different cases with if's at the innermost loop part, but all of the
// conditionals can be evaluated at compile time because they are
{
for (int i1=0; i1<n_blocks1; ++i1)
{
- Number xp[mid], xm[mid];
+ Number xp[mid>0?mid:1], xm[mid>0?mid:1];
for (int i=0; i<mid; ++i)
{
if (dof_to_quad == true && type == 1)
{
if (dof_to_quad == true)
{
- r0 = shapes[0][col] * xp[0];
- r1 = shapes[fe_degree][col] * xm[0];
+ r0 = shapes[col] * xp[0];
+ r1 = shapes[fe_degree*offset + col] * xm[0];
}
else
{
- r0 = shapes[col][0] * xp[0];
- r1 = shapes[fe_degree-col][0] * xm[0];
+ r0 = shapes[col*offset] * xp[0];
+ r1 = shapes[(fe_degree-col)*offset] * xm[0];
}
for (int ind=1; ind<mid; ++ind)
{
if (dof_to_quad == true)
{
- r0 += shapes[ind][col] * xp[ind];
- r1 += shapes[fe_degree-ind][col] * xm[ind];
+ r0 += shapes[ind*offset+col] * xp[ind];
+ r1 += shapes[(fe_degree-ind)*offset+col] * xm[ind];
}
else
{
- r0 += shapes[col][ind] * xp[ind];
- r1 += shapes[fe_degree-col][ind] * xm[ind];
+ r0 += shapes[col*offset+ind] * xp[ind];
+ r1 += shapes[(fe_degree-col)*offset+ind] * xm[ind];
}
}
}
if (mm % 2 == 1 && dof_to_quad == true)
{
if (type == 1)
- r1 += shapes[mid][col] * in[stride*mid];
+ r1 += shapes[mid*offset+col] * in[stride*mid];
else
- r0 += shapes[mid][col] * in[stride*mid];
+ r0 += shapes[mid*offset+col] * in[stride*mid];
}
else if (mm % 2 == 1 && (nn % 2 == 0 || type > 0))
- r0 += shapes[col][mid] * in[stride*mid];
+ r0 += shapes[col*offset+mid] * in[stride*mid];
if (add == false)
{
Number r0;
if (mid > 0)
{
- r0 = shapes[0][n_cols] * xp[0];
+ r0 = shapes[n_cols] * xp[0];
for (int ind=1; ind<mid; ++ind)
- r0 += shapes[ind][n_cols] * xp[ind];
+ r0 += shapes[ind*offset+n_cols] * xp[ind];
}
else
r0 = Number();
if (type != 1 && mm % 2 == 1)
- r0 += shapes[mid][n_cols] * in[stride*mid];
+ r0 += shapes[mid*offset+n_cols] * in[stride*mid];
if (add == false)
out[stride*n_cols] = r0;
{
if (type == 1)
{
- r0 = shapes[n_cols][0] * xm[0];
+ r0 = shapes[n_cols*offset] * xm[0];
for (int ind=1; ind<mid; ++ind)
- r0 += shapes[n_cols][ind] * xm[ind];
+ r0 += shapes[n_cols*offset+ind] * xm[ind];
}
else
{
- r0 = shapes[n_cols][0] * xp[0];
+ r0 = shapes[n_cols*offset] * xp[0];
for (int ind=1; ind<mid; ++ind)
- r0 += shapes[n_cols][ind] * xp[ind];
+ r0 += shapes[n_cols*offset+ind] * xp[ind];
}
}
else
if (type == 0 && mm % 2 == 1)
r0 += in[stride*mid];
else if (type == 2 && mm % 2 == 1)
- r0 += shapes[n_cols][mid] * in[stride*mid];
+ r0 += shapes[n_cols*offset+mid] * in[stride*mid];
if (add == false)
out[stride*n_cols] = r0;
- // evaluates the given shape data in 1d-3d using the tensor product
- // form assuming the symmetries of unit cell shape gradients for
- // finite elements in FEEvaluationGL
-
- // This function specializes the application of the tensor product loop for
- // Gauss-Lobatto elements which are symmetric about 0.5 just as the general
- // class of elements treated by FEEvaluation, have diagonal shape matrices
- // for the values and have the following gradient matrices (notice the zeros
- // on the diagonal in the interior points, which is due to the construction
- // of Legendre polynomials):
- // Q2 --> [-3 -1 1 ]
- // [ 4 0 -4 ]
- // [-1 1 3 ]
- // Q3 --> [-6 -1.618 0.618 -1 ]
- // [ 8.09 0 -2.236 3.09 ]
- // [-3.09 2.236 0 -8.09 ]
- // [ 1 -0.618 1.618 6 ]
- // Q4 --> [-10 -2.482 0.75 -0.518 1 ]
- // [ 13.51 0 -2.673 1.528 -2.82 ]
- // [-5.333 3.491 0 -3.491 5.333 ]
- // [ 2.82 -1.528 2.673 0 -13.51 ]
- // [-1 0.518 -0.75 2.482 10 ]
- template <int dim, int fe_degree, typename Number,
- int direction, bool dof_to_quad, bool add>
- inline
- void
- apply_tensor_product_gradients_gl (const Number *shape_gradients,
- const Number in [],
- Number out [])
+ // Select evaluator type from element shape function type
+ template <MatrixFreeFunctions::ElementType element, bool is_long>
+ struct EvaluatorSelector {};
+
+ template <bool is_long>
+ struct EvaluatorSelector<MatrixFreeFunctions::tensor_general,is_long>
{
- AssertIndexRange (direction, dim);
- const int mm = fe_degree+1;
- const int nn = fe_degree+1;
- const int n_cols = nn / 2;
- const int mid = mm / 2;
+ static const EvaluatorVariant variant = evaluate_general;
+ };
- const int n_blocks1 = (dim > 1 ? (direction > 0 ? nn : mm) : 1);
- const int n_blocks2 = (dim > 2 ? (direction > 1 ? nn : mm) : 1);
- const int stride = Utilities::fixed_int_power<nn,direction>::value;
+ template <>
+ struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric,false>
+ {
+ static const EvaluatorVariant variant = evaluate_symmetric;
+ };
- for (int i2=0; i2<n_blocks2; ++i2)
- {
- for (int i1=0; i1<n_blocks1; ++i1)
- {
- for (int col=0; col<n_cols; ++col)
- {
- Number val0, val1, in0, in1, res0, res1;
- if (mid > 0)
- {
- if (dof_to_quad == true)
- {
- val0 = shape_gradients[col];
- val1 = shape_gradients[nn-1-col];
- }
- else
- {
- val0 = shape_gradients[col*mm];
- val1 = shape_gradients[(nn-col-1)*mm];
- }
- in0 = in[0];
- in1 = in[stride*(mm-1)];
- if (col == 0)
- {
- if ((mm+dof_to_quad)%2 == 1)
- {
- res0 = val0 * in0;
- res1 = -in0;
- res0 += in1;
- res1 -= val0 * in1;
- }
- else
- {
- res0 = val0 * in0;
- res0 -= in1;
- res1 = in0;
- res1 -= val0 * in1;
- }
- }
- else
- {
- res0 = val0 * in0;
- res1 = val1 * in0;
- res0 -= val1 * in1;
- res1 -= val0 * in1;
- }
- for (int ind=1; ind<mid; ++ind)
- {
- if (dof_to_quad == true)
- {
- val0 = shape_gradients[ind*mm+col];
- val1 = shape_gradients[ind*mm+nn-1-col];
- }
- else
- {
- val0 = shape_gradients[col*mm+ind];
- val1 = shape_gradients[(nn-col-1)*mm+ind];
- }
+ template <> struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric,true>
+ {
+ static const EvaluatorVariant variant = evaluate_evenodd;
+ };
- // at inner points, the gradient is zero for ind==col
- in0 = in[stride*ind];
- in1 = in[stride*(mm-1-ind)];
- if (ind == col)
- {
- res1 += val1 * in0;
- res0 -= val1 * in1;
- }
- else
- {
- res0 += val0 * in0;
- res1 += val1 * in0;
- res0 -= val1 * in1;
- res1 -= val0 * in1;
- }
- }
- }
- else
- res0 = res1 = Number();
- if (mm % 2 == 1)
- {
- if (dof_to_quad == true)
- val0 = shape_gradients[mid*mm+col];
- else
- val0 = shape_gradients[col*mm+mid];
- val1 = val0 * in[stride*mid];
- res0 += val1;
- res1 -= val1;
- }
- if (add == false)
- {
- out[stride*col] = res0;
- out[stride*(nn-1-col)] = res1;
- }
- else
- {
- out[stride*col] += res0;
- out[stride*(nn-1-col)] += res1;
- }
- }
- if ( nn%2 == 1 )
- {
- Number val0, res0;
- if (dof_to_quad == true)
- val0 = shape_gradients[n_cols];
- else
- val0 = shape_gradients[n_cols*mm];
- if (mid > 0)
- {
- res0 = in[0] - in[stride*(mm-1)];
- res0 *= val0;
- for (int ind=1; ind<mid; ++ind)
- {
- if (dof_to_quad == true)
- val0 = shape_gradients[ind*mm+n_cols];
- else
- val0 = shape_gradients[n_cols*mm+ind];
- Number val1 = in[stride*ind] - in[stride*(mm-1-ind)];
- val1 *= val0;
- res0 += val1;
- }
- }
- else
- res0 = Number();
- if (add == false)
- out[stride*n_cols] = res0;
- else
- out[stride*n_cols] += res0;
- }
+ template <bool is_long>
+ struct EvaluatorSelector<MatrixFreeFunctions::truncated_tensor,is_long>
+ {
+ static const EvaluatorVariant variant = evaluate_general;
+ };
- // increment: in regular case, just go to the next point in
- // x-direction. for y-part in 3D and if we are at the end of one
- // chunk in x-dir, need to jump over to the next layer in
- // z-direction
- switch (direction)
+ template <>
+ struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric_plus_dg0,false>
+ {
+ static const EvaluatorVariant variant = evaluate_symmetric;
+ };
+
+ template <>
+ struct EvaluatorSelector<MatrixFreeFunctions::tensor_symmetric_plus_dg0,true>
+ {
+ static const EvaluatorVariant variant = evaluate_evenodd;
+ };
+
+ template <bool is_long>
+ struct EvaluatorSelector<MatrixFreeFunctions::tensor_gausslobatto,is_long>
+ {
+ static const EvaluatorVariant variant = evaluate_evenodd;
+ };
+
+
+
+ // This struct performs the evaluation of function values, gradients and
+ // Hessians for tensor-product finite elements. The operation is used for
+ // both the symmetric and non-symmetric case, which use different apply
+ // functions 'values', 'gradients' in the individual coordinate
+ // directions. The apply functions for values are provided through one of
+ // the template classes EvaluatorTensorProduct which in turn are selected
+ // from the MatrixFreeFunctions::ElementType template argument.
+ //
+ // There is a specialization made for Gauss-Lobatto elements further down
+ // where the 'values' operation is identity, which allows us to write
+ // shorter code.
+ template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
+ int n_q_points_1d, int n_components, typename Number>
+ struct FEEvaluationImpl
+ {
+ static
+ void evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl);
+
+ static
+ void integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ const bool evaluate_val,
+ const bool evaluate_grad);
+ };
+
+
+ template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
+ int n_q_points_1d, int n_components, typename Number>
+ inline
+ void
+ FEEvaluationImpl<type,dim,fe_degree,n_q_points_1d,n_components,Number>
+ ::evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl)
+ {
+ if (evaluate_val == false && evaluate_grad == false && evaluate_lapl == false)
+ return;
+
+ const EvaluatorVariant variant =
+ EvaluatorSelector<type,(fe_degree+n_q_points_1d>4)>::variant;
+ typedef EvaluatorTensorProduct<variant, dim, fe_degree, n_q_points_1d,
+ VectorizedArray<Number> > Eval;
+ Eval eval (variant == evaluate_evenodd ? shape_info.shape_val_evenodd :
+ shape_info.shape_values,
+ variant == evaluate_evenodd ? shape_info.shape_gra_evenodd :
+ shape_info.shape_gradients,
+ variant == evaluate_evenodd ? shape_info.shape_hes_evenodd :
+ shape_info.shape_hessians);
+
+ const unsigned int temp_size = Eval::dofs_per_cell > Eval::n_q_points ?
+ Eval::dofs_per_cell : Eval::n_q_points;
+
+ VectorizedArray<Number> **values_dofs = values_dofs_actual;
+ VectorizedArray<Number> data_array[type!=MatrixFreeFunctions::truncated_tensor ? 1 :
+ n_components*Eval::dofs_per_cell];
+ VectorizedArray<Number> *expanded_dof_values[n_components];
+ if (type == MatrixFreeFunctions::truncated_tensor)
+ {
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c] = &data_array[c*Eval::dofs_per_cell];
+ values_dofs = expanded_dof_values;
+
+ unsigned int count_p = 0, count_q = 0;
+ for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
+ {
+ for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
{
- case 0:
- in += mm;
- out += nn;
- break;
- case 1:
- case 2:
- ++in;
- ++out;
- break;
- default:
- Assert (false, ExcNotImplemented());
+ for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = values_dofs_actual[c][count_p];
+ for (unsigned int k=fe_degree+1-j-i; k<fe_degree+1; ++k, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = VectorizedArray<Number>();
}
+ for (unsigned int j=fe_degree+1-i; j<fe_degree+1; ++j)
+ for (unsigned int k=0; k<fe_degree+1; ++k, ++count_q)
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c][count_q] = VectorizedArray<Number>();
}
+ AssertDimension(count_q, Eval::dofs_per_cell);
+ }
- if (direction == 1)
+ // These avoid compiler errors; they are only used in sensible context but
+ // compilers typically cannot detect when we access something like
+ // gradients_quad[2] only for dim==3.
+ const unsigned int d1 = dim>1?1:0;
+ const unsigned int d2 = dim>2?2:0;
+ const unsigned int d3 = dim>2?3:0;
+ const unsigned int d4 = dim>2?4:0;
+ const unsigned int d5 = dim>2?5:0;
+
+ switch (dim)
+ {
+ case 1:
+ for (unsigned int c=0; c<n_components; c++)
{
- in += nn * (mm-1);
- out += nn * (nn-1);
+ if (evaluate_val == true)
+ eval.template values<0,true,false> (values_dofs[c], values_quad[c]);
+ if (evaluate_grad == true)
+ eval.template gradients<0,true,false>(values_dofs[c], gradients_quad[c][0]);
+ if (evaluate_lapl == true)
+ eval.template hessians<0,true,false> (values_dofs[c], hessians_quad[c][0]);
}
- }
- }
+ break;
+ case 2:
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ VectorizedArray<Number> temp1[temp_size];
+ VectorizedArray<Number> temp2[temp_size];
+ // grad x
+ if (evaluate_grad == true)
+ {
+ eval.template gradients<0,true,false> (values_dofs[c], temp1);
+ eval.template values<1,true,false> (temp1, gradients_quad[c][0]);
+ }
+ if (evaluate_lapl == true)
+ {
+ // grad xy
+ if (evaluate_grad == false)
+ eval.template gradients<0,true,false>(values_dofs[c], temp1);
+ eval.template gradients<1,true,false> (temp1, hessians_quad[c][d1+d1]);
- // This performs the evaluation of function values, gradients and Hessians
- // for tensor-product finite elements. The operation is used for both
- // FEEvaluationGeneral and FEEvaluation, which provide different functions
- // apply_values, apply_gradients in the individual coordinate directions
- template <typename FEEval>
- inline
- void
- do_evaluate (FEEval &fe_eval,
- const bool evaluate_val,
- const bool evaluate_grad,
- const bool evaluate_lapl)
- {
- Assert (fe_eval.cell != numbers::invalid_unsigned_int,
- ExcNotInitialized());
- Assert (fe_eval.dof_values_initialized == true,
- internal::ExcAccessToUninitializedField());
+ // grad xx
+ eval.template hessians<0,true,false>(values_dofs[c], temp1);
+ eval.template values<1,true,false> (temp1, hessians_quad[c][0]);
+ }
- const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
- FEEval::dofs_per_cell : FEEval::n_q_points;
- const unsigned int n_components = FEEval::n_components;
- const unsigned int dim = FEEval::dimension;
+ // grad y
+ eval.template values<0,true,false> (values_dofs[c], temp1);
+ if (evaluate_grad == true)
+ eval.template gradients<1,true,false> (temp1, gradients_quad[c][d1]);
- for (unsigned int c=0; c<n_components; c++)
- {
- VectorizedArray<typename FEEval::number_type> temp1[temp_size];
- VectorizedArray<typename FEEval::number_type> temp2[temp_size];
+ // grad yy
+ if (evaluate_lapl == true)
+ eval.template hessians<1,true,false> (temp1, hessians_quad[c][d1]);
- switch (dim)
+ // val: can use values applied in x
+ if (evaluate_val == true)
+ eval.template values<1,true,false> (temp1, values_quad[c]);
+ }
+ break;
+
+ case 3:
+ for (unsigned int c=0; c<n_components; c++)
{
- case 3:
+ VectorizedArray<Number> temp1[temp_size];
+ VectorizedArray<Number> temp2[temp_size];
if (evaluate_grad == true)
{
// grad x
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.gradients_quad[c][0]);
+ eval.template gradients<0,true,false> (values_dofs[c], temp1);
+ eval.template values<1,true,false> (temp1, temp2);
+ eval.template values<2,true,false> (temp2, gradients_quad[c][0]);
}
if (evaluate_lapl == true)
// grad xz
if (evaluate_grad == false)
{
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
+ eval.template gradients<0,true,false> (values_dofs[c], temp1);
+ eval.template values<1,true,false> (temp1, temp2);
}
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.hessians_quad[c][4]);
+ eval.template gradients<2,true,false> (temp2, hessians_quad[c][d4]);
// grad xy
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][3]);
+ eval.template gradients<1,true,false> (temp1, temp2);
+ eval.template values<2,true,false> (temp2, hessians_quad[c][d3]);
// grad xx
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][0]);
+ eval.template hessians<0,true,false>(values_dofs[c], temp1);
+ eval.template values<1,true,false> (temp1, temp2);
+ eval.template values<2,true,false> (temp2, hessians_quad[c][0]);
}
// grad y
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], temp1);
+ eval.template values<0,true,false> (values_dofs[c], temp1);
if (evaluate_grad == true)
{
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.gradients_quad[c][1]);
+ eval.template gradients<1,true,false>(temp1, temp2);
+ eval.template values<2,true,false> (temp2, gradients_quad[c][d1]);
}
if (evaluate_lapl == true)
{
// grad yz
if (evaluate_grad == false)
- fe_eval.template apply_gradients<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.hessians_quad[c][5]);
+ eval.template gradients<1,true,false>(temp1, temp2);
+ eval.template gradients<2,true,false> (temp2, hessians_quad[c][d5]);
// grad yy
- fe_eval.template apply_hessians<1,true,false>
- (temp1, temp2);
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.hessians_quad[c][1]);
+ eval.template hessians<1,true,false> (temp1, temp2);
+ eval.template values<2,true,false> (temp2, hessians_quad[c][d1]);
}
// grad z: can use the values applied in x direction stored in temp1
- fe_eval.template apply_values<1,true,false>
- (temp1, temp2);
+ eval.template values<1,true,false> (temp1, temp2);
if (evaluate_grad == true)
- fe_eval.template apply_gradients<2,true,false>
- (temp2, fe_eval.gradients_quad[c][2]);
+ eval.template gradients<2,true,false> (temp2, gradients_quad[c][d2]);
// grad zz: can use the values applied in x and y direction stored
// in temp2
if (evaluate_lapl == true)
- fe_eval.template apply_hessians<2,true,false>
- (temp2, fe_eval.hessians_quad[c][2]);
+ eval.template hessians<2,true,false>(temp2, hessians_quad[c][d2]);
// val: can use the values applied in x & y direction stored in temp2
if (evaluate_val == true)
- fe_eval.template apply_values<2,true,false>
- (temp2, fe_eval.values_quad[c]);
-
- break;
-
- case 2:
-
- // grad x
- if (evaluate_grad == true)
- {
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.gradients_quad[c][0]);
- }
- if (evaluate_lapl == true)
- {
- // grad xy
- if (evaluate_grad == false)
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_gradients<1,true,false>
- (temp1, fe_eval.hessians_quad[c][2]);
-
- // grad xx
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.hessians_quad[c][0]);
- }
-
- // grad y
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], temp1);
- if (evaluate_grad == true)
- fe_eval.template apply_gradients<1,true,false>
- (temp1, fe_eval.gradients_quad[c][1]);
-
- // grad yy
- if (evaluate_lapl == true)
- fe_eval.template apply_hessians<1,true,false>
- (temp1, fe_eval.hessians_quad[c][1]);
-
- // val: can use values applied in x
- if (evaluate_val == true)
- fe_eval.template apply_values<1,true,false>
- (temp1, fe_eval.values_quad[c]);
-
- break;
-
- case 1:
- if (evaluate_val == true)
- fe_eval.template apply_values<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.values_quad[c]);
- if (evaluate_grad == true)
- fe_eval.template apply_gradients<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.gradients_quad[c][0]);
- if (evaluate_lapl == true)
- fe_eval.template apply_hessians<0,true,false>
- (fe_eval.values_dofs[c], fe_eval.hessians_quad[c][0]);
- break;
-
- default:
- Assert (false, ExcNotImplemented());
+ eval.template values<2,true,false> (temp2, values_quad[c]);
}
+ break;
+
+ default:
+ AssertThrow(false, ExcNotImplemented());
}
-#ifdef DEBUG
- if (evaluate_val == true)
- fe_eval.values_quad_initialized = true;
- if (evaluate_grad == true)
- fe_eval.gradients_quad_initialized = true;
- if (evaluate_lapl == true)
- fe_eval.hessians_quad_initialized = true;
-#endif
+ // case additional dof for FE_Q_DG0: add values; gradients and second
+ // derivatives evaluate to zero
+ if (type == MatrixFreeFunctions::tensor_symmetric_plus_dg0 && evaluate_val)
+ for (unsigned int c=0; c<n_components; ++c)
+ for (unsigned int q=0; q<Eval::n_q_points; ++q)
+ values_quad[c][q] += values_dofs[c][Eval::dofs_per_cell];
}
- template <typename FEEval>
+ template <MatrixFreeFunctions::ElementType type, int dim, int fe_degree,
+ int n_q_points_1d, int n_components, typename Number>
inline
void
- do_integrate (FEEval &fe_eval,
- const bool integrate_val,
- const bool integrate_grad)
+ FEEvaluationImpl<type,dim,fe_degree,n_q_points_1d,n_components,Number>
+ ::integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs_actual[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ const bool integrate_val,
+ const bool integrate_grad)
{
- Assert (fe_eval.cell != numbers::invalid_unsigned_int, ExcNotInitialized());
- if (integrate_val == true)
- Assert (fe_eval.values_quad_submitted == true,
- ExcAccessToUninitializedField());
- if (integrate_grad == true)
- Assert (fe_eval.gradients_quad_submitted == true,
- ExcAccessToUninitializedField());
-
- const unsigned int temp_size = FEEval::dofs_per_cell > FEEval::n_q_points ?
- FEEval::dofs_per_cell : FEEval::n_q_points;
- const unsigned int n_components = FEEval::n_components;
- const unsigned int dim = FEEval::dimension;
+ const EvaluatorVariant variant =
+ EvaluatorSelector<type,(fe_degree+n_q_points_1d>4)>::variant;
+ typedef EvaluatorTensorProduct<variant, dim, fe_degree, n_q_points_1d,
+ VectorizedArray<Number> > Eval;
+ Eval eval (variant == evaluate_evenodd ? shape_info.shape_val_evenodd :
+ shape_info.shape_values,
+ variant == evaluate_evenodd ? shape_info.shape_gra_evenodd :
+ shape_info.shape_gradients,
+ variant == evaluate_evenodd ? shape_info.shape_hes_evenodd :
+ shape_info.shape_hessians);
+
+ const unsigned int temp_size = Eval::dofs_per_cell > Eval::n_q_points ?
+ Eval::dofs_per_cell : Eval::n_q_points;
+ VectorizedArray<Number> temp1[temp_size];
+ VectorizedArray<Number> temp2[temp_size];
+
+ // expand dof_values to tensor product for truncated tensor products
+ VectorizedArray<Number> ** values_dofs = values_dofs_actual;
+ VectorizedArray<Number> data_array[type!=MatrixFreeFunctions::truncated_tensor ? 1 :
+ n_components*Eval::dofs_per_cell];
+ VectorizedArray<Number> *expanded_dof_values[n_components];
+ if (type == MatrixFreeFunctions::truncated_tensor)
+ {
+ for (unsigned int c=0; c<n_components; ++c)
+ expanded_dof_values[c] = &data_array[c*Eval::dofs_per_cell];
+ values_dofs = expanded_dof_values;
+ }
+ // These avoid compiler errors; they are only used in sensible context but
+ // compilers typically cannot detect when we access something like
+ // gradients_quad[2] only for dim==3.
+ const unsigned int d1 = dim>1?1:0;
+ const unsigned int d2 = dim>2?2:0;
- for (unsigned int c=0; c<n_components; c++)
+ switch (dim)
{
- VectorizedArray<typename FEEval::number_type> temp1[temp_size];
- VectorizedArray<typename FEEval::number_type> temp2[temp_size];
-
- switch (dim)
+ case 1:
+ for (unsigned int c=0; c<n_components; c++)
{
- case 3:
-
if (integrate_val == true)
- {
- // val
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], temp1);
- }
+ eval.template values<0,false,false> (values_quad[c], values_dofs[c]);
if (integrate_grad == true)
{
- // grad x: can sum to temporary value in temp1
if (integrate_val == true)
- fe_eval.template apply_gradients<0,false,true>
- (fe_eval.gradients_quad[c][0], temp1);
+ eval.template gradients<0,false,true> (gradients_quad[c][0], values_dofs[c]);
else
- fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], temp1);
+ eval.template gradients<0,false,false> (gradients_quad[c][0], values_dofs[c]);
}
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<1,false,false>
- (temp1, temp2);
- if (integrate_grad == true)
+ }
+ break;
+
+ case 2:
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ if (integrate_val == true)
{
- // grad y: can sum to temporary x value in temp2
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][1], temp1);
- fe_eval.template apply_gradients<1,false,true>
- (temp1, temp2);
+ // val
+ eval.template values<0,false,false> (values_quad[c], temp1);
+ //grad x
+ if (integrate_grad == true)
+ eval.template gradients<0,false,true> (gradients_quad[c][0], temp1);
+ eval.template values<1,false,false>(temp1, values_dofs[c]);
}
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<2,false,false>
- (temp2, fe_eval.values_dofs[c]);
if (integrate_grad == true)
{
- // grad z: can sum to temporary x and y value in output
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][2], temp1);
- fe_eval.template apply_values<1,false,false>
- (temp1, temp2);
- fe_eval.template apply_gradients<2,false,true>
- (temp2, fe_eval.values_dofs[c]);
+ // grad y
+ eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
+ if (integrate_val == false)
+ {
+ eval.template gradients<1,false,false>(temp1, values_dofs[c]);
+ //grad x
+ eval.template gradients<0,false,false> (gradients_quad[c][0], temp1);
+ eval.template values<1,false,true> (temp1, values_dofs[c]);
+ }
+ else
+ eval.template gradients<1,false,true>(temp1, values_dofs[c]);
}
+ }
+ break;
- break;
-
- case 2:
-
- // val
+ case 3:
+ for (unsigned int c=0; c<n_components; c++)
+ {
if (integrate_val == true)
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], temp1);
- if (integrate_grad == true)
{
- //grad x
- if (integrate_val == true)
- fe_eval.template apply_gradients<0,false,true>
- (fe_eval.gradients_quad[c][0], temp1);
- else
- fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], temp1);
+ // val
+ eval.template values<0,false,false> (values_quad[c], temp1);
+ //grad x: can sum to temporary value in temp1
+ if (integrate_grad == true)
+ eval.template gradients<0,false,true> (gradients_quad[c][0], temp1);
+ eval.template values<1,false,false>(temp1, temp2);
+ eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
+ if (integrate_grad == true)
+ eval.template gradients<1,false,true>(temp1, temp2);
+ eval.template values<2,false,false> (temp2, values_dofs[c]);
+ }
+ else if (integrate_grad == true)
+ {
+ eval.template gradients<0,false,false>(gradients_quad[c][0], temp1);
+ eval.template values<1,false,false> (temp1, temp2);
+ eval.template values<0,false,false> (gradients_quad[c][d1], temp1);
+ eval.template gradients<1,false,true>(temp1, temp2);
+ eval.template values<2,false,false> (temp2, values_dofs[c]);
}
- if (integrate_val || integrate_grad)
- fe_eval.template apply_values<1,false,false>
- (temp1, fe_eval.values_dofs[c]);
if (integrate_grad == true)
{
- // grad y
- fe_eval.template apply_values<0,false,false>
- (fe_eval.gradients_quad[c][1], temp1);
- fe_eval.template apply_gradients<1,false,true>
- (temp1, fe_eval.values_dofs[c]);
+ // grad z: can sum to temporary x and y value in output
+ eval.template values<0,false,false> (gradients_quad[c][d2], temp1);
+ eval.template values<1,false,false> (temp1, temp2);
+ eval.template gradients<2,false,true> (temp2, values_dofs[c]);
}
+ }
+ break;
- break;
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
- case 1:
+ // case FE_Q_DG0: add values, gradients and second derivatives are zero
+ if (type == MatrixFreeFunctions::tensor_symmetric_plus_dg0)
+ {
+ if (integrate_val)
+ for (unsigned int c=0; c<n_components; ++c)
+ {
+ values_dofs[c][Eval::dofs_per_cell] = values_quad[c][0];
+ for (unsigned int q=1; q<Eval::n_q_points; ++q)
+ values_dofs[c][Eval::dofs_per_cell] += values_quad[c][q];
+ }
+ else
+ for (unsigned int c=0; c<n_components; ++c)
+ values_dofs[c][Eval::dofs_per_cell] = VectorizedArray<Number>();
+ }
- if (integrate_grad == true)
- fe_eval.template apply_gradients<0,false,false>
- (fe_eval.gradients_quad[c][0], fe_eval.values_dofs[c]);
- if (integrate_val == true)
+ if (type == MatrixFreeFunctions::truncated_tensor)
+ {
+ unsigned int count_p = 0, count_q = 0;
+ for (unsigned int i=0; i<(dim>2?fe_degree+1:1); ++i)
+ {
+ for (unsigned int j=0; j<(dim>1?fe_degree+1-i:1); ++j)
{
- if (integrate_grad == true)
- fe_eval.template apply_values<0,false,true>
- (fe_eval.values_quad[c], fe_eval.values_dofs[c]);
- else
- fe_eval.template apply_values<0,false,false>
- (fe_eval.values_quad[c], fe_eval.values_dofs[c]);
+ for (unsigned int k=0; k<fe_degree+1-j-i; ++k, ++count_p, ++count_q)
+ {
+ for (unsigned int c=0; c<n_components; ++c)
+ values_dofs_actual[c][count_p] = expanded_dof_values[c][count_q];
+ }
+ count_q += j+i;
}
- break;
-
- default:
- Assert (false, ExcNotImplemented());
+ count_q += i*(fe_degree+1);
}
+ AssertDimension(count_q, Eval::dofs_per_cell);
}
-
-#ifdef DEBUG
- fe_eval.dof_values_initialized = true;
-#endif
}
-} // end of namespace internal
-
-
-
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-inline
-void
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::evaluate (const bool evaluate_val,
- const bool evaluate_grad,
- const bool evaluate_lapl)
-{
- internal::do_evaluate (*this, evaluate_val, evaluate_grad, evaluate_lapl);
-}
-
-
+ // This a specialization for Gauss-Lobatto elements where the 'values'
+ // operation is identity, which allows us to write shorter code.
+ template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
+ struct FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
+ fe_degree, n_q_points_1d, n_components, Number>
+ {
+ static
+ void evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl);
+
+ static
+ void integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ const bool integrate_val,
+ const bool integrate_grad);
+ };
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-inline
-void
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::integrate (const bool integrate_val,
- const bool integrate_grad)
-{
- internal::do_integrate (*this, integrate_val, integrate_grad);
-}
+ template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
+ inline
+ void
+ FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
+ fe_degree, n_q_points_1d, n_components, Number>
+ ::evaluate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ VectorizedArray<Number> *hessians_quad[][(dim*(dim+1))/2],
+ const bool evaluate_val,
+ const bool evaluate_grad,
+ const bool evaluate_lapl)
+ {
+ typedef EvaluatorTensorProduct<evaluate_evenodd, dim, fe_degree, fe_degree+1,
+ VectorizedArray<Number> > Eval;
+ Eval eval (shape_info.shape_val_evenodd, shape_info.shape_gra_evenodd,
+ shape_info.shape_hes_evenodd);
+
+ // These avoid compiler errors; they are only used in sensible context but
+ // compilers typically cannot detect when we access something like
+ // gradients_quad[2] only for dim==3.
+ const unsigned int d1 = dim>1?1:0;
+ const unsigned int d2 = dim>2?2:0;
+ const unsigned int d3 = dim>2?3:0;
+ const unsigned int d4 = dim>2?4:0;
+ const unsigned int d5 = dim>2?5:0;
+
+ switch (dim)
+ {
+ case 1:
+ if (evaluate_val == true)
+ std::memcpy (values_quad[0], values_dofs[0],
+ eval.dofs_per_cell * n_components *
+ sizeof (values_dofs[0][0]));
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ if (evaluate_grad == true)
+ eval.template gradients<0,true,false>(values_dofs[c], gradients_quad[c][0]);
+ if (evaluate_lapl == true)
+ eval.template hessians<0,true,false> (values_dofs[c], hessians_quad[c][0]);
+ }
+ break;
+ case 2:
+ if (evaluate_val == true)
+ {
+ std::memcpy (values_quad[0], values_dofs[0],
+ Eval::dofs_per_cell * n_components *
+ sizeof (values_dofs[0][0]));
+ }
+ if (evaluate_grad == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // grad x
+ eval.template gradients<0,true,false> (values_dofs[comp],
+ gradients_quad[comp][0]);
+ // grad y
+ eval.template gradients<1,true,false> (values_dofs[comp],
+ gradients_quad[comp][d1]);
+ }
+ if (evaluate_lapl == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // hess x
+ eval.template hessians<0,true,false> (values_dofs[comp],
+ hessians_quad[comp][0]);
+ // hess y
+ eval.template hessians<1,true,false> (values_dofs[comp],
+ hessians_quad[comp][d1]);
+
+ VectorizedArray<Number> temp1[Eval::dofs_per_cell];
+ // grad x grad y
+ eval.template gradients<0,true,false> (values_dofs[comp], temp1);
+ eval.template gradients<1,true,false> (temp1, hessians_quad[comp][d1+d1]);
+ }
+ break;
+ case 3:
+ if (evaluate_val == true)
+ {
+ std::memcpy (values_quad[0], values_dofs[0],
+ Eval::dofs_per_cell * n_components *
+ sizeof (values_dofs[0][0]));
+ }
+ if (evaluate_grad == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // grad x
+ eval.template gradients<0,true,false> (values_dofs[comp],
+ gradients_quad[comp][0]);
+ // grad y
+ eval.template gradients<1,true,false> (values_dofs[comp],
+ gradients_quad[comp][d1]);
+ // grad y
+ eval.template gradients<2,true,false> (values_dofs[comp],
+ gradients_quad[comp][d2]);
+ }
+ if (evaluate_lapl == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // grad x
+ eval.template hessians<0,true,false> (values_dofs[comp],
+ hessians_quad[comp][0]);
+ // grad y
+ eval.template hessians<1,true,false> (values_dofs[comp],
+ hessians_quad[comp][d1]);
+ // grad y
+ eval.template hessians<2,true,false> (values_dofs[comp],
+ hessians_quad[comp][d2]);
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-inline
-Point<dim,VectorizedArray<Number> >
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::quadrature_point (const unsigned int q) const
-{
- Assert (this->mapping_info.quadrature_points_initialized == true,
- ExcNotInitialized());
- AssertIndexRange (q, n_q_points);
+ VectorizedArray<Number> temp1[Eval::dofs_per_cell];
+ // grad xy
+ eval.template gradients<0,true,false> (values_dofs[comp], temp1);
+ eval.template gradients<1,true,false> (temp1, hessians_quad[comp][d3]);
+ // grad xz
+ eval.template gradients<2,true,false> (temp1, hessians_quad[comp][d4]);
+ // grad yz
+ eval.template gradients<1,true,false> (values_dofs[comp], temp1);
+ eval.template gradients<2,true,false> (temp1, hessians_quad[comp][d5]);
+ }
+ break;
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ }
- // Cartesian mesh: not all quadrature points are stored, only the
- // diagonal. Hence, need to find the tensor product index and retrieve the
- // value from that
- if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
- {
- Point<dim,VectorizedArray<Number> > point (false);
- switch (dim)
- {
- case 1:
- return this->quadrature_points[q];
- case 2:
- point[0] = this->quadrature_points[q%n_q_points_1d][0];
- point[1] = this->quadrature_points[q/n_q_points_1d][1];
- return point;
- case 3:
- point[0] = this->quadrature_points[q%n_q_points_1d][0];
- point[1] = this->quadrature_points[(q/n_q_points_1d)%n_q_points_1d][1];
- point[2] = this->quadrature_points[q/(n_q_points_1d*n_q_points_1d)][2];
- return point;
- default:
- Assert (false, ExcNotImplemented());
- return point;
- }
- }
- // all other cases: just return the respective data as it is fully stored
- else
- return this->quadrature_points[q];
-}
+ template <int dim, int fe_degree, int n_q_points_1d, int n_components, typename Number>
+ inline
+ void
+ FEEvaluationImpl<MatrixFreeFunctions::tensor_gausslobatto, dim,
+ fe_degree, n_q_points_1d, n_components, Number>
+ ::integrate (const MatrixFreeFunctions::ShapeInfo<Number> &shape_info,
+ VectorizedArray<Number> *values_dofs[],
+ VectorizedArray<Number> *values_quad[],
+ VectorizedArray<Number> *gradients_quad[][dim],
+ const bool integrate_val,
+ const bool integrate_grad)
+ {
+ typedef EvaluatorTensorProduct<evaluate_evenodd, dim, fe_degree, fe_degree+1,
+ VectorizedArray<Number> > Eval;
+ Eval eval (shape_info.shape_val_evenodd, shape_info.shape_gra_evenodd,
+ shape_info.shape_hes_evenodd);
+ // These avoid compiler errors; they are only used in sensible context but
+ // compilers typically cannot detect when we access something like
+ // gradients_quad[2] only for dim==3.
+ const unsigned int d1 = dim>1?1:0;
+ const unsigned int d2 = dim>2?2:0;
+ if (integrate_val == true)
+ std::memcpy (values_dofs[0], values_quad[0],
+ Eval::dofs_per_cell * n_components *
+ sizeof (values_dofs[0][0]));
+ switch (dim)
+ {
+ case 1:
+ for (unsigned int c=0; c<n_components; c++)
+ {
+ if (integrate_grad == true)
+ {
+ if (integrate_val == true)
+ eval.template gradients<0,false,true> (gradients_quad[c][0],
+ values_dofs[c]);
+ else
+ eval.template gradients<0,false,false> (gradients_quad[c][0],
+ values_dofs[c]);
+ }
+ }
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-template <int direction, bool dof_to_quad, bool add>
-inline
-void
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_values(const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
-{
- internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_values.begin(), in, out);
-}
+ break;
+ case 2:
+ if (integrate_grad == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // grad x: If integrate_val == true we have to add to the
+ // previous output
+ if (integrate_val == true)
+ eval.template gradients<0, false, true> (gradients_quad[comp][0],
+ values_dofs[comp]);
+ else
+ eval.template gradients<0, false, false> (gradients_quad[comp][0],
+ values_dofs[comp]);
+ // grad y
+ eval.template gradients<1, false, true> (gradients_quad[comp][d1],
+ values_dofs[comp]);
+ }
+ break;
+ case 3:
+ if (integrate_grad == true)
+ for (unsigned int comp=0; comp<n_components; comp++)
+ {
+ // grad x: If integrate_val == true we have to add to the
+ // previous output
+ if (integrate_val == true)
+ eval.template gradients<0, false, true> (gradients_quad[comp][0],
+ values_dofs[comp]);
+ else
+ eval.template gradients<0, false, false> (gradients_quad[comp][0],
+ values_dofs[comp]);
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-template <int direction, bool dof_to_quad, bool add>
-inline
-void
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_gradients(const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
-{
- internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
-}
+ // grad y
+ eval.template gradients<1, false, true> (gradients_quad[comp][d1],
+ values_dofs[comp]);
+ // grad z
+ eval.template gradients<2, false, true> (gradients_quad[comp][d2],
+ values_dofs[comp]);
+ }
+ break;
+
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+ }
+} // end of namespace internal
-template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
- typename Number>
-template <int direction, bool dof_to_quad, bool add>
-inline
-void
-FEEvaluationGeneral<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_hessians(const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
-{
- internal::apply_tensor_product<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_hessians.begin(), in, out);
-}
/*-------------------------- FEEvaluation -----------------------------------*/
const unsigned int fe_no,
const unsigned int quad_no)
:
- BaseClass (data_in, fe_no, quad_no)
+ BaseClass (data_in, fe_no, quad_no, fe_degree, n_q_points),
+ dofs_per_cell (this->data->dofs_per_cell)
{
- // check whether element is appropriate
-#ifdef DEBUG
- const double zero_tol =
- types_are_equal<Number,double>::value==true?1e-8:1e-7;
- std::string error_message = "FEEvaluation not appropriate.\n";
- error_message += " It assumes symmetry of quadrature points w.r.t. 0.5 \n";
- error_message += " and the basis functions starting from left and right.\n";
- error_message += "Try FEEvaluationGeneral<...> instead!";
-
- // symmetry for values
- const unsigned int n_dofs_1d = fe_degree + 1;
- for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
- for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_values[i*n_q_points_1d+j][0] -
- this->data.shape_values[(n_dofs_1d-i)*n_q_points_1d
- -j-1][0]) < zero_tol,
- ExcMessage(error_message));
-
- // shape values should be zero at for all basis functions except for one
- // where they are one in the middle
- if (n_q_points_1d%2 == 1 && n_dofs_1d%2 == 1)
- {
- for (int i=0; i<static_cast<int>(n_dofs_1d/2); ++i)
- Assert (std::fabs(this->data.shape_values[i*n_q_points_1d+
- n_q_points_1d/2][0]) < zero_tol,
- ExcMessage(error_message));
- Assert (std::fabs(this->data.shape_values[(n_dofs_1d/2)*n_q_points_1d+
- n_q_points_1d/2][0]-1.)< zero_tol,
- ExcMessage(error_message));
- }
-
- // skew-symmetry for gradient, zero of middle basis function in middle
- // quadrature point
- for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
- for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_gradients[i*n_q_points_1d+j][0] +
- this->data.shape_gradients[(n_dofs_1d-i)*n_q_points_1d-
- j-1][0]) < zero_tol,
- ExcMessage(error_message));
- if (n_dofs_1d%2 == 1 && n_q_points_1d%2 == 1)
- Assert (std::fabs(this->data.shape_gradients[(n_dofs_1d/2)*n_q_points_1d+
- (n_q_points_1d/2)][0]) < zero_tol,
- ExcMessage(error_message));
-
-
- // symmetry for Laplacian
- for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
- for (unsigned int j=0; j<n_q_points_1d; ++j)
- Assert (std::fabs(this->data.shape_hessians[i*n_q_points_1d+j][0] -
- this->data.shape_hessians[(n_dofs_1d-i)*n_q_points_1d-
- j-1][0]) < zero_tol,
- ExcMessage(error_message));
-#endif
-
- // Compute symmetric and skew-symmetric part of shape values for even-odd
- // decomposition
- for (unsigned int i=0; i<(fe_degree+1)/2; ++i)
- for (unsigned int q=0; q<(n_q_points_1d+1)/2; ++q)
- {
- shape_val_evenodd[i][q] =
- 0.5 * (this->data.shape_values[i*n_q_points_1d+q] +
- this->data.shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
- shape_val_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_values[i*n_q_points_1d+q] -
- this->data.shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
-
- shape_gra_evenodd[i][q] =
- 0.5 * (this->data.shape_gradients[i*n_q_points_1d+q] +
- this->data.shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
- shape_gra_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_gradients[i*n_q_points_1d+q] -
- this->data.shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
-
- shape_hes_evenodd[i][q] =
- 0.5 * (this->data.shape_hessians[i*n_q_points_1d+q] +
- this->data.shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
- shape_hes_evenodd[fe_degree-i][q] =
- 0.5 * (this->data.shape_hessians[i*n_q_points_1d+q] -
- this->data.shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
- }
- if (fe_degree % 2 == 0)
- for (unsigned int q=0; q<(n_q_points_1d+1)/2; ++q)
- {
- shape_val_evenodd[fe_degree/2][q] =
- this->data.shape_values[(fe_degree/2)*n_q_points_1d+q];
- shape_gra_evenodd[fe_degree/2][q] =
- this->data.shape_gradients[(fe_degree/2)*n_q_points_1d+q];
- shape_hes_evenodd[fe_degree/2][q] =
- this->data.shape_hessians[(fe_degree/2)*n_q_points_1d+q];
- }
+ check_template_arguments(fe_no);
+ set_data_pointers();
}
template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
typename Number>
inline
-void
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::evaluate (const bool evaluate_val,
- const bool evaluate_grad,
- const bool evaluate_lapl)
+::FEEvaluation (const MappingFEEvaluation<dim,Number> &geometry,
+ const DoFHandler<dim> &dof_handler,
+ const unsigned int first_selected_component)
+ :
+ BaseClass (geometry, dof_handler, first_selected_component),
+ dofs_per_cell (this->data->dofs_per_cell)
{
- internal::do_evaluate (*this, evaluate_val, evaluate_grad, evaluate_lapl);
+ check_template_arguments(numbers::invalid_unsigned_int);
+ set_data_pointers();
}
template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
typename Number>
inline
-void
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::integrate (bool integrate_val,bool integrate_grad)
+::FEEvaluation (const FEEvaluation &other)
+ :
+ BaseClass (other),
+ dofs_per_cell (this->data->dofs_per_cell)
{
- internal::do_integrate (*this, integrate_val, integrate_grad);
+ set_data_pointers();
}
template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
typename Number>
-template <int direction, bool dof_to_quad, bool add>
inline
void
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_values (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
+::set_data_pointers()
{
- // for linear elements, the even-odd decomposition is slower than the plain
- // evaluation (additions to create the symmetric and anti-symmetric part),
- // for all other orders, we choose even-odd
- if (fe_degree > 1 || n_q_points_1d > 3)
- internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add, 0>
- (shape_val_evenodd, in, out);
- else
- internal::apply_tensor_product_values<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_values.begin(), in, out);
+ AssertIndexRange(this->data->dofs_per_cell, tensor_dofs_per_cell+2);
+ const unsigned int desired_dofs_per_cell = this->data->dofs_per_cell;
+
+ // set the pointers to the correct position in the data array
+ for (unsigned int c=0; c<n_components_; ++c)
+ {
+ this->values_dofs[c] = &my_data_array[c*desired_dofs_per_cell];
+ this->values_quad[c] = &my_data_array[n_components*desired_dofs_per_cell+c*n_q_points];
+ for (unsigned int d=0; d<dim; ++d)
+ this->gradients_quad[c][d] = &my_data_array[n_components*(desired_dofs_per_cell+
+ n_q_points)
+ +
+ (c*dim+d)*n_q_points];
+ for (unsigned int d=0; d<(dim*dim+dim)/2; ++d)
+ this->hessians_quad[c][d] = &my_data_array[n_components*((dim+1)*n_q_points+
+ desired_dofs_per_cell)
+ +
+ (c*(dim*dim+dim)+d)*n_q_points];
+ }
+
+ switch (this->data->element_type)
+ {
+ case internal::MatrixFreeFunctions::tensor_symmetric:
+ evaluate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::evaluate;
+ integrate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::integrate;
+ break;
+
+ case internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0:
+ evaluate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::evaluate;
+ integrate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_symmetric_plus_dg0,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::integrate;
+ break;
+
+ case internal::MatrixFreeFunctions::tensor_general:
+ evaluate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_general,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::evaluate;
+ integrate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_general,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::integrate;
+ break;
+
+ case internal::MatrixFreeFunctions::tensor_gausslobatto:
+ evaluate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_gausslobatto,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::evaluate;
+ integrate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::tensor_gausslobatto,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::integrate;
+ break;
+
+ case internal::MatrixFreeFunctions::truncated_tensor:
+ evaluate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::truncated_tensor,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::evaluate;
+ integrate_funct =
+ internal::FEEvaluationImpl<internal::MatrixFreeFunctions::truncated_tensor,
+ dim, fe_degree, n_q_points_1d, n_components_,
+ Number>::integrate;
+ break;
+
+ default:
+ AssertThrow(false, ExcNotImplemented());
+ }
+
}
template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
typename Number>
-template <int direction, bool dof_to_quad, bool add>
inline
void
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_gradients (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
+::check_template_arguments(const unsigned int fe_no)
{
- if (fe_degree > 1 || n_q_points_1d > 3)
- internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add, 1>
- (shape_gra_evenodd, in, out);
- else
- internal::apply_tensor_product_gradients<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
+#ifdef DEBUG
+ // print error message when the dimensions do not match. Propose a possible
+ // fix
+ if (fe_degree != this->data->fe_degree
+ ||
+ n_q_points != this->data->n_q_points)
+ {
+ std::string message =
+ "-------------------------------------------------------\n";
+ message += "Illegal arguments in constructor/wrong template arguments!\n";
+ message += " Called --> FEEvaluation<dim,";
+ message += Utilities::int_to_string(fe_degree) + ",";
+ message += Utilities::int_to_string(n_q_points_1d);
+ message += "," + Utilities::int_to_string(n_components);
+ message += ",Number>(data, ";
+ message += Utilities::int_to_string(fe_no) + ", ";
+ message += Utilities::int_to_string(this->quad_no) + ")\n";
+
+ // check whether some other vector component has the correct number of
+ // points
+ unsigned int proposed_dof_comp = numbers::invalid_unsigned_int,
+ proposed_quad_comp = numbers::invalid_unsigned_int;
+ if (fe_no != numbers::invalid_unsigned_int)
+ {
+ if (fe_degree == this->data->fe_degree)
+ proposed_dof_comp = fe_no;
+ else
+ for (unsigned int no=0; no<this->matrix_info->n_components(); ++no)
+ if (this->matrix_info->get_shape_info(no,0,this->active_fe_index,0).fe_degree
+ == fe_degree)
+ {
+ proposed_dof_comp = no;
+ break;
+ }
+ if (n_q_points ==
+ this->mapping_info->mapping_data_gen[this->quad_no].n_q_points[this->active_quad_index])
+ proposed_quad_comp = this->quad_no;
+ else
+ for (unsigned int no=0; no<this->mapping_info->mapping_data_gen.size(); ++no)
+ if (this->mapping_info->mapping_data_gen[no].n_q_points[this->active_quad_index]
+ == n_q_points)
+ {
+ proposed_quad_comp = no;
+ break;
+ }
+ }
+ if (proposed_dof_comp != numbers::invalid_unsigned_int &&
+ proposed_quad_comp != numbers::invalid_unsigned_int)
+ {
+ if (proposed_dof_comp != fe_no)
+ message += "Wrong vector component selection:\n";
+ else
+ message += "Wrong quadrature formula selection:\n";
+ message += " Did you mean FEEvaluation<dim,";
+ message += Utilities::int_to_string(fe_degree) + ",";
+ message += Utilities::int_to_string(n_q_points_1d);
+ message += "," + Utilities::int_to_string(n_components);
+ message += ",Number>(data, ";
+ message += Utilities::int_to_string(proposed_dof_comp) + ", ";
+ message += Utilities::int_to_string(proposed_quad_comp) + ")?\n";
+ std::string correct_pos;
+ if (proposed_dof_comp != fe_no)
+ correct_pos = " ^ ";
+ else
+ correct_pos = " ";
+ if (proposed_quad_comp != this->quad_no)
+ correct_pos += " ^\n";
+ else
+ correct_pos += " \n";
+ message += " " + correct_pos;
+ }
+ // ok, did not find the numbers specified by the template arguments in
+ // the given list. Suggest correct template arguments
+ const unsigned int proposed_n_q_points_1d = static_cast<unsigned int>(std::pow(1.001*this->data->n_q_points,1./dim));
+ message += "Wrong template arguments:\n";
+ message += " Did you mean FEEvaluation<dim,";
+ message += Utilities::int_to_string(this->data->fe_degree) + ",";
+ message += Utilities::int_to_string(proposed_n_q_points_1d);
+ message += "," + Utilities::int_to_string(n_components);
+ message += ",Number>(data, ";
+ message += Utilities::int_to_string(fe_no) + ", ";
+ message += Utilities::int_to_string(this->quad_no) + ")?\n";
+ std::string correct_pos;
+ if (this->data->fe_degree != fe_degree)
+ correct_pos = " ^";
+ else
+ correct_pos = " ";
+ if (proposed_n_q_points_1d != n_q_points_1d)
+ correct_pos += " ^\n";
+ else
+ correct_pos += " \n";
+ message += " " + correct_pos;
+
+ Assert (fe_degree == this->data->fe_degree &&
+ n_q_points == this->data->n_q_points,
+ ExcMessage(message));
+ }
+ if (fe_no != numbers::invalid_unsigned_int)
+ {
+ AssertDimension (n_q_points,
+ this->mapping_info->mapping_data_gen[this->quad_no].
+ n_q_points[this->active_quad_index]);
+ AssertDimension (this->data->dofs_per_cell * this->n_fe_components,
+ this->dof_info->dofs_per_cell[this->active_fe_index]);
+ }
+#endif
}
-// Laplacian operator application. Very similar to value application because
-// the same symmetry relations hold. However, it is not possible to omit some
-// values that are zero for the values
template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
typename Number>
-template <int direction, bool dof_to_quad, bool add>
inline
-void
+Point<dim,VectorizedArray<Number> >
FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
-::apply_hessians (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
+::quadrature_point (const unsigned int q) const
{
- if (fe_degree > 1 || n_q_points_1d > 3)
- internal::apply_tensor_product_evenodd<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add, 2>
- (shape_hes_evenodd, in, out);
- else
- internal::apply_tensor_product_hessians<dim,fe_degree,n_q_points_1d,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_hessians.begin(), in, out);
-}
-
-
-
-/*------------------------- FEEvaluationGL ----------------------------------*/
+ Assert (this->mapping_info->quadrature_points_initialized == true,
+ ExcNotInitialized());
+ AssertIndexRange (q, n_q_points);
-template <int dim, int fe_degree, int n_components_, typename Number>
-inline
-FEEvaluationGL<dim,fe_degree,n_components_,Number>
-::FEEvaluationGL (const MatrixFree<dim,Number> &data_in,
- const unsigned int fe_no,
- const unsigned int quad_no)
- :
- BaseClass (data_in, fe_no, quad_no)
-{
-#ifdef DEBUG
- std::string error_mess = "FEEvaluationGL not appropriate. It assumes:\n";
- error_mess += " - identity operation for shape values\n";
- error_mess += " - zero diagonal at interior points for gradients\n";
- error_mess += " - gradient equal to unity at element boundary\n";
- error_mess += "Try FEEvaluation<...> instead!";
-
- const double zero_tol =
- types_are_equal<Number,double>::value==true?1e-9:1e-7;
-
- const unsigned int n_points_1d = fe_degree+1;
- for (unsigned int i=0; i<n_points_1d; ++i)
- for (unsigned int j=0; j<n_points_1d; ++j)
- if (i!=j)
- {
- Assert (std::fabs(this->data.shape_values[i*n_points_1d+j][0])<zero_tol,
- ExcMessage (error_mess.c_str()));
- }
- else
+ // Cartesian mesh: not all quadrature points are stored, only the
+ // diagonal. Hence, need to find the tensor product index and retrieve the
+ // value from that
+ if (this->cell_type == internal::MatrixFreeFunctions::cartesian)
+ {
+ Point<dim,VectorizedArray<Number> > point (false);
+ switch (dim)
{
- Assert (std::fabs(this->data.shape_values[i*n_points_1d+
- j][0]-1.)<zero_tol,
- ExcMessage (error_mess.c_str()));
+ case 1:
+ return this->quadrature_points[q];
+ case 2:
+ point[0] = this->quadrature_points[q%n_q_points_1d][0];
+ point[1] = this->quadrature_points[q/n_q_points_1d][1];
+ return point;
+ case 3:
+ point[0] = this->quadrature_points[q%n_q_points_1d][0];
+ point[1] = this->quadrature_points[(q/n_q_points_1d)%n_q_points_1d][1];
+ point[2] = this->quadrature_points[q/(n_q_points_1d*n_q_points_1d)][2];
+ return point;
+ default:
+ Assert (false, ExcNotImplemented());
+ return point;
}
- for (unsigned int i=1; i<n_points_1d-1; ++i)
- Assert (std::fabs(this->data.shape_gradients[i*n_points_1d+i][0])<zero_tol,
- ExcMessage (error_mess.c_str()));
- Assert (std::fabs(this->data.shape_gradients[n_points_1d-1][0]-
- (n_points_1d%2==0 ? -1. : 1.)) < zero_tol,
- ExcMessage (error_mess.c_str()));
-#endif
+ }
+ // all other cases: just return the respective data as it is fully stored
+ else
+ return this->quadrature_points[q];
}
-template <int dim, int fe_degree, int n_components_, typename Number>
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
inline
void
-FEEvaluationGL<dim,fe_degree,n_components_,Number>
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
::evaluate (const bool evaluate_val,
const bool evaluate_grad,
const bool evaluate_lapl)
{
- Assert (this->cell != numbers::invalid_unsigned_int,
- ExcNotInitialized());
Assert (this->dof_values_initialized == true,
internal::ExcAccessToUninitializedField());
- if (evaluate_val == true)
- {
- std::memcpy (&this->values_quad[0][0], &this->values_dofs[0][0],
- dofs_per_cell * n_components *
- sizeof (this->values_dofs[0][0]));
+ // Select algorithm matching the element type at run time (the function
+ // pointer is easy to predict, so negligible in cost)
+ evaluate_funct (*this->data, &this->values_dofs[0],
+ this->values_quad, this->gradients_quad, this->hessians_quad,
+ evaluate_val, evaluate_grad, evaluate_lapl);
+
#ifdef DEBUG
- this->values_quad_initialized = true;
-#endif
- }
- // separate implementation here compared to the general case because the
- // values are an identity operation
+ if (evaluate_val == true)
+ this->values_quad_initialized = true;
if (evaluate_grad == true)
- {
- for (unsigned int comp=0; comp<n_components; comp++)
- {
- if (dim == 3)
- {
- // grad x
- apply_gradients<0,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][0]);
- // grad y
- apply_gradients<1,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][1]);
- // grad y
- apply_gradients<2,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][2]);
- }
- else if (dim == 2)
- {
- // grad x
- apply_gradients<0,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][0]);
- // grad y
- apply_gradients<1,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][1]);
- }
- else if (dim == 1)
- apply_gradients<0,true,false> (this->values_dofs[comp],
- this->gradients_quad[comp][0]);
- }
-#ifdef DEBUG
- this->gradients_quad_initialized = true;
-#endif
- }
+ this->gradients_quad_initialized = true;
if (evaluate_lapl == true)
- {
- for (unsigned int comp=0; comp<n_components; comp++)
- {
- if (dim == 3)
- {
- // grad x
- this->template apply_hessians<0,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][0]);
- // grad y
- this->template apply_hessians<1,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][1]);
- // grad y
- this->template apply_hessians<2,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][2]);
-
- VectorizedArray<Number> temp1[n_q_points];
- // grad xy
- apply_gradients<0,true,false> (this->values_dofs[comp], temp1);
- apply_gradients<1,true,false> (temp1, this->hessians_quad[comp][3]);
- // grad xz
- apply_gradients<2,true,false> (temp1, this->hessians_quad[comp][4]);
- // grad yz
- apply_gradients<1,true,false> (this->values_dofs[comp], temp1);
- apply_gradients<2,true,false> (temp1, this->hessians_quad[comp][5]);
- }
- else if (dim == 2)
- {
- // grad x
- this->template apply_hessians<0,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][0]);
- // grad y
- this->template apply_hessians<1,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][1]);
- VectorizedArray<Number> temp1[n_q_points];
- // grad xy
- apply_gradients<0,true,false> (this->values_dofs[comp], temp1);
- apply_gradients<1,true,false> (temp1, this->hessians_quad[comp][2]);
- }
- else if (dim == 1)
- this->template apply_hessians<0,true,false> (this->values_dofs[comp],
- this->hessians_quad[comp][0]);
- }
-#ifdef DEBUG
- this->hessians_quad_initialized = true;
+ this->hessians_quad_initialized = true;
#endif
- }
}
-template <int dim, int fe_degree, int n_components_, typename Number>
+template <int dim, int fe_degree, int n_q_points_1d, int n_components_,
+ typename Number>
inline
void
-FEEvaluationGL<dim,fe_degree,n_components_,Number>
-::integrate (const bool integrate_val, const bool integrate_grad)
+FEEvaluation<dim,fe_degree,n_q_points_1d,n_components_,Number>
+::integrate (bool integrate_val,bool integrate_grad)
{
- Assert (this->cell != numbers::invalid_unsigned_int,
- ExcNotInitialized());
if (integrate_val == true)
Assert (this->values_quad_submitted == true,
internal::ExcAccessToUninitializedField());
if (integrate_grad == true)
Assert (this->gradients_quad_submitted == true,
internal::ExcAccessToUninitializedField());
- if (integrate_val == true)
- std::memcpy (&this->values_dofs[0][0], &this->values_quad[0][0],
- dofs_per_cell * n_components *
- sizeof (this->values_dofs[0][0]));
- if (integrate_grad == true)
- {
- for (unsigned int comp=0; comp<n_components; comp++)
- {
- if (dim == 3)
- {
- // grad x: If integrate_val == true we have to add to the previous output
- if (integrate_val == true)
- apply_gradients<0, false, true> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
- else
- apply_gradients<0, false, false> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
-
- // grad y: can sum to temporary x value in temp2
- apply_gradients<1, false, true> (this->gradients_quad[comp][1],
- this->values_dofs[comp]);
-
- // grad z: can sum to temporary x and y value in output
- apply_gradients<2, false, true> (this->gradients_quad[comp][2],
- this->values_dofs[comp]);
- }
- else if (dim == 2)
- {
- // grad x: If integrate_val == true we have to add to the previous output
- if (integrate_val == true)
- apply_gradients<0, false, true> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
- else
- apply_gradients<0, false, false> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
-
- // grad y: can sum to temporary x value in temp2
- apply_gradients<1, false, true> (this->gradients_quad[comp][1],
- this->values_dofs[comp]);
- }
- else if (dim == 1)
- {
- if (integrate_val == true)
- apply_gradients<0, false, true> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
- else
- apply_gradients<0, false, false> (this->gradients_quad[comp][0],
- this->values_dofs[comp]);
- }
- }
- }
+ // Select algorithm matching the element type at run time (the function
+ // pointer is easy to predict, so negligible in cost)
+ integrate_funct (*this->data, this->values_dofs, this->values_quad,
+ this->gradients_quad, integrate_val, integrate_grad);
#ifdef DEBUG
this->dof_values_initialized = true;
-template <int dim, int fe_degree, int n_components_, typename Number>
-template <int direction, bool dof_to_quad, bool add>
-inline
-void
-FEEvaluationGL<dim,fe_degree,n_components_,Number>
-::apply_gradients (const VectorizedArray<Number> in [],
- VectorizedArray<Number> out [])
-{
- internal::apply_tensor_product_gradients_gl<dim,fe_degree,
- VectorizedArray<Number>, direction, dof_to_quad, add>
- (this->data.shape_gradients.begin(), in, out);
-}
-
-
#endif // ifndef DOXYGEN
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__matrix_free_mapping_fe_evaluation_h
+#define __deal2__matrix_free_mapping_fe_evaluation_h
+
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
+#include <deal.II/matrix_free/shape_info.h>
+#include <deal.II/matrix_free/mapping_info.h>
+#include <deal.II/fe/fe_values.h>
+#include <deal.II/fe/fe_nothing.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * This class provides evaluated mapping information using standard deal.II
+ * information in a form that FEEvaluation and friends can use for vectorized
+ * access. Since no vectorization over cells is available with the
+ * DoFHandler/Triangulation cell iterators, the interface to FEEvaluation's
+ * vectorization model is to use @p VectorizedArray::n_array_element copies of
+ * the same element. This interface is thus primarily useful for evaluating
+ * several operators on the same cell, e.g., when assembling cell matrices.
+ *
+ * As opposed to the standard Mapping classes in deal.II, this class does not
+ * actually provide a boundary description that can be used to evaluate the
+ * geometry, but it rather provides the evaluated geometry from a given
+ * deal.II mapping (as passed to the constructor of this class) in a form
+ * accessible to FEEvaluation.
+ *
+ * @author Martin Kronbichler, 2014
+ */
+template <int dim, typename Number=double>
+class MappingFEEvaluation : public Subscriptor
+{
+public:
+ /**
+ * Constructor, similar to FEValues. Since this class only evaluates the
+ * geometry, no finite element has to be specified and the simplest element,
+ * FE_Nothing, is used internally for the underlying FEValues object.
+ */
+ MappingFEEvaluation (const Mapping<dim> &mapping,
+ const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags);
+
+ /**
+ * Constructor. Instead of providing a mapping, use MappingQ1.
+ */
+ MappingFEEvaluation (const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags);
+
+ /**
+ * Initialize with the given cell iterator. This works for all type of
+ * iterators that can be converted into a Triangulation::cell_iterator
+ * (DoFHandler::cell_iterator or Triangulation::cell_iterator).
+ */
+ template <typename ITERATOR>
+ void reinit(ITERATOR cell);
+
+ /**
+ * Return a triangulation iterator to the current cell.
+ */
+ typename Triangulation<dim>::cell_iterator get_cell () const;
+
+ /**
+ * Return a reference to the underlying FEValues object that evaluates
+ * certain quantities (only mapping-related ones like Jacobians or mapped
+ * quadrature points are accessible, as no finite element data is actually
+ * used).
+ */
+ const FEValues<dim>& get_fe_values () const;
+
+ /**
+ * Return a vector of inverse transpose Jacobians. For compatibility with
+ * FEEvaluation, it returns tensors of vectorized arrays, even though all
+ * components are equal.
+ */
+ const AlignedVector<Tensor<2,dim,VectorizedArray<Number> > >&
+ get_inverse_jacobians() const;
+
+ /**
+ * Return a vector of quadrature weights times the Jacobian determinant
+ * (JxW). For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<VectorizedArray<Number> >&
+ get_JxW_values() const;
+
+ /**
+ * Return a vector of quadrature points in real space on the given
+ * cell. For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<Point<dim,VectorizedArray<Number> > >&
+ get_quadrature_points() const;
+
+ /**
+ * Return a vector of quadrature points in real space on the given
+ * cell. For compatibility with FEEvaluation, it returns tensors of
+ * vectorized arrays, even though all components are equal.
+ */
+ const AlignedVector<Tensor<1,dim,VectorizedArray<Number> > >&
+ get_normal_vectors() const;
+
+ /**
+ * Return a reference to 1D quadrature underlying this object.
+ */
+ const Quadrature<1>&
+ get_quadrature () const;
+
+private:
+ /**
+ * Dummy finite element object necessary for initializing the FEValues
+ * object.
+ */
+ FE_Nothing<dim> fe_dummy;
+
+ /**
+ * An underlying FEValues object that performs the (scalar) evaluation.
+ */
+ FEValues<dim> fe_values;
+
+ /**
+ * Get 1D quadrature formula to be used for reinitializing shape info.
+ */
+ const Quadrature<1> quadrature_1d;
+
+ /**
+ * Inverse Jacobians, stored in vectorized array form.
+ */
+ AlignedVector<Tensor<2,dim,VectorizedArray<Number> > > inverse_jacobians;
+
+ /**
+ * Stored Jacobian determinants and quadrature weights
+ */
+ AlignedVector<VectorizedArray<Number> > jxw_values;
+
+ /**
+ * Stored quadrature points
+ */
+ AlignedVector<Point<dim,VectorizedArray<Number> > > quadrature_points;
+
+ /**
+ * Stored normal vectors (for face integration)
+ */
+ AlignedVector<Tensor<1,dim,VectorizedArray<Number> > > normal_vectors;
+};
+
+
+/*----------------------- Inline functions ----------------------------------*/
+
+template <int dim, typename Number>
+inline
+MappingFEEvaluation<dim,Number>::MappingFEEvaluation (const Mapping<dim> &mapping,
+ const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags)
+ :
+ fe_values(mapping, fe_dummy, Quadrature<dim>(quadrature),
+ internal::MatrixFreeFunctions::MappingInfo<dim,Number>::compute_update_flags(update_flags)),
+ quadrature_1d(quadrature),
+ inverse_jacobians(fe_values.get_quadrature().size()),
+ jxw_values(fe_values.get_quadrature().size()),
+ quadrature_points(fe_values.get_quadrature().size()),
+ normal_vectors(fe_values.get_quadrature().size())
+{
+ Assert(!(fe_values.get_update_flags() & update_jacobian_grads),
+ ExcNotImplemented());
+}
+
+
+
+template <int dim, typename Number>
+inline
+MappingFEEvaluation<dim,Number>::MappingFEEvaluation (const Quadrature<1> &quadrature,
+ const UpdateFlags update_flags)
+ :
+ fe_values(fe_dummy, Quadrature<dim>(quadrature),
+ internal::MatrixFreeFunctions::MappingInfo<dim,Number>::compute_update_flags(update_flags)),
+ quadrature_1d(quadrature),
+ inverse_jacobians(fe_values.get_quadrature().size()),
+ jxw_values(fe_values.get_quadrature().size()),
+ quadrature_points(fe_values.get_quadrature().size()),
+ normal_vectors(fe_values.get_quadrature().size())
+{
+ Assert(!(fe_values.get_update_flags() & update_jacobian_grads),
+ ExcNotImplemented());
+}
+
+
+
+template <int dim, typename Number>
+template <typename ITERATOR>
+inline
+void
+MappingFEEvaluation<dim,Number>::reinit(ITERATOR cell)
+{
+ fe_values.reinit(static_cast<typename Triangulation<dim>::cell_iterator>(cell));
+ for (unsigned int q=0; q<fe_values.get_quadrature().size(); ++q)
+ {
+ if (fe_values.get_update_flags() & update_inverse_jacobians)
+ for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int e=0; e<dim; ++e)
+ inverse_jacobians[q][d][e] = fe_values.inverse_jacobian(q)[e][d];
+ if (fe_values.get_update_flags() & update_quadrature_points)
+ for (unsigned int d=0; d<dim; ++d)
+ quadrature_points[q][d] = fe_values.quadrature_point(q)[d];
+ if (fe_values.get_update_flags() & update_normal_vectors)
+ for (unsigned int d=0; d<dim; ++d)
+ normal_vectors[q][d] = fe_values.normal_vector(q)[d];
+ if (fe_values.get_update_flags() & update_JxW_values)
+ jxw_values[q] = fe_values.JxW(q);
+ }
+}
+
+
+
+template <int dim, typename Number>
+inline
+typename Triangulation<dim>::cell_iterator
+MappingFEEvaluation<dim,Number>::get_cell() const
+{
+ return fe_values.get_cell();
+}
+
+
+
+template <int dim, typename Number>
+inline
+const FEValues<dim>&
+MappingFEEvaluation<dim,Number>::get_fe_values() const
+{
+ return fe_values;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Tensor<2,dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_inverse_jacobians() const
+{
+ return inverse_jacobians;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Tensor<1,dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_normal_vectors() const
+{
+ return normal_vectors;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<Point<dim,VectorizedArray<Number> > >&
+MappingFEEvaluation<dim,Number>::get_quadrature_points() const
+{
+ return quadrature_points;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const AlignedVector<VectorizedArray<Number> >&
+MappingFEEvaluation<dim,Number>::get_JxW_values() const
+{
+ return jxw_values;
+}
+
+
+
+template <int dim, typename Number>
+inline
+const Quadrature<1>&
+MappingFEEvaluation<dim,Number>::get_quadrature() const
+{
+ return quadrature_1d;
+}
+
+
+#ifndef DOXYGEN
+
+
+#endif // ifndef DOXYGEN
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/exceptions.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
#include <deal.II/hp/q_collection.h>
#include <deal.II/fe/fe.h>
#include <deal.II/fe/mapping.h>
* Helper function to determine which update flags must be set in the
* internal functions to initialize all data as requested by the user.
*/
- UpdateFlags
+ static UpdateFlags
compute_update_flags (const UpdateFlags update_flags,
- const std::vector<dealii::hp::QCollection<1> > &quad) const;
+ const std::vector<dealii::hp::QCollection<1> > &quad =
+ std::vector<dealii::hp::QCollection<1> >());
/**
* Returns the type of a given cell as detected during initialization.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
UpdateFlags
MappingInfo<dim,Number>::
compute_update_flags (const UpdateFlags update_flags,
- const std::vector<dealii::hp::QCollection<1> > &quad) const
+ const std::vector<dealii::hp::QCollection<1> > &quad)
{
// this class is build around the evaluation this class is build around
// the evaluation of inverse gradients, so compute them in any case
// one quadrature point on the first component, but more points on later
// components, we need to have Jacobian gradients anyway in order to
// determine whether the Jacobian is constant throughout a cell
- bool formula_with_one_point = false;
- for (unsigned int i=0; i<quad[0].size(); ++i)
- if (quad[0][i].size() == 1)
- {
- formula_with_one_point = true;
- break;
- }
- if (formula_with_one_point == true)
- for (unsigned int comp=1; comp<quad.size(); ++comp)
- for (unsigned int i=0; i<quad[comp].size(); ++i)
- if (quad[comp][i].size() > 1)
+ if (quad.empty() == false)
+ {
+ bool formula_with_one_point = false;
+ for (unsigned int i=0; i<quad[0].size(); ++i)
+ if (quad[0][i].size() == 1)
{
- new_flags |= update_jacobian_grads;
- goto end_set;
+ formula_with_one_point = true;
+ break;
}
-end_set:
+ if (formula_with_one_point == true)
+ for (unsigned int comp=1; comp<quad.size(); ++comp)
+ for (unsigned int i=0; i<quad[comp].size(); ++i)
+ if (quad[comp][i].size() > 1)
+ {
+ new_flags |= update_jacobian_grads;
+ }
+ }
return new_flags;
}
memory += MemoryConsumption::memory_consumption (affine_data);
memory += MemoryConsumption::memory_consumption (cartesian_data);
memory += MemoryConsumption::memory_consumption (cell_type);
- memory += sizeof (this);
+ memory += sizeof (*this);
return memory;
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
const std::vector<hp::QCollection<1> > &quad,
const typename MatrixFree<dim,Number>::AdditionalData additional_data)
{
+
+ // Reads out the FE information and stores the shape function values,
+ // gradients and Hessians for quadrature points.
+ {
+ const unsigned int n_fe = dof_handler.size();
+ const unsigned int n_quad = quad.size();
+ shape_info.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
+ for (unsigned int no=0; no<n_fe; no++)
+ for (unsigned int nq =0; nq<n_quad; nq++)
+ {
+ AssertDimension (quad[nq].size(), 1);
+ shape_info(no,nq,0,0).reinit(quad[nq][0], dof_handler[no]->get_fe());
+ }
+ }
+
if (additional_data.initialize_indices == true)
{
clear();
}
}
- // Reads out the FE information and stores the shape function values,
- // gradients and Hessians for quadrature points.
- const unsigned int n_fe = dof_handler.size();
- const unsigned int n_quad = quad.size();
- shape_info.reinit (TableIndices<4>(n_fe, n_quad, 1, 1));
- for (unsigned int no=0; no<n_fe; no++)
- {
- const FiniteElement<dim> &fe = dof_handler[no]->get_fe();
- for (unsigned int nq =0; nq<n_quad; nq++)
- {
- AssertDimension (quad[nq].size(), 1);
- shape_info(no,nq,0,0).reinit(quad[nq][0], fe.base_element(0));
- }
- }
-
// Evaluates transformations from unit to real cell, Jacobian determinants,
// quadrature points in real space, based on the ordering of the cells
// determined in @p extract_local_to_global_indices. The algorithm assumes
const std::vector<hp::QCollection<1> > &quad,
const typename MatrixFree<dim,Number>::AdditionalData additional_data)
{
+ // Reads out the FE information and stores the shape function values,
+ // gradients and Hessians for quadrature points.
+ {
+ const unsigned int n_components = dof_handler.size();
+ const unsigned int n_quad = quad.size();
+ unsigned int n_fe_in_collection = 0;
+ for (unsigned int i=0; i<n_components; ++i)
+ n_fe_in_collection = std::max (n_fe_in_collection,
+ dof_handler[i]->get_fe().size());
+ unsigned int n_quad_in_collection = 0;
+ for (unsigned int q=0; q<n_quad; ++q)
+ n_quad_in_collection = std::max (n_quad_in_collection, quad[q].size());
+ shape_info.reinit (TableIndices<4>(n_components, n_quad,
+ n_fe_in_collection,
+ n_quad_in_collection));
+ for (unsigned int no=0; no<n_components; no++)
+ for (unsigned int fe_no=0; fe_no<dof_handler[no]->get_fe().size(); ++fe_no)
+ for (unsigned int nq =0; nq<n_quad; nq++)
+ for (unsigned int q_no=0; q_no<quad[nq].size(); ++q_no)
+ shape_info(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
+ dof_handler[no]->get_fe()[fe_no]);
+ }
+
if (additional_data.initialize_indices == true)
{
clear();
}
}
- // Reads out the FE information and stores the shape function values,
- // gradients and Hessians for quadrature points.
- const unsigned int n_components = dof_handler.size();
- const unsigned int n_quad = quad.size();
- unsigned int n_fe_in_collection = 0;
- for (unsigned int i=0; i<n_components; ++i)
- n_fe_in_collection = std::max (n_fe_in_collection,
- dof_handler[i]->get_fe().size());
- unsigned int n_quad_in_collection = 0;
- for (unsigned int q=0; q<n_quad; ++q)
- n_quad_in_collection = std::max (n_quad_in_collection, quad[q].size());
- shape_info.reinit (TableIndices<4>(n_components, n_quad,
- n_fe_in_collection,
- n_quad_in_collection));
- for (unsigned int no=0; no<n_components; no++)
- for (unsigned int fe_no=0; fe_no<dof_handler[no]->get_fe().size(); ++fe_no)
- {
- const FiniteElement<dim> &fe = dof_handler[no]->get_fe()[fe_no];
- for (unsigned int nq =0; nq<n_quad; nq++)
- for (unsigned int q_no=0; q_no<quad[nq].size(); ++q_no)
- shape_info(no,nq,fe_no,q_no).reinit (quad[nq][q_no],
- fe.base_element(0));
- }
-
// Evaluates transformations from unit to real cell, Jacobian determinants,
// quadrature points in real space, based on the ordering of the cells
// determined in @p extract_local_to_global_indices.
template <int dim, typename Number>
void MatrixFree<dim,Number>::initialize_indices
(const std::vector<const ConstraintMatrix *> &constraint,
- const std::vector<IndexSet> &locally_owned_set)
+ const std::vector<IndexSet> &locally_owned_set)
{
const unsigned int n_fe = dof_handlers.n_dof_handlers;
const unsigned int n_active_cells = cell_level_index.size();
fes.back()->dofs_per_cell);
}
- lexicographic_inv[no].resize (fes.size());
for (unsigned int fe_index = 0; fe_index<fes.size(); ++fe_index)
{
const FiniteElement<dim> &fe = *fes[fe_index];
Assert (fe.n_base_elements() == 1,
- ExcMessage ("MatrixFree only works for DoFHandler with one base element"));
+ ExcMessage ("MatrixFree currently only works for DoFHandler with one base element"));
const unsigned int n_fe_components = fe.element_multiplicity (0);
// cache number of finite elements and dofs_per_cell
dof_info[no].dimension = dim;
dof_info[no].n_components = n_fe_components;
- // get permutation that gives lexicographic renumbering of the cell
- // dofs renumber (this is necessary for FE_Q, for example, since
- // there the vertex DoFs come first, which is incompatible with the
- // lexicographic ordering necessary to apply tensor products
- // efficiently)
- const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *fe_poly =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>
- (&fe.base_element(0));
- const FE_Poly<TensorProductPolynomials<dim,Polynomials::
- PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim,
- Polynomials::PiecewisePolynomial<double> >,dim,dim>*>
- (&fe.base_element(0));
-
- // This class currently only works for elements derived from
- // FE_Poly<TensorProductPolynomials<dim>,dim,dim> or piecewise
- // polynomials. For any other element, the dynamic casts above will
- // fail and give fe_poly == 0.
- Assert (fe_poly != 0 || fe_poly_piece != 0, ExcNotImplemented());
- if (n_fe_components == 1)
- {
- if (fe_poly != 0)
- lexicographic_inv[no][fe_index] =
- fe_poly->get_poly_space_numbering_inverse();
- else
- lexicographic_inv[no][fe_index] =
- fe_poly_piece->get_poly_space_numbering_inverse();
- AssertDimension (lexicographic_inv[no][fe_index].size(),
- dof_info[no].dofs_per_cell[fe_index]);
- }
- else
- {
- // ok, we have more than one component
- Assert (n_fe_components > 1, ExcInternalError());
- std::vector<unsigned int> scalar_lex =
- fe_poly != 0 ? fe_poly->get_poly_space_numbering() :
- fe_poly_piece->get_poly_space_numbering();
- AssertDimension (scalar_lex.size() * n_fe_components,
- dof_info[no].dofs_per_cell[fe_index]);
- std::vector<unsigned int> lexicographic (dof_info[no].dofs_per_cell[fe_index]);
- for (unsigned int comp=0; comp<n_fe_components; ++comp)
- for (unsigned int i=0; i<scalar_lex.size(); ++i)
- lexicographic[fe.component_to_system_index(comp,i)]
- = scalar_lex.size () * comp + scalar_lex[i];
-
- // invert numbering
- lexicographic_inv[no][fe_index] =
- Utilities::invert_permutation(lexicographic);
- }
- AssertDimension (lexicographic_inv[no][fe_index].size(),
+ AssertDimension (shape_info(no,0,fe_index,0).lexicographic_numbering.size(),
dof_info[no].dofs_per_cell[fe_index]);
}
local_dof_indices.resize (dof_info[no].dofs_per_cell[0]);
cell_it->get_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][0],
+ shape_info(no,0,0,0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
local_dof_indices.resize (dof_info[no].dofs_per_cell[0]);
cell_it->get_mg_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][0],
+ shape_info(no,0,0,0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
local_dof_indices.resize (cell_it->get_fe().dofs_per_cell);
cell_it->get_dof_indices(local_dof_indices);
dof_info[no].read_dof_indices (local_dof_indices,
- lexicographic_inv[no][cell_it->active_fe_index()],
+ shape_info(no,0,cell_it->active_fe_index(),0).lexicographic_numbering,
*constraint[no], counter,
constraint_values,
cell_at_boundary);
memory += MemoryConsumption::memory_consumption (constraint_pool_data);
memory += MemoryConsumption::memory_consumption (constraint_pool_row_index);
memory += MemoryConsumption::memory_consumption (task_info);
- memory += sizeof(this);
+ memory += sizeof(*this);
memory += mapping_info.memory_consumption();
return memory;
}
std::size_t
TaskInfo::memory_consumption () const
{
- return (MemoryConsumption::memory_consumption (partition_color_blocks_row_index) +
+ return (sizeof(*this)+
+ MemoryConsumption::memory_consumption (partition_color_blocks_row_index) +
MemoryConsumption::memory_consumption (partition_color_blocks_data)+
MemoryConsumption::memory_consumption (partition_evens) +
MemoryConsumption::memory_consumption (partition_odds) +
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2011 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef __deal2__matrix_free_operators_h
+#define __deal2__matrix_free_operators_h
+
+
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/vectorization.h>
+
+#include <deal.II/matrix_free/fe_evaluation.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+namespace MatrixFreeOperators
+{
+ /**
+ * This class implements the operation of the action of the inverse of a mass
+ * matrix on an element for the special case of an evaluation object with as
+ * many quadrature points as there are cell degrees of freedom. It uses
+ * algorithms from FEEvaluation and produces the exact mass matrix for DGQ
+ * elements. This algorithm uses tensor products of inverse 1D shape matrices
+ * over quadrature points, so the inverse operation is exactly as expensive as
+ * applying the forward operator on each cell. Of course, for continuous
+ * finite elements this operation does not produce the inverse of a mass
+ * operation as the coupling between the elements cannot be considered by this
+ * operation.
+ *
+ * The equation may contain variable coefficients, so the user is required to
+ * provide an array for the inverse of the local coefficient (this class
+ * provide a helper method 'fill_inverse_JxW_values' to get the inverse of a
+ * constant-coefficient operator).
+ *
+ * @author Martin Kronbichler, 2014
+ */
+ template <int dim, int fe_degree, int n_components = 1, typename Number = double>
+ class CellwiseInverseMassMatrix
+ {
+ public:
+ /**
+ * Constructor. Initializes the shape information from the ShapeInfo field
+ * in the class FEEval.
+ */
+ CellwiseInverseMassMatrix (const FEEvaluationBase<dim,n_components,Number> &fe_eval);
+
+ /**
+ * Applies the inverse mass matrix operation on an input array. It is
+ * assumed that the passed input and output arrays are of correct size,
+ * namely FEEval::dofs_per_cell * n_components long. The inverse of the
+ * local coefficient (also containing the inverse JxW values) must be passed
+ * as first argument. Passing more than one component in the coefficient is
+ * allowed.
+ */
+ void apply(const AlignedVector<VectorizedArray<Number> > &inverse_coefficient,
+ const unsigned int n_actual_components,
+ const VectorizedArray<Number> *in_array,
+ VectorizedArray<Number> *out_array) const;
+
+ /**
+ * Fills the given array with the inverse of the JxW values, i.e., a mass
+ * matrix with coefficient 1. Non-unit coefficients must be multiplied (in
+ * inverse form) to this array.
+ */
+ void fill_inverse_JxW_values(AlignedVector<VectorizedArray<Number> > &inverse_jxw) const;
+
+ private:
+ /**
+ * A reference to the FEEvaluation object for getting the JxW_values.
+ */
+ const FEEvaluationBase<dim,n_components,Number> &fe_eval;
+
+ /**
+ * A structure to hold inverse shape functions
+ */
+ AlignedVector<VectorizedArray<Number> > inverse_shape;
+ };
+
+
+
+ // ------------------------------------ inline functions ---------------------
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::CellwiseInverseMassMatrix (const FEEvaluationBase<dim,n_components,Number> &fe_eval)
+ :
+ fe_eval (fe_eval)
+ {
+ FullMatrix<double> shapes_1d(fe_degree+1, fe_degree+1);
+ for (unsigned int i=0, c=0; i<shapes_1d.m(); ++i)
+ for (unsigned int j=0; j<shapes_1d.n(); ++j, ++c)
+ shapes_1d(i,j) = fe_eval.get_shape_info().shape_values_number[c];
+ shapes_1d.gauss_jordan();
+ const unsigned int stride = (fe_degree+2)/2;
+ inverse_shape.resize(stride*(fe_degree+1));
+ for (unsigned int i=0; i<stride; ++i)
+ for (unsigned int q=0; q<(fe_degree+2)/2; ++q)
+ {
+ inverse_shape[i*stride+q] =
+ 0.5 * (shapes_1d(i,q) + shapes_1d(i,fe_degree-q));
+ inverse_shape[(fe_degree-i)*stride+q] =
+ 0.5 * (shapes_1d(i,q) - shapes_1d(i,fe_degree-q));
+ }
+ if (fe_degree % 2 == 0)
+ for (unsigned int q=0; q<(fe_degree+2)/2; ++q)
+ inverse_shape[fe_degree/2*stride+q] = shapes_1d(fe_degree/2,q);
+ }
+
+
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ void
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::fill_inverse_JxW_values(AlignedVector<VectorizedArray<Number> > &inverse_jxw) const
+ {
+ const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ Assert(inverse_jxw.size() > 0 &&
+ inverse_jxw.size() % dofs_per_cell == 0,
+ ExcMessage("Expected diagonal to be a multiple of scalar dof per cells"));
+
+ // temporarily reduce size of inverse_jxw to dofs_per_cell to get JxW values
+ // from fe_eval (will not reallocate any memory)
+ const unsigned int previous_size = inverse_jxw.size();
+ inverse_jxw.resize(dofs_per_cell);
+ fe_eval.fill_JxW_values(inverse_jxw);
+
+ // invert
+ inverse_jxw.resize_fast(previous_size);
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ inverse_jxw[q] = 1./inverse_jxw[q];
+ // copy values to rest of vector
+ for (unsigned int q=dofs_per_cell; q<previous_size; )
+ for (unsigned int i=0; i<dofs_per_cell; ++i, ++q)
+ inverse_jxw[q] = inverse_jxw[i];
+ }
+
+
+
+ template <int dim, int fe_degree, int n_components, typename Number>
+ inline
+ void
+ CellwiseInverseMassMatrix<dim,fe_degree,n_components,Number>
+ ::apply(const AlignedVector<VectorizedArray<Number> > &inverse_coefficients,
+ const unsigned int n_actual_components,
+ const VectorizedArray<Number> *in_array,
+ VectorizedArray<Number> *out_array) const
+ {
+ const unsigned int dofs_per_cell = Utilities::fixed_int_power<fe_degree+1,dim>::value;
+ Assert(inverse_coefficients.size() > 0 &&
+ inverse_coefficients.size() % dofs_per_cell == 0,
+ ExcMessage("Expected diagonal to be a multiple of scalar dof per cells"));
+ if (inverse_coefficients.size() != dofs_per_cell)
+ AssertDimension(n_actual_components * dofs_per_cell, inverse_coefficients.size());
+
+ Assert(dim == 2 || dim == 3, ExcNotImplemented());
+
+ internal::EvaluatorTensorProduct<internal::evaluate_evenodd,dim,fe_degree,
+ fe_degree+1, VectorizedArray<Number> >
+ evaluator(inverse_shape, inverse_shape, inverse_shape);
+
+ const unsigned int shift_coefficient =
+ inverse_coefficients.size() > dofs_per_cell ? dofs_per_cell : 0;
+ const VectorizedArray<Number> *inv_coefficient = &inverse_coefficients[0];
+ VectorizedArray<Number> temp_data_field[dofs_per_cell];
+ for (unsigned int d=0; d<n_actual_components; ++d)
+ {
+ const VectorizedArray<Number>* in = in_array+d*dofs_per_cell;
+ VectorizedArray<Number>* out = out_array+d*dofs_per_cell;
+ // Need to select 'apply' method with hessian slot because values
+ // assume symmetries that do not exist in the inverse shapes
+ evaluator.template hessians<0,false,false> (in, temp_data_field);
+ evaluator.template hessians<1,false,false> (temp_data_field, out);
+
+ if (dim == 3)
+ {
+ evaluator.template hessians<2,false,false> (out, temp_data_field);
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ temp_data_field[q] *= inv_coefficient[q];
+ evaluator.template hessians<2,true,false> (temp_data_field, out);
+ }
+ else if (dim == 2)
+ for (unsigned int q=0; q<dofs_per_cell; ++q)
+ out[q] *= inv_coefficient[q];
+
+ evaluator.template hessians<1,true,false>(out, temp_data_field);
+ evaluator.template hessians<0,true,false>(temp_data_field, out);
+
+ inv_coefficient += shift_coefficient;
+ }
+ }
+
+} // end of namespace MatrixFreeOperators
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/exceptions.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/vectorization.h>
+#include <deal.II/base/aligned_vector.h>
#include <deal.II/fe/fe.h>
#include <deal.II/matrix_free/helper_functions.h>
{
namespace MatrixFreeFunctions
{
+ /**
+ * An enum that encodes the type of element detected during
+ * initialization. FEEvaluation will select the most efficient algorithm
+ * based on the given element type.
+ */
+ enum ElementType
+ {
+ tensor_general,
+ tensor_symmetric,
+ truncated_tensor,
+ tensor_symmetric_plus_dg0,
+ tensor_gausslobatto
+ };
+
/**
* The class that stores the shape functions, gradients and Hessians
* evaluated for a tensor product finite element and tensor product
*/
ShapeInfo ();
+ /**
+ * Constructor that initializes the data fields using the reinit method.
+ */
+ template <int dim>
+ ShapeInfo (const Quadrature<1> &quad,
+ const FiniteElement<dim> &fe,
+ const unsigned int base_element = 0);
+
/**
* Initializes the data fields. Takes a one-dimensional quadrature
* formula and a finite element as arguments and evaluates the shape
*/
template <int dim>
void reinit (const Quadrature<1> &quad,
- const FiniteElement<dim> &fe_dim);
+ const FiniteElement<dim> &fe_dim,
+ const unsigned int base_element = 0);
/**
- * Returns the memory consumption of this
- * class in bytes.
+ * Returns the memory consumption of this class in bytes.
*/
std::size_t memory_consumption () const;
/**
- * Stores the shape values of the 1D finite
- * element evaluated on all 1D quadrature
- * points in vectorized format, i.e., as an
- * array of
- * VectorizedArray<dim>::n_array_elements
- * equal elements. The length of this array is
- * <tt>n_dofs_1d * n_q_points_1d</tt> and
- * quadrature points are the index running
- * fastest.
+ * Encodes the type of element detected at construction. FEEvaluation
+ * will select the most efficient algorithm based on the given element
+ * type.
+ */
+ ElementType element_type;
+
+ /**
+ * Stores the shape values of the 1D finite element evaluated on all 1D
+ * quadrature points in vectorized format, i.e., as an array of
+ * VectorizedArray<dim>::n_array_elements equal elements. The length of
+ * this array is <tt>n_dofs_1d * n_q_points_1d</tt> and quadrature
+ * points are the index running fastest.
*/
AlignedVector<VectorizedArray<Number> > shape_values;
/**
- * Stores the shape gradients of the 1D finite
- * element evaluated on all 1D quadrature
- * points in vectorized format, i.e., as an
- * array of
- * VectorizedArray<dim>::n_array_elements
- * equal elements. The length of this array is
- * <tt>n_dofs_1d * n_q_points_1d</tt> and
- * quadrature points are the index running
- * fastest.
+ * Stores the shape gradients of the 1D finite element evaluated on all
+ * 1D quadrature points in vectorized format, i.e., as an array of
+ * VectorizedArray<dim>::n_array_elements equal elements. The length of
+ * this array is <tt>n_dofs_1d * n_q_points_1d</tt> and quadrature
+ * points are the index running fastest.
*/
AlignedVector<VectorizedArray<Number> > shape_gradients;
/**
- * Stores the shape Hessians of the 1D finite
- * element evaluated on all 1D quadrature
- * points in vectorized format, i.e., as an
- * array of
- * VectorizedArray<dim>::n_array_elements
- * equal elements. The length of this array is
- * <tt>n_dofs_1d * n_q_points_1d</tt> and
- * quadrature points are the index running
- * fastest.
+ * Stores the shape Hessians of the 1D finite element evaluated on all
+ * 1D quadrature points in vectorized format, i.e., as an array of
+ * VectorizedArray<dim>::n_array_elements equal elements. The length of
+ * this array is <tt>n_dofs_1d * n_q_points_1d</tt> and quadrature
+ * points are the index running fastest.
*/
AlignedVector<VectorizedArray<Number> > shape_hessians;
/**
- * Stores the indices from cell DoFs to face
- * DoFs. The rows go through the
- * <tt>2*dim</tt> faces, and the columns the
- * DoFs on the faces.
+ * Stores the shape values in a different format, namely the so-called
+ * even-odd scheme where the symmetries in shape_values are used for
+ * faster evaluation.
+ */
+ AlignedVector<VectorizedArray<Number> > shape_val_evenodd;
+
+ /**
+ * Stores the shape gradients in a different format, namely the
+ * so-called even-odd scheme where the symmetries in shape_gradients are
+ * used for faster evaluation.
+ */
+ AlignedVector<VectorizedArray<Number> > shape_gra_evenodd;
+
+ /**
+ * Stores the shape second derivatives in a different format, namely the
+ * so-called even-odd scheme where the symmetries in shape_hessians are
+ * used for faster evaluation.
+ */
+ AlignedVector<VectorizedArray<Number> > shape_hes_evenodd;
+
+ /**
+ * Stores the indices from cell DoFs to face DoFs. The rows go through
+ * the <tt>2*dim</tt> faces, and the columns the DoFs on the faces.
*/
dealii::Table<2,unsigned int> face_indices;
std::vector<Number> subface_value[2];
/**
- * Non-vectorized version of shape
- * values. Needed when evaluating face info.
+ * Non-vectorized version of shape values. Needed when evaluating face
+ * info.
*/
std::vector<Number> shape_values_number;
/**
- * Non-vectorized version of shape
- * gradients. Needed when evaluating face
- * info.
+ * Non-vectorized version of shape gradients. Needed when evaluating
+ * face info.
*/
std::vector<Number> shape_gradient_number;
/**
- * Stores the number of quadrature points in
- * @p dim dimensions for a cell.
+ * Renumbering from deal.II's numbering of cell degrees of freedom to
+ * lexicographic numbering used inside the FEEvaluation schemes of the
+ * underlying element in the DoFHandler. For vector-valued elements, the
+ * renumbering starts with a lexicographic numbering of the first
+ * component, then everything of the second component, and so on.
+ */
+ std::vector<unsigned int> lexicographic_numbering;
+
+ /**
+ * Stores the degree of the element.
+ */
+ unsigned int fe_degree;
+
+ /**
+ * Stores the number of quadrature points in @p dim dimensions for a
+ * cell.
*/
unsigned int n_q_points;
/**
- * Stores the number of DoFs per cell in @p
- * dim dimensions.
+ * Stores the number of DoFs per cell in @p dim dimensions.
*/
unsigned int dofs_per_cell;
/**
- * Stores the number of quadrature points per
- * face in @p dim dimensions.
+ * Stores the number of quadrature points per face in @p dim dimensions.
*/
unsigned int n_q_points_face;
/**
- * Stores the number of DoFs per face in @p
- * dim dimensions.
+ * Stores the number of DoFs per face in @p dim dimensions.
*/
unsigned int dofs_per_face;
+
+ /**
+ * Checks whether we have symmetries in the shape values. In that case,
+ * also fill the shape_???_evenodd fields.
+ */
+ bool check_1d_shapes_symmetric(const unsigned int n_q_points_1d);
+
+ /**
+ * Checks whether symmetric 1D basis functions are such that the shape
+ * values form a diagonal matrix, which allows to use specialized
+ * algorithms that save some operations.
+ */
+ bool check_1d_shapes_gausslobatto();
};
+
+
+ // ------------------------------------------ inline functions
+
+ template <typename Number>
+ template <int dim>
+ inline
+ ShapeInfo<Number>::ShapeInfo (const Quadrature<1> &quad,
+ const FiniteElement<dim> &fe_in,
+ const unsigned int base_element_number)
+ :
+ fe_degree (0),
+ n_q_points (0),
+ dofs_per_cell (0)
+ {
+ reinit (quad, fe_in, base_element_number);
+ }
+
+
+
} // end of namespace MatrixFreeFunctions
} // end of namespace internal
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2011 - 2013 by the deal.II authors
+// Copyright (C) 2011 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/tensor_product_polynomials.h>
#include <deal.II/base/polynomials_piecewise.h>
#include <deal.II/fe/fe_poly.h>
+#include <deal.II/fe/fe_dgp.h>
+#include <deal.II/fe/fe_q_dg0.h>
#include <deal.II/matrix_free/shape_info.h>
template <typename Number>
ShapeInfo<Number>::ShapeInfo ()
:
+ element_type (tensor_general),
n_q_points (0),
dofs_per_cell (0)
{}
template <int dim>
void
ShapeInfo<Number>::reinit (const Quadrature<1> &quad,
- const FiniteElement<dim> &fe)
+ const FiniteElement<dim> &fe_in,
+ const unsigned int base_element_number)
{
- Assert (fe.n_components() == 1,
+ const FiniteElement<dim> *fe = &fe_in;
+ fe = &fe_in.base_element(base_element_number);
+
+ Assert (fe->n_components() == 1,
ExcMessage("FEEvaluation only works for scalar finite elements."));
- const unsigned int n_dofs_1d = fe.degree+1,
+ fe_degree = fe->degree;
+
+ const unsigned int n_dofs_1d = fe_degree+1,
n_q_points_1d = quad.size();
- AssertDimension(fe.dofs_per_cell, Utilities::fixed_power<dim>(n_dofs_1d));
- std::vector<unsigned int> lexicographic (fe.dofs_per_cell);
// renumber (this is necessary for FE_Q, for example, since there the
// vertex DoFs come first, which is incompatible with the lexicographic
// ordering necessary to apply tensor products efficiently)
+ std::vector<unsigned int> scalar_lexicographic;
{
+ // find numbering to lexicographic
+ Assert(fe->n_components() == 1,
+ ExcMessage("Expected a scalar element"));
+
const FE_Poly<TensorProductPolynomials<dim>,dim,dim> *fe_poly =
- dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>(&fe);
+ dynamic_cast<const FE_Poly<TensorProductPolynomials<dim>,dim,dim>*>(fe);
+
const FE_Poly<TensorProductPolynomials<dim,Polynomials::
- PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
+ PiecewisePolynomial<double> >,dim,dim> *fe_poly_piece =
dynamic_cast<const FE_Poly<TensorProductPolynomials<dim,
- Polynomials::PiecewisePolynomial<double> >,dim,dim>*> (&fe);
- Assert (fe_poly != 0 || fe_poly_piece, ExcNotImplemented());
- lexicographic = fe_poly != 0 ?
- fe_poly->get_poly_space_numbering_inverse() :
- fe_poly_piece->get_poly_space_numbering_inverse();
+ Polynomials::PiecewisePolynomial<double> >,dim,dim>*> (fe);
+
+ const FE_DGP<dim> *fe_dgp = dynamic_cast<const FE_DGP<dim>*>(fe);
+
+ const FE_Q_DG0<dim> *fe_q_dg0 = dynamic_cast<const FE_Q_DG0<dim>*>(fe);
+
+ element_type = tensor_general;
+ if (fe_poly != 0)
+ scalar_lexicographic = fe_poly->get_poly_space_numbering_inverse();
+ else if (fe_poly_piece != 0)
+ scalar_lexicographic = fe_poly_piece->get_poly_space_numbering_inverse();
+ else if (fe_dgp != 0)
+ {
+ scalar_lexicographic.resize(fe_dgp->dofs_per_cell);
+ for (unsigned int i=0; i<fe_dgp->dofs_per_cell; ++i)
+ scalar_lexicographic[i] = i;
+ element_type = truncated_tensor;
+ }
+ else if (fe_q_dg0 != 0)
+ {
+ scalar_lexicographic = fe_q_dg0->get_poly_space_numbering_inverse();
+ element_type = tensor_symmetric_plus_dg0;
+ }
+ else
+ Assert(false, ExcNotImplemented());
+
+ // Finally store the renumbering into the member variable of this
+ // class
+ if (fe_in.n_components() == 1)
+ lexicographic_numbering = scalar_lexicographic;
+ else
+ {
+ // have more than one component, get the inverse
+ // permutation, invert it, sort the components one after one,
+ // and invert back
+ std::vector<unsigned int> scalar_inv =
+ Utilities::invert_permutation(scalar_lexicographic);
+ std::vector<unsigned int> lexicographic (fe_in.dofs_per_cell);
+ for (unsigned int comp=0; comp<fe_in.n_components(); ++comp)
+ for (unsigned int i=0; i<scalar_inv.size(); ++i)
+ lexicographic[fe_in.component_to_system_index(comp,i)]
+ = scalar_inv.size () * comp + scalar_inv[i];
+
+ // invert numbering again
+ lexicographic_numbering =
+ Utilities::invert_permutation(lexicographic);
+ }
// to evaluate 1D polynomials, evaluate along the line where y=z=0,
// assuming that shape_value(0,Point<dim>()) == 1. otherwise, need
// other entry point (e.g. generating a 1D element by reading the
// name, as done before r29356)
- Assert(std::fabs(fe.shape_value(lexicographic[0], Point<dim>())-1) < 1e-13,
+ Assert(std::fabs(fe->shape_value(scalar_lexicographic[0],
+ Point<dim>())-1) < 1e-13,
ExcInternalError());
}
n_q_points = Utilities::fixed_power<dim>(n_q_points_1d);
- dofs_per_cell = Utilities::fixed_power<dim>(n_dofs_1d);
+ dofs_per_cell = fe->dofs_per_cell;
n_q_points_face = dim>1?Utilities::fixed_power<dim-1>(n_q_points_1d):1;
- dofs_per_face = dim>1?Utilities::fixed_power<dim-1>(n_dofs_1d):1;
+ dofs_per_face = fe->dofs_per_face;
const unsigned int array_size = n_dofs_1d*n_q_points_1d;
this->shape_gradients.resize_fast (array_size);
{
// need to reorder from hierarchical to lexicographic to get the
// DoFs correct
- const unsigned int my_i = lexicographic[i];
+ const unsigned int my_i = scalar_lexicographic[i];
for (unsigned int q=0; q<n_q_points_1d; ++q)
{
// fill both vectors with
// non-vectorized fields
Point<dim> q_point;
q_point[0] = quad.get_points()[q][0];
- shape_values_number[i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
- shape_gradient_number[i*n_q_points_1d+q] = fe.shape_grad (my_i,q_point)[0];
+ shape_values_number[i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
+ shape_gradient_number[i*n_q_points_1d+q] = fe->shape_grad (my_i,q_point)[0];
shape_values [i*n_q_points_1d+q] =
shape_values_number [i*n_q_points_1d+q];
shape_gradients[i*n_q_points_1d+q] =
shape_gradient_number[i*n_q_points_1d+q];
shape_hessians[i*n_q_points_1d+q] =
- fe.shape_grad_grad(my_i,q_point)[0][0];
+ fe->shape_grad_grad(my_i,q_point)[0][0];
q_point[0] *= 0.5;
- subface_value[0][i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
+ subface_value[0][i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
q_point[0] += 0.5;
- subface_value[1][i*n_q_points_1d+q] = fe.shape_value(my_i,q_point);
+ subface_value[1][i*n_q_points_1d+q] = fe->shape_value(my_i,q_point);
}
Point<dim> q_point;
- this->face_value[0][i] = fe.shape_value(my_i,q_point);
- this->face_gradient[0][i] = fe.shape_grad(my_i,q_point)[0];
+ this->face_value[0][i] = fe->shape_value(my_i,q_point);
+ this->face_gradient[0][i] = fe->shape_grad(my_i,q_point)[0];
q_point[0] = 1;
- this->face_value[1][i] = fe.shape_value(my_i,q_point);
- this->face_gradient[1][i] = fe.shape_grad(my_i,q_point)[0];
+ this->face_value[1][i] = fe->shape_value(my_i,q_point);
+ this->face_gradient[1][i] = fe->shape_grad(my_i,q_point)[0];
+ }
+
+ if (element_type == tensor_general &&
+ check_1d_shapes_symmetric(n_q_points_1d))
+ {
+ if (check_1d_shapes_gausslobatto())
+ element_type = tensor_gausslobatto;
+ else
+ element_type = tensor_symmetric;
}
+ else if (element_type == tensor_symmetric_plus_dg0)
+ check_1d_shapes_symmetric(n_q_points_1d);
// face information
unsigned int n_faces = GeometryInfo<dim>::faces_per_cell;
}
case 2:
{
- for (unsigned int i=0; i<n_dofs_1d; i++)
+ for (unsigned int i=0; i<this->dofs_per_face; i++)
{
this->face_indices(0,i) = n_dofs_1d*i;
this->face_indices(1,i) = n_dofs_1d*i + n_dofs_1d-1;
+ template <typename Number>
+ bool
+ ShapeInfo<Number>::check_1d_shapes_symmetric(const unsigned int n_q_points_1d)
+ {
+ const double zero_tol =
+ types_are_equal<Number,double>::value==true?1e-10:1e-7;
+ // symmetry for values
+ const unsigned int n_dofs_1d = fe_degree + 1;
+ for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
+ for (unsigned int j=0; j<n_q_points_1d; ++j)
+ if (std::fabs(shape_values[i*n_q_points_1d+j][0] -
+ shape_values[(n_dofs_1d-i)*n_q_points_1d
+ -j-1][0]) > zero_tol)
+ return false;
+
+ // shape values should be zero at x=0.5 for all basis functions except
+ // for one which is one
+ if (n_q_points_1d%2 == 1 && n_dofs_1d%2 == 1)
+ {
+ for (unsigned int i=0; i<n_dofs_1d/2; ++i)
+ if (std::fabs(shape_values[i*n_q_points_1d+
+ n_q_points_1d/2][0]) > zero_tol)
+ return false;
+ if (std::fabs(shape_values[(n_dofs_1d/2)*n_q_points_1d+
+ n_q_points_1d/2][0]-1.)> zero_tol)
+ return false;
+ }
+
+ // skew-symmetry for gradient, zero of middle basis function in middle
+ // quadrature point
+ for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
+ for (unsigned int j=0; j<n_q_points_1d; ++j)
+ if (std::fabs(shape_gradients[i*n_q_points_1d+j][0] +
+ shape_gradients[(n_dofs_1d-i)*n_q_points_1d-
+ j-1][0]) > zero_tol)
+ return false;
+ if (n_dofs_1d%2 == 1 && n_q_points_1d%2 == 1)
+ if (std::fabs(shape_gradients[(n_dofs_1d/2)*n_q_points_1d+
+ (n_q_points_1d/2)][0]) > zero_tol)
+ return false;
+
+ // symmetry for Laplacian
+ for (unsigned int i=0; i<(n_dofs_1d+1)/2; ++i)
+ for (unsigned int j=0; j<n_q_points_1d; ++j)
+ if (std::fabs(shape_hessians[i*n_q_points_1d+j][0] -
+ shape_hessians[(n_dofs_1d-i)*n_q_points_1d-
+ j-1][0]) > zero_tol)
+ return false;
+
+ const unsigned int stride = (n_q_points_1d+1)/2;
+ shape_val_evenodd.resize((fe_degree+1)*stride);
+ shape_gra_evenodd.resize((fe_degree+1)*stride);
+ shape_hes_evenodd.resize((fe_degree+1)*stride);
+ for (unsigned int i=0; i<(fe_degree+1)/2; ++i)
+ for (unsigned int q=0; q<stride; ++q)
+ {
+ shape_val_evenodd[i*stride+q] =
+ 0.5 * (shape_values[i*n_q_points_1d+q] +
+ shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
+ shape_val_evenodd[(fe_degree-i)*stride+q] =
+ 0.5 * (shape_values[i*n_q_points_1d+q] -
+ shape_values[i*n_q_points_1d+n_q_points_1d-1-q]);
+
+ shape_gra_evenodd[i*stride+q] =
+ 0.5 * (shape_gradients[i*n_q_points_1d+q] +
+ shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
+ shape_gra_evenodd[(fe_degree-i)*stride+q] =
+ 0.5 * (shape_gradients[i*n_q_points_1d+q] -
+ shape_gradients[i*n_q_points_1d+n_q_points_1d-1-q]);
+
+ shape_hes_evenodd[i*stride+q] =
+ 0.5 * (shape_hessians[i*n_q_points_1d+q] +
+ shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
+ shape_hes_evenodd[(fe_degree-i)*stride+q] =
+ 0.5 * (shape_hessians[i*n_q_points_1d+q] -
+ shape_hessians[i*n_q_points_1d+n_q_points_1d-1-q]);
+ }
+ if (fe_degree % 2 == 0)
+ for (unsigned int q=0; q<stride; ++q)
+ {
+ shape_val_evenodd[fe_degree/2*stride+q] =
+ shape_values[(fe_degree/2)*n_q_points_1d+q];
+ shape_gra_evenodd[fe_degree/2*stride+q] =
+ shape_gradients[(fe_degree/2)*n_q_points_1d+q];
+ shape_hes_evenodd[fe_degree/2*stride+q] =
+ shape_hessians[(fe_degree/2)*n_q_points_1d+q];
+ }
+
+ return true;
+ }
+
+
+
+ template <typename Number>
+ bool
+ ShapeInfo<Number>::check_1d_shapes_gausslobatto()
+ {
+ if (dofs_per_cell != n_q_points)
+ return false;
+
+ const double zero_tol =
+ types_are_equal<Number,double>::value==true?1e-10:1e-7;
+ // check: - identity operation for shape values
+ // - zero diagonal at interior points for gradients
+ // - gradient equal to unity at element boundary
+ const unsigned int n_points_1d = fe_degree+1;
+ for (unsigned int i=0; i<n_points_1d; ++i)
+ for (unsigned int j=0; j<n_points_1d; ++j)
+ if (i!=j)
+ {
+ if (std::fabs(shape_values[i*n_points_1d+j][0])>zero_tol)
+ return false;
+ }
+ else
+ {
+ if (std::fabs(shape_values[i*n_points_1d+
+ j][0]-1.)>zero_tol)
+ return false;
+ }
+ for (unsigned int i=1; i<n_points_1d-1; ++i)
+ if (std::fabs(shape_gradients[i*n_points_1d+i][0])>zero_tol)
+ return false;
+ if (std::fabs(shape_gradients[n_points_1d-1][0]-
+ (n_points_1d%2==0 ? -1. : 1.)) > zero_tol)
+ return false;
+
+ return true;
+ }
+
+
+
template <typename Number>
std::size_t
ShapeInfo<Number>::memory_consumption () const
std::size_t memory = sizeof(*this);
memory += MemoryConsumption::memory_consumption(shape_values);
memory += MemoryConsumption::memory_consumption(shape_gradients);
- memory += MemoryConsumption::memory_consumption(shape_hessians);
+ memory += MemoryConsumption::memory_consumption(shape_hessians);
+ memory += MemoryConsumption::memory_consumption(shape_val_evenodd);
+ memory += MemoryConsumption::memory_consumption(shape_gra_evenodd);
+ memory += MemoryConsumption::memory_consumption(shape_hes_evenodd);
memory += face_indices.memory_consumption();
for (unsigned int i=0; i<2; ++i)
{
#define __deal2__mesh_worker_functional_h
#include <deal.II/base/named_data.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/mg_level_object.h>
#include <deal.II/lac/block_vector.h>
{
public:
/**
- * The data type for
- * communicating the cell and
- * face vectors.
- */
- typedef NamedData<BlockVector<number>*> DataVectors;
-
- /**
- * The initialization
- * function, specifying the
- * @p results vectors and
- * whether face data should
- * be collected separately.
+ * The initialization function, specifying the @p results
+ * vectors and whether face data should be collected separately.
*
- * @p results should contain
- * two block vectors named
- * "cells" and "faces" (the
- * latter only if
- * @p separate_faces is
- * true). In each of the two,
- * each block should have
- * equal size and be large
- * enough to accommodate all
- * user indices set in the
- * cells and faces covered by
- * the loop it is used
- * in. Typically, for
- * estimators, this is
- * Triangulation::n_active_cells()
- * and
- * Triangulation::n_faces(),
- * respectively.
+ * @p results should contain two block vectors named "cells" and
+ * "faces" (the latter only if @p separate_faces is true). In
+ * each of the two, each block should have equal size and be
+ * large enough to accommodate all user indices set in the cells
+ * and faces covered by the loop it is used in. Typically, for
+ * estimators, this is Triangulation::n_active_cells() and
+ * Triangulation::n_faces(), respectively.
*
- * The use of BlockVector may
- * seem cumbersome, but it
- * allows us to assemble
- * several functionals at the
- * same time, one in each
- * block. The typical
- * situation for error
- * estimate is just having a
- * single block in each vector.
+ * The use of BlockVector may seem cumbersome, but it allows us
+ * to assemble several functionals at the same time, one in each
+ * block. The typical situation for error estimate is just
+ * having a single block in each vector.
*/
- void initialize(DataVectors &results,
+ void initialize(AnyData &results, bool separate_faces = true);
+
+ /**
+ * @deprecated
+ */
+ void initialize(NamedData<BlockVector<number>*> &results,
bool separate_faces = true);
/**
* Initialize the local data
*/
number operator() (const unsigned int i) const;
private:
- DataVectors results;
+ AnyData results;
bool separate_faces;
};
//----------------------------------------------------------------------//
template <typename number>
inline void
- CellsAndFaces<number>::initialize(DataVectors &r, bool sep)
+ CellsAndFaces<number>::initialize(AnyData &r, bool sep)
+ {
+ Assert(r.name(0) == "cells", AnyData::ExcNameMismatch(0, "cells"));
+ if (sep)
+ {
+ Assert(r.name(1) == "faces", AnyData::ExcNameMismatch(1, "faces"));
+ AssertDimension(r.entry<BlockVector<double>*>(0)->n_blocks(),
+ r.entry<BlockVector<double>*>(1)->n_blocks());
+ }
+
+ results = r;
+ separate_faces = sep;
+ }
+
+ template <typename number>
+ inline void
+ CellsAndFaces<number>::initialize(NamedData<BlockVector<number>*> &r, bool sep)
{
- Assert(r.name(0) == "cells", typename DataVectors::ExcNameMismatch(0, "cells"));
+ Assert(r.name(0) == "cells", AnyData::ExcNameMismatch(0, "cells"));
if (sep)
{
- Assert(r.name(1) == "faces", typename DataVectors::ExcNameMismatch(1, "faces"));
- AssertDimension(r(0)->n_blocks(), r(1)->n_blocks());
+ Assert(r.name(1) == "faces", AnyData::ExcNameMismatch(1, "faces"));
+ AssertDimension(r(0)->n_blocks(),r(1)->n_blocks());
}
results = r;
inline void
CellsAndFaces<number>::initialize_info(DOFINFO &info, bool) const
{
- info.initialize_numbers(results(0)->n_blocks());
+ info.initialize_numbers(results.entry<BlockVector<double>*>(0)->n_blocks());
}
inline void
CellsAndFaces<number>::assemble(const DOFINFO &info)
{
+ BlockVector<double>* v;
+ if (separate_faces &&
+ info.face_number != deal_II_numbers::invalid_unsigned_int)
+ v = results.entry<BlockVector<double>*>(1);
+ else
+ v = results.entry<BlockVector<double>*>(0);
+
for (unsigned int i=0; i<info.n_values(); ++i)
- {
- if (separate_faces &&
- info.face_number != deal_II_numbers::invalid_unsigned_int)
- results(1)->block(i)(info.face->user_index()) += info.value(i);
- else
- results(0)->block(i)(info.cell->user_index()) += info.value(i);
- }
+ v->block(i)(info.cell->user_index()) += info.value(i);
}
{
if (separate_faces)
{
+ BlockVector<double>* v1 = results.entry<BlockVector<double>*>(1);
const double J = info1.value(i) + info2.value(i);
- results(1)->block(i)(info1.face->user_index()) += J;
+ v1->block(i)(info1.face->user_index()) += J;
if (info2.face != info1.face)
- results(1)->block(i)(info2.face->user_index()) += J;
+ v1->block(i)(info2.face->user_index()) += J;
}
else
{
- results(0)->block(i)(info1.cell->user_index()) += .5*info1.value(i);
- results(0)->block(i)(info2.cell->user_index()) += .5*info2.value(i);
+ BlockVector<double>* v0 = results.entry<BlockVector<double>*>(0);
+ v0->block(i)(info1.cell->user_index()) += .5*info1.value(i);
+ v0->block(i)(info2.cell->user_index()) += .5*info2.value(i);
}
}
}
*/
void clear();
+ /**
+ * Return a reference to the FiniteElement that was used to
+ * initialize this object.
+ */
+ const FiniteElement<dim, spacedim>& finite_element() const;
+
/// This is true if we are assembling for multigrid
bool multigrid;
/// Access to finite element
/**
- * This is the access function being used, if the constructor for
- * a single element was used. It throws an exception, if applied
- * to a vector of elements.
+ * This is the access function being used, if initialize() for a
+ * single element was used (without the BlockInfo argument). It
+ * throws an exception, if applied to a vector of elements.
*/
const FEValuesBase<dim, spacedim> &fe_values () const;
/// Access to finite elements
/**
- * This access function must be used if the constructor for a
- * group of elements was used.
- *
- * @see DGBlockSplitApplication
+ * This access function must be used if the initalize() for a
+ * group of elements was used (with a valid BlockInfo object).
*/
const FEValuesBase<dim, spacedim> &fe_values (const unsigned int i) const;
std::size_t memory_consumption () const;
private:
+ /**
+ * The pointer to the (system) element used for initialization.
+ */
+ SmartPointer<const FiniteElement<dim, spacedim>, IntegrationInfo<dim, spacedim> > fe_pointer;
+
/**
* Use the finite element functions in #global_data and fill the
* vectors #values, #gradients and #hessians with values according
* undertaken to use this class.
*
* First, you should consider if you need values from any vectors in a
- * NamedData object. If so, fill the VectorSelector objects
+ * AnyData object. If so, fill the VectorSelector objects
* #cell_selector, #boundary_selector and #face_selector with their names
* and the data type (value, gradient, Hessian) to be extracted.
*
* formulas, which integrate polynomial bilinear forms exactly.
*/
template <typename VECTOR>
+ void initialize(const FiniteElement<dim, spacedim> &el,
+ const Mapping<dim, spacedim> &mapping,
+ const AnyData &data,
+ const VECTOR& dummy,
+ const BlockInfo *block_info = 0);
+ /**
+ * @deprecated Use AnyData instead of NamedData.
+ */
+ template <typename VECTOR>
void initialize(const FiniteElement<dim, spacedim> &el,
const Mapping<dim, spacedim> &mapping,
const NamedData<VECTOR *> &data,
const BlockInfo *block_info = 0);
/**
- * Initialize the IntegrationInfo objects contained.
- *
- * Before doing so, add update flags necessary to produce the data
- * needed and also set uninitialized quadrature rules to Gauss
- * formulas, which integrate polynomial bilinear forms exactly.
+ * @deprecated Use AnyData instead of NamedData.
*/
template <typename VECTOR>
void initialize(const FiniteElement<dim, spacedim> &el,
gradients(other.gradients),
hessians(other.hessians),
global_data(other.global_data),
+ fe_pointer(other.fe_pointer),
n_components(other.n_components)
{
fevalv.resize(other.fevalv.size());
const UpdateFlags flags,
const BlockInfo *block_info)
{
+ fe_pointer = ⪙
if (block_info == 0 || block_info->local().size() == 0)
{
fevalv.resize(1);
}
+ template <int dim, int spacedim>
+ inline const FiniteElement<dim, spacedim> &
+ IntegrationInfo<dim,spacedim>::finite_element() const
+ {
+ Assert (fe_pointer !=0, ExcNotInitialized());
+ return *fe_pointer;
+ }
+
template <int dim, int spacedim>
inline const FEValuesBase<dim, spacedim> &
IntegrationInfo<dim,spacedim>::fe_values() const
}
+ template <int dim, int sdim>
+ template <typename VECTOR>
+ void
+ IntegrationInfoBox<dim,sdim>::initialize(
+ const FiniteElement<dim,sdim> &el,
+ const Mapping<dim,sdim> &mapping,
+ const AnyData &data,
+ const VECTOR& dummy,
+ const BlockInfo *block_info)
+ {
+ initialize(el, mapping, block_info);
+ std_cxx1x::shared_ptr<VectorData<VECTOR, dim, sdim> > p;
+ VectorDataBase<dim,sdim>* pp;
+
+ p = std_cxx1x::shared_ptr<VectorData<VECTOR, dim, sdim> >(new VectorData<VECTOR, dim, sdim> (cell_selector));
+ // Public member function of parent class was not found without
+ // explicit cast
+ pp = &*p;
+ pp->initialize(data);
+ cell_data = p;
+ cell.initialize_data(p);
+
+ p = std_cxx1x::shared_ptr<VectorData<VECTOR, dim, sdim> >(new VectorData<VECTOR, dim, sdim> (boundary_selector));
+ pp = &*p;
+ pp->initialize(data);
+ boundary_data = p;
+ boundary.initialize_data(p);
+
+ p = std_cxx1x::shared_ptr<VectorData<VECTOR, dim, sdim> >(new VectorData<VECTOR, dim, sdim> (face_selector));
+ pp = &*p;
+ pp->initialize(data);
+ face_data = p;
+ face.initialize_data(p);
+ subface.initialize_data(p);
+ neighbor.initialize_data(p);
+ }
+
+
template <int dim, int sdim>
template <typename VECTOR>
void
// Now neighbor is on same level, double-check this:
Assert(cell->level()==neighbor->level(), ExcInternalError());
- // only do faces on same level from one side (unless
- // LoopControl says otherwise)
+ // If we own both cells only do faces from one side (unless
+ // LoopControl says otherwise). Here, we rely on cell comparison
+ // that will look at cell->index().
if (own_cell && own_neighbor
&& loop_control.own_faces == LoopControl::one
&& (neighbor < cell))
if (!own_cell)
continue;
- // now only one processor assembles faces_to_ghost. This
- // logic is based on the subdomain id and is handled inside
- // operator<.
+ // now only one processor assembles faces_to_ghost. We let the
+ // processor with the smaller (level-)subdomain id assemble the
+ // face.
if (own_cell && !own_neighbor
&& loop_control.faces_to_ghost == LoopControl::one
- && (neighbor < cell))
- continue;
+ && (neighbid < csid))
+ continue;
const unsigned int neighbor_face_no = cell->neighbor_face_no(face_no);
Assert (neighbor->face(neighbor_face_no) == face, ExcInternalError());
{
LoopControl lctrl;
lctrl.cells_first = cells_first;
- lctrl.own_faces = (unique_faces_only)?LoopControl::one:LoopControl::both;
+ lctrl.own_faces = (unique_faces_only)
+ ? LoopControl::one
+ : LoopControl::both;
loop<dim,spacedim>(begin, end, dinfo, info, cell_worker, boundary_worker, face_worker, assembler, lctrl);
}
#define __deal2__mesh_worker_simple_h
#include <deal.II/base/named_data.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/mg_level_object.h>
#include <deal.II/lac/block_vector.h>
class ResidualSimple
{
public:
- void initialize(NamedData<VECTOR *> &results);
+ /**
+ * Initialize with an AnyData object holding the result of
+ * assembling.
+ *
+ * Assembling currently writes into the first vector of <tt>results</tt>.
+ */
+ void initialize(AnyData& results);
+ /**
+ * @deprecated Use initialize(AnyData&) instead.
+ */
+ void initialize(NamedData<VECTOR *> &results);
/**
* Initialize the constraints.
*/
/**
* The global residal vectors filled by assemble().
*/
- NamedData<SmartPointer<VECTOR,ResidualSimple<VECTOR> > > residuals;
+ AnyData residuals;
/**
* A pointer to the object containing constraints.
*/
//----------------------------------------------------------------------//
+ template <class VECTOR>
+ inline void
+ ResidualSimple<VECTOR>::initialize(AnyData &results)
+ {
+ residuals = results;
+ }
+
template <class VECTOR>
inline void
ResidualSimple<VECTOR>::initialize(NamedData<VECTOR *> &results)
{
for (unsigned int k=0; k<residuals.size(); ++k)
{
+ VECTOR* v = residuals.entry<VECTOR*>(k);
if (constraints == 0)
{
for (unsigned int i=0; i<info.vector(k).block(0).size(); ++i)
- (*residuals(k))(info.indices[i]) += info.vector(k).block(0)(i);
+ (*v)(info.indices[i]) += info.vector(k).block(0)(i);
}
else
{
if (info.indices_by_block.size() == 0)
- constraints->distribute_local_to_global(info.vector(k).block(0), info.indices, (*residuals(k)));
+ constraints->distribute_local_to_global(info.vector(k).block(0), info.indices, *v);
else
for (unsigned int i=0; i != info.vector(k).n_blocks(); ++i)
- constraints->distribute_local_to_global(info.vector(k).block(i), info.indices_by_block[i], (*residuals(k)));
+ constraints->distribute_local_to_global(info.vector(k).block(i), info.indices_by_block[i], *v);
}
}
}
{
for (unsigned int k=0; k<residuals.size(); ++k)
{
+ VECTOR* v = residuals.entry<VECTOR*>(k);
if (constraints == 0)
{
for (unsigned int i=0; i<info1.vector(k).block(0).size(); ++i)
- (*residuals(k))(info1.indices[i]) += info1.vector(k).block(0)(i);
+ (*v)(info1.indices[i]) += info1.vector(k).block(0)(i);
for (unsigned int i=0; i<info2.vector(k).block(0).size(); ++i)
- (*residuals(k))(info2.indices[i]) += info2.vector(k).block(0)(i);
+ (*v)(info2.indices[i]) += info2.vector(k).block(0)(i);
}
else
{
if (info1.indices_by_block.size() == 0 && info2.indices_by_block.size() == 0)
{
constraints->distribute_local_to_global
- (info1.vector(k).block(0), info1.indices, (*residuals(k)));
+ (info1.vector(k).block(0), info1.indices, *v);
constraints->distribute_local_to_global
- (info2.vector(k).block(0), info2.indices, (*residuals(k)));
+ (info2.vector(k).block(0), info2.indices, *v);
}
else if (info1.indices_by_block.size() != 0 && info2.indices_by_block.size() != 0)
{
for (unsigned int i=0; i<info1.vector(k).n_blocks(); ++i)
{
constraints->distribute_local_to_global
- (info1.vector(k).block(i), info1.indices_by_block[i], (*residuals(k)));
+ (info1.vector(k).block(i), info1.indices_by_block[i], *v);
constraints->distribute_local_to_global
- (info2.vector(k).block(i), info2.indices_by_block[i], (*residuals(k)));
+ (info2.vector(k).block(i), info2.indices_by_block[i], *v);
}
}
else
inline void
SystemSimple<MATRIX,VECTOR>::initialize(MATRIX &m, VECTOR &rhs)
{
- NamedData<VECTOR *> data;
+ AnyData data;
VECTOR *p = &rhs;
data.add(p, "right hand side");
#define __deal2__mesh_worker_vector_selector_h
#include <deal.II/base/named_data.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/mg_level_object.h>
/**
* A class that selects vectors from a list of named vectors.
*
- * Since the number of vectors in a NamedData object may grow with every
+ * Since the number of vectors in an AnyData object may grow with every
* nesting of applications or loops, it is important to be able to
* select those, which are actually used in computing residuals etc.
* This class organizes the selection.
{
public:
/**
- * Add a vector to the
- * selection of finite element
- * functions. The arguments are
- * the name of the vector and
- * indicators, which
- * information is to be
- * extracted from the
- * vector. The name refers to
- * an entry in a NamedData
- * object, which will be
- * identified by initialize().
- * The three bool parameters
- * indicate, whether values,
- * greadients and Hessians of
- * the finite element function
- * are to be computed on each
- * cell or face.
+ * Add a vector to the selection of finite element functions. The
+ * arguments are the name of the vector and indicators, which
+ * information is to be extracted from the vector. The name refers
+ * to an entry in a AnyData object, which will be identified by
+ * initialize(). The three bool parameters indicate, whether
+ * values, greadients and Hessians of the finite element function
+ * are to be computed on each cell or face.
*/
void add(const std::string &name,
const bool values = true,
const bool hessians = false);
/**
- * Does the same as the function
- * above but it is possible to
- * select a block of the global
- * vector.
+ * Does the same as the function above but it is possible to
+ * select a block of the global vector.
*/
// void add(const std::string& name,
// const unsigned int selected_block,
// bool hessians = false);
/**
- * Initialize the selection
- * field with a data
- * vector. While add() only
- * enters the names of vectors,
- * which will be used in the integration
- * loop over cells and faces,
- * this function links the
- * names to actual vectos in a
- * NamedData object.
+ * Initialize the selection field with a data vector. While add()
+ * only enters the names of vectors, which will be used in the
+ * integration loop over cells and faces, this function links the
+ * names to actual vectos in a AnyData object.
*
- * @note This function caches
- * the index associated with a
- * name. Therefore, it must be
- * called every time after the
- * NamedData object has changed.
+ * @note This function caches the index associated with a
+ * name. Therefore, it must be called every time after the AnyData
+ * object has changed.
+ */
+ void initialize(const AnyData &);
+
+ /**
+ * @deprecated Use AnyData instead of NamedData.
*/
template <class DATA>
void initialize(const NamedData<DATA> &);
bool empty () const;
/**
- * Returns true if values are
- * selected for any vector.
+ * Returns true if values are selected for any vector.
*/
bool has_values () const;
/**
- * Returns true if gradients are
- * selected for any vector.
+ * Returns true if gradients are selected for any vector.
*/
bool has_gradients () const;
/**
- * Returns true if hessians are
- * selected for any vector.
+ * Returns true if hessians are selected for any vector.
*/
bool has_hessians () const;
* selection to the stream.
*/
template <class STREAM, typename DATA>
+ void print (STREAM &s, const AnyData &v) const;
+
+ /**
+ * @deprecated Use AnyData instead of NamedData.
+ */
+ template <class STREAM, typename DATA>
void print (STREAM &s, const NamedData<DATA> &v) const;
/**
NamedSelection value_selection;
/**
- * Selection of the vectors
- * used to compute gradients.
+ * Selection of the vectors used to compute gradients.
*/
NamedSelection gradient_selection;
/**
- * Selection of the vectors
- * used to compute hessians.
+ * Selection of the vectors used to compute hessians.
*/
NamedSelection hessian_selection;
};
VectorDataBase();
/**
- * Constructor from a base
- * class object
+ * Constructor from a base class object
*/
VectorDataBase(const VectorSelector &);
/**
- * Virtual, but empty
- * destructor.
+ * Initialize with a AnyData object and cache the indices in the
+ * VectorSelector base class.
+ *
+ * @note Make sure the VectorSelector base class was filled with
+ * reasonable data before calling this function.
+ */
+ void initialize(const AnyData&);
+
+ /**
+ * Virtual, but empty destructor.
*/
virtual ~VectorDataBase();
/**
- * The only function added to
- * VectorSelector is an
- * abstract virtual function
- * implemented in the derived
- * class template and called by
- * IntegrationInfo.
+ * The only function added to VectorSelector is an abstract
+ * virtual function implemented in the derived class template and
+ * called by IntegrationInfo.
*
- * Depending on the selections
- * made in our base class, this
- * fills the first three
- * arguments with the local
- * data of the finite element
- * functions. It is usually
- * called either for the whole
- * FESystem, or for each base
- * element separately.
+ * Depending on the selections made in our base class, this fills
+ * the first three arguments with the local data of the finite
+ * element functions. It is usually called either for the whole
+ * FESystem, or for each base element separately.
*
- * @param values is the vector
- * filled with the values of
- * the finite element function
- * in the quadrature points.
+ * @param values is the vector filled with the values of the
+ * finite element function in the quadrature points.
*
- * @param gradients is the vector
- * filled with the derivatives of
- * the finite element function
- * in the quadrature points.
+ * @param gradients is the vector filled with the derivatives of
+ * the finite element function in the quadrature points.
*
- * @param hessians is the
- * vector filled with the
- * second derivatives of the
- * finite element function in
- * the quadrature points.
+ * @param hessians is the vector filled with the second
+ * derivatives of the finite element function in the quadrature
+ * points.
*
- * @param fe is the
- * FEValuesBase object which is
- * used to compute the function
- * values. Its UpdateFlags must
- * have been set appropriately.
+ * @param fe is the FEValuesBase object which is used to compute
+ * the function values. Its UpdateFlags must have been set
+ * appropriately.
*
- * @param index is the local
- * index vector. If @p fe
- * refers to base elements of
- * the system, this vector
- * should be sorted by block
- * and the arguments @p start
- * and @p size below specify
- * the subset of @p indices
- * used.
+ * @param index is the local index vector. If @p fe refers to base
+ * elements of the system, this vector should be sorted by block
+ * and the arguments @p start and @p size below specify the subset
+ * of @p indices used.
*
- * @param component is the first
- * index in @p values, @p
- * gradients and @p hessians
- * entered in this function.
+ * @param component is the first index in @p values, @p gradients
+ * and @p hessians entered in this function.
*
- * @param n_comp is the number
- * of components to be filled.
+ * @param n_comp is the number of components to be filled.
*
- * @param start is the first
- * index of this block in @p
- * indices, or zero if
- * no base elements are used.
+ * @param start is the first index of this block in @p indices, or
+ * zero if no base elements are used.
*
- * @param size is the number of
- * dofs per cell of the current
+ * @param size is the number of dofs per cell of the current
* element or base element.
*/
virtual void fill(
const unsigned int size) const;
/**
- * Fill the local data vector
- * from level vectors. Performs
- * exactly what the other
- * fill() does, but uses the
- * cell level to access a
- * single level out of a
- * hierarchy of level vectors,
- * instead of a global data
- * vector on the active cells.
+ * Fill the local data vector from level vectors. Performs exactly
+ * what the other fill() does, but uses the cell level to access a
+ * single level out of a hierarchy of level vectors, instead of a
+ * global data vector on the active cells.
*/
virtual void mg_fill(
std::vector<std::vector<std::vector<double> > > &values,
* The memory used by this object.
*/
std::size_t memory_consumption () const;
+ protected:
+ AnyData data;
};
/**
* Based on VectorSelector, this is the class that implements the
* function VectorDataBase::fill() for a certain type of vector, using
- * NamedData to identify vectors by name.
+ * AnyData to identify vectors by name.
*
* @ingroup MeshWorker
* @author Guido Kanschat, 2009
VectorData(const VectorSelector &);
/**
- * Initialize with a NamedData
- * object and cache the indices
- * in the VectorSelector base
- * class.
- *
- * @note Make sure the
- * VectorSelector base class
- * was filled with reasonable
- * data before calling this
- * function.
+ * @deprecated Use AnyData instead of NamedData.
*/
void initialize(const NamedData<VECTOR *> &);
/**
- * Initialize with a single
- * vector and cache the indices
- * in the VectorSelector base
- * class.
+ * Initialize with a single vector and cache the indices in the
+ * VectorSelector base class.
*
- * @note Make sure the
- * VectorSelector base class
- * was filled with reasonable
- * data before calling this
- * function.
+ * @note Make sure the VectorSelector base class was filled with
+ * reasonable data before calling this function.
*/
void initialize(const VECTOR *, const std::string &name);
const unsigned int start,
const unsigned int size) const;
- /**
+ virtual void mg_fill(
+ std::vector<std::vector<std::vector<double> > > &values,
+ std::vector<std::vector<std::vector<Tensor<1,dim> > > > &gradients,
+ std::vector<std::vector<std::vector<Tensor<2,dim> > > > &hessians,
+ const FEValuesBase<dim,spacedim> &fe,
+ const unsigned int level,
+ const std::vector<types::global_dof_index> &index,
+ const unsigned int component,
+ const unsigned int n_comp,
+ const unsigned int start,
+ const unsigned int size) const;
+
+ /**
* The memory used by this object.
*/
std::size_t memory_consumption () const;
-
- private:
- NamedData<SmartPointer<const VECTOR,VectorData<VECTOR,dim,spacedim> > > data;
};
/**
* Based on VectorSelector, this is the class that implements the
* function VectorDataBase::fill() for a certain type of multilevel vectors, using
- * NamedData to identify vectors by name.
+ * AnyData to identify vectors by name.
*
* @ingroup MeshWorker
* @author Guido Kanschat, 2010
*/
template <class VECTOR, int dim, int spacedim = dim>
class MGVectorData :
- public VectorDataBase<dim, spacedim>
+ public VectorData<VECTOR, dim, spacedim>
{
public:
/**
*/
MGVectorData();
/**
- * Constructor using a
- * prefilled VectorSelector
+ * Constructor using a prefilled VectorSelector
*/
MGVectorData(const VectorSelector &);
/**
- * Initialize with a NamedData
- * object and cache the indices
- * in the VectorSelector base
- * class.
- *
- * @note Make sure the
- * VectorSelector base class
- * was filled with reasonable
- * data before calling this
- * function.
+ * @deprecated Use AnyData instead of NamedData.
*/
void initialize(const NamedData<MGLevelObject<VECTOR>*> &);
/**
- * Initialize with a single
- * vector and cache the indices
- * in the VectorSelector base
- * class.
+ * Initialize with a single vector and cache the indices in the
+ * VectorSelector base class.
*
- * @note Make sure the
- * VectorSelector base class
- * was filled with reasonable
- * data before calling this
- * function.
+ * @note Make sure the VectorSelector base class was filled with
+ * reasonable data before calling this function.
*/
void initialize(const MGLevelObject<VECTOR> *, const std::string &name);
- virtual void mg_fill(
- std::vector<std::vector<std::vector<double> > > &values,
- std::vector<std::vector<std::vector<Tensor<1,dim> > > > &gradients,
- std::vector<std::vector<std::vector<Tensor<2,dim> > > > &hessians,
- const FEValuesBase<dim,spacedim> &fe,
- const unsigned int level,
- const std::vector<types::global_dof_index> &index,
- const unsigned int component,
- const unsigned int n_comp,
- const unsigned int start,
- const unsigned int size) const;
/**
* The memory used by this object.
*/
std::size_t memory_consumption () const;
-
- private:
- NamedData<SmartPointer<const MGLevelObject<VECTOR>,MGVectorData<VECTOR,dim,spacedim> > > data;
};
//}
+ inline void
+ VectorSelector::initialize(const AnyData &src)
+ {
+ value_selection.initialize(src);
+ gradient_selection.initialize(src);
+ hessian_selection.initialize(src);
+ }
+
template <typename DATA>
inline void
VectorSelector::initialize(const NamedData<DATA> &src)
}
+ template <class STREAM, typename DATA>
+ inline void
+ VectorSelector::print(STREAM &s, const AnyData &v) const
+ {
+ s << "values: ";
+ for (unsigned int i=0; i<n_values(); ++i)
+ s << " '" << v.name(value_selection(i)) << '\'';
+ s << std::endl << "gradients:";
+ for (unsigned int i=0; i<n_gradients(); ++i)
+ s << " '" << v.name(gradient_selection(i)) << '\'';
+ s << std::endl << "hessians: ";
+ for (unsigned int i=0; i<n_hessians(); ++i)
+ s << " '" << v.name(hessian_selection(i)) << '\'';
+ s << std::endl;
+ }
+
+
template <class STREAM, typename DATA>
inline void
VectorSelector::print(STREAM &s, const NamedData<DATA> &v) const
{}
+ template <int dim, int spacedim>
+ void
+ VectorDataBase<dim, spacedim>::initialize(const AnyData &d)
+ {
+ this->data = d;
+ VectorSelector::initialize(d);
+ }
+
+
template <int dim, int spacedim>
void
VectorDataBase<dim, spacedim>::fill(
void
VectorData<VECTOR, dim, spacedim>::initialize(const NamedData<VECTOR *> &d)
{
- data = d;
+ this->data = d;
VectorSelector::initialize(d);
}
VectorData<VECTOR, dim, spacedim>::initialize(const VECTOR *v, const std::string &name)
{
SmartPointer<const VECTOR,VectorData<VECTOR, dim, spacedim> > p = v;
- data.add(p, name);
- VectorSelector::initialize(data);
+ this->data.add(p, name);
+ VectorSelector::initialize(this->data);
}
AssertDimension(gradients.size(), this->n_gradients());
AssertDimension(hessians.size(), this->n_hessians());
+ const AnyData& data = this->data;
for (unsigned int i=0; i<this->n_values(); ++i)
{
- const VECTOR &src = *data(this->value_index(i));
+ const VECTOR* src = data.read_ptr<VECTOR>(this->value_index(i));
VectorSlice<std::vector<std::vector<double> > > dst(values[i], component, n_comp);
- fe.get_function_values(src, make_slice(index, start, size), dst, true);
+ fe.get_function_values(*src, make_slice(index, start, size), dst, true);
}
for (unsigned int i=0; i<this->n_gradients(); ++i)
{
- const VECTOR &src = *data(this->gradient_index(i));
+ const VECTOR* src = data.read_ptr<VECTOR>(this->gradient_index(i));
VectorSlice<std::vector<std::vector<Tensor<1,dim> > > > dst(gradients[i], component, n_comp);
- fe.get_function_gradients(src, make_slice(index, start, size), dst, true);
+ fe.get_function_gradients(*src, make_slice(index, start, size), dst, true);
}
for (unsigned int i=0; i<this->n_hessians(); ++i)
{
- const VECTOR &src = *data(this->hessian_index(i));
+ const VECTOR* src = data.read_ptr<VECTOR>(this->hessian_index(i));
VectorSlice<std::vector<std::vector<Tensor<2,dim> > > > dst(hessians[i], component, n_comp);
- fe.get_function_hessians(src, make_slice(index, start, size), dst, true);
+ fe.get_function_hessians(*src, make_slice(index, start, size), dst, true);
}
}
VectorData<VECTOR, dim, spacedim>::memory_consumption () const
{
std::size_t mem = VectorSelector::memory_consumption();
- mem += sizeof (data);
+ mem += sizeof (this->data);
return mem;
}
template <class VECTOR, int dim, int spacedim>
MGVectorData<VECTOR, dim, spacedim>::MGVectorData(const VectorSelector &s)
- :
- VectorDataBase<dim, spacedim>(s)
+ :
+ VectorData<VECTOR, dim, spacedim>(s)
{}
void
MGVectorData<VECTOR, dim, spacedim>::initialize(const NamedData<MGLevelObject<VECTOR>*> &d)
{
- data = d;
+ this->data = d;
VectorSelector::initialize(d);
}
{
SmartPointer<const MGLevelObject<VECTOR>, MGVectorData<VECTOR, dim, spacedim> >
p = v;
- data.add(p, name);
- VectorSelector::initialize(data);
+ this->data.add(p, name);
+ VectorSelector::initialize(this->data);
}
template <class VECTOR, int dim, int spacedim>
void
- MGVectorData<VECTOR, dim, spacedim>::mg_fill(
+ VectorData<VECTOR, dim, spacedim>::mg_fill(
std::vector<std::vector<std::vector<double> > > &values,
std::vector<std::vector<std::vector<Tensor<1,dim> > > > &gradients,
std::vector<std::vector<std::vector<Tensor<2,dim> > > > &hessians,
AssertDimension(gradients.size(), this->n_gradients());
AssertDimension(hessians.size(), this->n_hessians());
+ const AnyData& data = this->data;
for (unsigned int i=0; i<this->n_values(); ++i)
{
- const VECTOR &src = (*data(this->value_index(i)))[level];
+ const MGLevelObject<VECTOR>* src = data.read_ptr<MGLevelObject<VECTOR> >(this->value_index(i));
VectorSlice<std::vector<std::vector<double> > > dst(values[i], component, n_comp);
- fe.get_function_values(src, make_slice(index, start, size), dst, true);
+ fe.get_function_values((*src)[level], make_slice(index, start, size), dst, true);
}
for (unsigned int i=0; i<this->n_gradients(); ++i)
{
- const VECTOR &src = (*data(this->value_index(i)))[level];
+ const MGLevelObject<VECTOR>* src = data.read_ptr<MGLevelObject<VECTOR> >(this->value_index(i));
VectorSlice<std::vector<std::vector<Tensor<1,dim> > > > dst(gradients[i], component, n_comp);
- fe.get_function_gradients(src, make_slice(index, start, size), dst, true);
+ fe.get_function_gradients((*src)[level], make_slice(index, start, size), dst, true);
}
for (unsigned int i=0; i<this->n_hessians(); ++i)
{
- const VECTOR &src = (*data(this->value_index(i)))[level];
+ const MGLevelObject<VECTOR>* src = data.read_ptr<MGLevelObject<VECTOR> >(this->value_index(i));
VectorSlice<std::vector<std::vector<Tensor<2,dim> > > > dst(hessians[i], component, n_comp);
- fe.get_function_hessians(src, make_slice(index, start, size), dst, true);
+ fe.get_function_hessians((*src)[level], make_slice(index, start, size), dst, true);
}
}
-
-
- template <class VECTOR, int dim, int spacedim>
- std::size_t
- MGVectorData<VECTOR, dim, spacedim>::memory_consumption () const
- {
- std::size_t mem = VectorSelector::memory_consumption();
- mem += sizeof (data);
- return mem;
- }
}
DEAL_II_NAMESPACE_CLOSE
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2010 - 2013 by the deal.II authors
+// Copyright (C) 2010 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
typedef std::vector<std::set<types::global_dof_index> >::size_type size_dof;
/**
- * Fill the internal data
- * structures with values
- * extracted from the dof
- * handler.
+ * Fill the internal data structures with values extracted from the dof
+ * handler object.
*
- * This function leaves
- * #boundary_indices empty, since
- * no boundary values are
- * provided.
+ * This function ensures that on every level, degrees of freedom at interior
+ * edges of a refinement level are treated corrected but leaves degrees of
+ * freedom at the boundary of the domain untouched assuming that no
+ * Dirichlet boundary conditions for them exist.
*/
template <int dim, int spacedim>
- void initialize(const DoFHandler<dim,spacedim> &dof);
+ void initialize (const DoFHandler<dim,spacedim> &dof);
/**
- * Fill the internal data
- * structures with values
- * extracted from the dof
- * handler, applying the boundary
- * values provided.
+ * Fill the internal data structures with values extracted from the dof
+ * handler object and apply the boundary values provided.
+ *
+ * This function internally calls the initialize() function above and the
+ * constrains degrees on the external boundary of the domain by calling
+ * MGTools::make_boundary_list() with the given second and third argument.
*/
template <int dim, int spacedim>
void initialize(const DoFHandler<dim,spacedim> &dof,
/**
* Determine whether a dof index is subject to a boundary
- * constraint. (is on boundary of domain)
+ * constraint. (In other words, whether it is on boundary of domain.)
*/
bool is_boundary_index (const unsigned int level,
const types::global_dof_index index) const;
MGConstrainedDoFs::initialize(const DoFHandler<dim,spacedim> &dof)
{
const unsigned int nlevels = dof.get_tria().n_global_levels();
+
+ boundary_indices.resize(nlevels);
+
refinement_edge_indices.resize(nlevels);
refinement_edge_boundary_indices.resize(nlevels);
refinement_edge_indices_old.clear();
refinement_edge_boundary_indices_old.clear();
for (unsigned int l=0; l<nlevels; ++l)
{
+ boundary_indices[l].clear();
+
refinement_edge_indices[l] = IndexSet(dof.n_dofs(l));
refinement_edge_boundary_indices[l] = IndexSet(dof.n_dofs(l));
}
+
MGTools::extract_inner_interface_dofs (dof, refinement_edge_indices,
refinement_edge_boundary_indices);
}
template <int dim, int spacedim>
inline
void
-MGConstrainedDoFs::initialize(
- const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<dim>::type &function_map,
- const ComponentMask &component_mask)
+MGConstrainedDoFs::initialize(const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<dim>::type &function_map,
+ const ComponentMask &component_mask)
{
- const unsigned int nlevels = dof.get_tria().n_global_levels();
- boundary_indices.resize(nlevels);
- refinement_edge_indices.resize(nlevels);
- refinement_edge_boundary_indices.resize(nlevels);
- refinement_edge_indices_old.clear();
- refinement_edge_boundary_indices_old.clear();
-
- for (unsigned int l=0; l<nlevels; ++l)
- {
- boundary_indices[l].clear();
- refinement_edge_indices[l] = IndexSet(dof.n_dofs(l));
- refinement_edge_boundary_indices[l] = IndexSet(dof.n_dofs(l));
- }
-
- MGTools::make_boundary_list (dof, function_map, boundary_indices, component_mask);
- MGTools::extract_inner_interface_dofs (dof, refinement_edge_indices,
- refinement_edge_boundary_indices);
+ initialize (dof);
+
+ MGTools::make_boundary_list (dof,
+ function_map,
+ boundary_indices,
+ component_mask);
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
std::vector<unsigned int> target_component) DEAL_II_DEPRECATED;
/**
- * Generate a list of those
- * degrees of freedom at the
- * boundary which should be
- * eliminated from the matrix.
+ * Generate a list of those degrees of freedom at the boundary of the domain
+ * that should be eliminated from the matrix because they will be
+ * constrained by Dirichlet boundary conditions.
*
- * This is the multilevel
- * equivalent of
- * VectorTools::interpolate_boundary_values,
- * but since the multilevel
- * method does not have its own
- * right hand side, the function
- * values are ignored.
+ * This is the multilevel equivalent of
+ * VectorTools::interpolate_boundary_values, but since the multilevel method
+ * does not have its own right hand side, the function values returned by
+ * the function object that is part of the function_map argument are
+ * ignored.
*
- * @arg <tt>boundary_indices</tt>
- * is a vector which on return
- * contains all indices of
- * boundary constraint degrees of
- * freedom for each level. Its
- * length has to match the number
- * of levels.
+ * @arg <tt>boundary_indices</tt> is a vector which on return contains all
+ * indices of degrees of freedom for each level that are at the part of the
+ * boundary identified by the function_map argument. Its length has to match
+ * the number of levels in the dof handler object.
*/
template <int dim, int spacedim>
void
* the sequence of cells to be converted into patches itself, but relies
* on the two functions first_cell() and next_cell(). By default, they
* return the first active cell, and the next active cell, respectively.
- * Since they are @p virtual functions, you may overload them to select other
- * cells for output. If cells are not active, interpolated values are taken
- * for output instead of the exact values on active cells.
+ * Since they are @p virtual functions, you can write your own class
+ * derived from DataOut in which you overload these two functions to select other
+ * cells for output. This may, for example, include only cells that are
+ * in parts of a domain (e.g., if you don't care about the solution elsewhere,
+ * think for example a buffer region in which you attenuate outgoing waves
+ * in the Perfectly Matched Layer method) or if you don't want output to
+ * be generated at all levels of an adaptively refined mesh because this
+ * creates too much data (in this case, the set of cells returned by
+ * your implementations of first_cell() and next_cell() will include
+ * non-active cells, and DataOut::build_patches() will simply take
+ * interpolated values of the solution instead of the exact values on these
+ * cells children for output). Once you derive your own class, you would
+ * just create an object of this type instead of an object of type DataOut,
+ * and everything else will remain the same.
*
* The two functions are not constant, so you may store information within
* your derived class about the last accessed cell. This is useful if the
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*
* // first declare the vectors
* // to be used later
- * vector<string> solution_names;
+ * std::vector<std::string> solution_names;
* solution_names.push_back ("u");
* solution_names.push_back ("v");
* data_out_stack.declare_data_vector (solution_names,
* component and therefore more than one
* name needs to be given. However, you
* can also call this function with a
- * <tt>vector<string></tt> containing only one
+ * <tt>std::vector@<std::string@></tt> containing only one
* element if the finite element has
* only one component.
*/
* component and therefore more than one
* name needs to be given. However, you
* can also call this function with a
- * <tt>vector<string></tt> containing only one
+ * <tt>std::vector@<std::string@></tt> containing only one
* element if the finite element has
* only one component.
*
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2007 - 2013 by the deal.II authors
+// Copyright (C) 2007 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
+ * This class provides an interface to compute derived quantities from
+ * a solution that can then be output in graphical formats for visualization,
+ * using facilities such as the DataOut class.
+ *
* For the (graphical) output of a FE solution one frequently wants to include
* derived quantities, which are calculated from the values of the solution
* and possibly the first and second derivates of the solution. Examples are
- * the calculation Mach numbers from velocity and density in supersonic flow
+ * the calculation of Mach numbers from velocity and density in supersonic flow
* computations, or the computation of the magnitude of a complex-valued
* solution as demonstrated in step-29. Other uses are shown in step-32 and
* step-33. This class offers the interface to perform such
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
//
// ---------------------------------------------------------------------
-#ifndef __deal2__gradient_estimator_h
-#define __deal2__gradient_estimator_h
+#ifndef __deal2__derivative_approximation_h
+#define __deal2__derivative_approximation_h
#include <deal.II/base/config.h>
#include <deal.II/base/exceptions.h>
* In a parallel computation the @p solution vector needs to contain the
* locally relevant unknowns.
*/
- template <int dim, template <int, int> class DH, class InputVector, int order, int spacedim>
+ template <class DH, class InputVector, int order>
void
- approximate_derivative_tensor (const Mapping<dim,spacedim> &mapping,
- const DH<dim,spacedim> &dof,
+ approximate_derivative_tensor (const Mapping<DH::dimension,DH::space_dimension> &mapping,
+ const DH &dof,
const InputVector &solution,
- const typename DH<dim,spacedim>::active_cell_iterator &cell,
- Tensor<order,dim> &derivative,
+ const typename DH::active_cell_iterator &cell,
+ Tensor<order,DH::dimension> &derivative,
const unsigned int component = 0);
/**
* Same as above, with <tt>mapping=MappingQ1@<dim@>()</tt>.
*/
- template <int dim, template <int, int> class DH, class InputVector, int order, int spacedim>
+ template <class DH, class InputVector, int order>
void
- approximate_derivative_tensor (const DH<dim,spacedim> &dof,
+ approximate_derivative_tensor (const DH &dof,
const InputVector &solution,
- const typename DH<dim,spacedim>::active_cell_iterator &cell,
- Tensor<order,dim> &derivative,
+ const typename DH::active_cell_iterator &cell,
+ Tensor<order,DH::dimension> &derivative,
const unsigned int component = 0);
/**
#define __deal2__dof_output_operator_h
#include <deal.II/base/config.h>
+#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/named_data.h>
+#include <deal.II/algorithms/any_data.h>
#include <deal.II/base/event.h>
#include <deal.II/algorithms/operator.h>
#include <deal.II/dofs/dof_handler.h>
+#include <deal.II/numerics/data_out.h>
#include <fstream>
namespace Algorithms
{
+ /**
+ * An output operator writing a separate file in each step and
+ * writing the vectors as finite element functions with respect to a
+ * given DoFHandler.
+ */
template <class VECTOR, int dim, int spacedim=dim>
class DoFOutputOperator : public OutputOperator<VECTOR>
{
public:
- void initialize (DoFHandler<dim, spacedim> &dof_handler);
+ /*
+ * Constructor. The <tt>filename</tt> is the common base name of
+ * all files and the argument <tt>digits</tt> should be the number
+ * of digits of the highest number in the sequence. File names by
+ * default have the form "outputNN" with NNN the number set by the
+ * last step command. Numbers with less digits are filled with
+ * zeros from the left.
+ */
+ DoFOutputOperator (const std::string filename_base = std::string("output"),
+ const unsigned int digits = 3);
+
+ void parse_parameters(ParameterHandler ¶m);
+ void initialize (const DoFHandler<dim, spacedim> &dof_handler);
virtual OutputOperator<VECTOR> &
- operator<<(const NamedData<VECTOR *> &vectors);
+ operator << (const AnyData &vectors);
private:
- SmartPointer<DoFHandler<dim, spacedim>,
+ SmartPointer<const DoFHandler<dim, spacedim>,
DoFOutputOperator<VECTOR, dim, spacedim> > dof;
+
+ const std::string filename_base;
+ const unsigned int digits;
+
+ DataOut<dim> out;
};
template <class VECTOR, int dim, int spacedim>
- void DoFOutputOperator<VECTOR, dim, spacedim>::initialize(
- DoFHandler<dim, spacedim> &dof_handler)
+ inline void
+ DoFOutputOperator<VECTOR, dim, spacedim>::initialize(const DoFHandler<dim, spacedim> &dof_handler)
{
dof = &dof_handler;
}
#include <deal.II/numerics/dof_output_operator.h>
-#include <deal.II/numerics/data_out.h>
DEAL_II_NAMESPACE_OPEN
namespace Algorithms
{
+ template <class VECTOR, int dim, int spacedim>
+ DoFOutputOperator<VECTOR, dim, spacedim>::DoFOutputOperator (
+ const std::string filename_base,
+ const unsigned int digits)
+ :
+ filename_base(filename_base),
+ digits(digits)
+ {
+ out.set_default_format(DataOutBase::gnuplot);
+ }
+
+
+ template <class VECTOR, int dim, int spacedim>
+ void
+ DoFOutputOperator<VECTOR, dim, spacedim>::parse_parameters(ParameterHandler ¶m)
+ {
+ out.parse_parameters(param);
+ }
+
template <class VECTOR, int dim, int spacedim>
OutputOperator<VECTOR> &
DoFOutputOperator<VECTOR, dim, spacedim>::operator<<(
- const NamedData<VECTOR *> &vectors)
+ const AnyData &data)
{
Assert ((dof!=0), ExcNotInitialized());
- DataOut<dim> out;
out.attach_dof_handler (*dof);
- out.add_data_vector (*vectors(vectors.find("solution")), "solution");
- out.add_data_vector (*vectors(vectors.find("update")), "update");
- out.add_data_vector (*vectors(vectors.find("residual")), "residual");
+ for (unsigned int i=0; i<data.size(); ++i)
+ {
+ const VECTOR *p = data.try_read_ptr<VECTOR>(i);
+ if (p!=0)
+ {
+ out.add_data_vector (*p, data.name(i));
+ }
+ }
std::ostringstream streamOut;
- streamOut << "Newton_" << std::setw(3) << std::setfill('0') << this->step;
+ streamOut << filename_base
+ << std::setw(digits) << std::setfill('0') << this->step
+ << out.default_suffix();
std::ofstream out_filename (streamOut.str().c_str());
- out.build_patches (2);
- out.write_gnuplot (out_filename);
+ out.build_patches ();
+ out.write (out_filename);
+ out.clear ();
return *this;
}
}
* too expensive without direct access to
* the PETSc data structures. (This leads
* to the situation where the action
- * indicates by the default value of the
+ * indicated by the default value of the
* last argument is actually not
* implemented; that argument has
* <code>true</code> as its default value
* direct access to the Trilinos
* data structures. (This leads to
* the situation where the action
- * indicates by the default value
+ * indicated by the default value
* of the last argument is actually
* not implemented; that argument
* has <code>true</code> as its
* direct access to the Trilinos
* data structures. (This leads to
* the situation where the action
- * indicates by the default value
+ * indicated by the default value
* of the last argument is actually
* not implemented; that argument
* has <code>true</code> as its
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
* This class implements the transfer of a discrete FE function
* (e.g. a solution vector) from one mesh to another that is obtained
- * by the first by a single refinement and/or coarsening step. During
+ * from the first by a single refinement and/or coarsening step. During
* interpolation the vector is reinitialized to the new size and
* filled with the interpolated values. This class is used in the
- * step-15, step-31, and step-33 tutorial programs.
+ * step-15, step-31, and step-33 tutorial programs. A version of this
+ * class that works on parallel triangulations is available as
+ * parallel::distributed::SolutionTransfer.
*
* <h3>Usage</h3>
*
* </ul>
*
*
+ * <h3>Interaction with hanging nodes</h3>
+ *
+ * This class does its best to represent on the new mesh the finite element
+ * function that existed on the old mesh, but this may lead to situations
+ * where the function on the new mesh is no longer conforming at hanging
+ * nodes. To this end, consider a situation of a twice refined mesh that
+ * started with a single square cell (i.e., we now have 16 cells). Consider
+ * also that we coarsen 4 of the cells back to the first refinement level. In
+ * this case, we end up with a mesh that will look as follows if we were to
+ * use a $Q_1$ element:
+ *
+ * @image html hanging_nodes.png ""
+ *
+ * The process of interpolating from the old to the new mesh would imply that
+ * the values of the finite element function will not change on all of the
+ * cells that remained as they are (i.e., the fine cells) but that on the
+ * coarse cell at the top right, the four values at the vertices are obtained
+ * by interpolating down from its former children. If the original function
+ * was not linear, this implies that the marked hanging nodes will retain
+ * their old values which, in general, will not lead to a continuous function
+ * along the corresponding edges. In other words, the solution vector obtained
+ * after SolutionTransfer::interpolate() does not satisfy hanging node
+ * constraints: it corresponds to the pointwise interpolation, but not to the
+ * interpolation <i>onto the new finite element space that contains
+ * constraints from hanging nodes</i>.
+ *
+ * Whether this is a problem you need to worry about or not depends on your
+ * application. The situation is easily corrected, of course, by applying
+ * ConstraintMatrix::distribute() to your solution vector after transfer,
+ * using a constraint matrix object computed on the new DoFHandler object (you
+ * probably need to create this object anyway if you have hanging nodes). This
+ * is also what is done, for example, in step-15.
+ *
+ * @note This situation can only happen if you do coarsening. If all cells
+ * remain as they are or are refined, then SolutionTransfer::interpolate()
+ * computes a new vector of nodel values, but the function represented is of
+ * course exactly the same because the old finite element space is a subspace
+ * of the new one. Thus, if the old function was conforming (i.e., satisfied
+ * hanging node constraints), then so does the new one, and it is not
+ * necessary to call ConstraintMatrix::distribute().
+ *
+ *
* <h3>Implementation in the context of hp finite elements</h3>
*
- * In the case of hp::DoFHandlers, it is not defined which of the finite elements
+ * In the case of hp::DoFHandlers, nothing defines which of the finite elements
* that are part of the hp::FECollection associated with the DoF handler, should
* be considered on cells that are not active (i.e., that have children). This
* is because degrees of freedom are only allocated for active cells and, in fact,
* Q3, in this example, if the user has set the active_fe_index for a different
* space post-refinement and before calling hp::DoFHandler::distribute_dofs()).
*
+ * @note In the context of hp refinement, if cells are coarsened or the
+ * polynomial degree is lowered on some cells, then the old finite element
+ * space is not a subspace of the new space and you may run into the same
+ * situation as discussed above with hanging nodes. You may want to consider
+ * calling ConstraintMatrix::distribute() on the vector obtained by
+ * transfering the solution.
*
* @ingroup numerics
- * @author Ralf Hartmann, 1999, Oliver Kayser-Herold and Wolfgang Bangerth, 2006, 2014
+ * @author Ralf Hartmann, 1999, Oliver Kayser-Herold and Wolfgang Bangerth, 2006, Wolfgang Bangerth 2014
*/
template<int dim, typename VECTOR=Vector<double>, class DH=DoFHandler<dim> >
class SolutionTransfer
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
/**
- * This function computes the constraints that correspond to boundary conditions of the
- * form $\vec n \cdot \vec u=0$, i.e. no normal flux if $\vec u$ is a
- * vector-valued quantity. These conditions have exactly the form handled by
- * the ConstraintMatrix class, so instead of creating a map between boundary
- * degrees of freedom and corresponding value, we here create a list of
- * constraints that are written into a ConstraintMatrix. This object may
- * already have some content, for example from hanging node constraints,
- * that remains untouched. These constraints have to be applied to the
- * linear system like any other such constraints, i.e. you have to condense
- * the linear system with the constraints before solving, and you have to
- * distribute the solution vector afterwards.
+ * This function computes the constraints that correspond to boundary
+ * conditions of the form $\vec u \cdot \vec n=\vec u_\Gamma \cdot \vec n$,
+ * i.e. normal flux constraints if $\vec u$ is a vector-valued quantity.
+ * These conditions have exactly the form handled by the ConstraintMatrix
+ * class, so instead of creating a map between boundary degrees of freedom
+ * and corresponding value, we here create a list of constraints that are
+ * written into a ConstraintMatrix. This object may already have some
+ * content, for example from hanging node constraints, that remains
+ * untouched. These constraints have to be applied to the linear system
+ * like any other such constraints, i.e. you have to condense the linear
+ * system with the constraints before solving, and you have to distribute
+ * the solution vector afterwards.
*
* The use of this function is explained in more detail in step-31. It
* doesn't make much sense in 1d, so the function throws an exception in
* first_vector_component would be zero. On the other hand, if we solved the
* Maxwell equations in 3d and the finite element has components
* $(E_x,E_y,E_z,B_x,B_y,B_z)$ and we want the boundary condition $\vec
- * n\cdot \vec B=0$, then @p first_vector_component would be 3. Vectors are
- * implicitly assumed to have exactly <code>dim</code> components that are
- * ordered in the same way as we usually order the coordinate directions,
- * i.e. $x$-, $y$-, and finally $z$-component. The function assumes, but
- * can't check, that the vector components in the range
+ * B\cdot \vec n=\vec B_\Gamma\cdot \vec n$, then @p first_vector_component
+ * would be 3. Vectors are implicitly assumed to have exactly <code>dim</code>
+ * components that are ordered in the same way as we usually order the
+ * coordinate directions, i.e. $x$-, $y$-, and finally $z$-component. The
+ * function assumes, but can't check, that the vector components in the range
* <code>[first_vector_component,first_vector_component+dim)</code> come
* from the same base finite element. For example, in the Stokes example
* above, it would not make sense to use a
* call the function onces with the whole set of boundary indicators at
* once.
*
+ * The forth parameter describes the boundary function that is used for
+ * computing these constraints.
+ *
* The mapping argument is used to compute the boundary points where the
* function needs to request the normal vector $\vec n$ from the boundary
* description.
* right are meant to approximate a curved boundary (as indicated by the
* dashed line), then neither of the two computed normal vectors are equal
* to the exact normal vector (though they approximate it as the mesh is
- * refined further). What is worse, if we constrain $\vec n \cdot \vec u=0$
- * at the common vertex with the normal vector from both cells, then we
- * constrain the vector $\vec u$ with respect to two linearly independent
- * vectors; consequently, the constraint would be $\vec u=0$ at this point
- * (i.e. <i>all</i> components of the vector), which is not what we wanted.
+ * refined further). What is worse, if we constrain $\vec u \cdot \vec n=
+ * \vec u_\Gamma \cdot \vec n$ at the common vertex with the normal vector
+ * from both cells, then we constrain the vector $\vec u$ with respect to
+ * two linearly independent vectors; consequently, the constraint would be
+ * $\vec u=\vec u_\Gamma$ at this point (i.e. <i>all</i> components of the
+ * vector), which is not what we wanted.
*
* To deal with this situation, the algorithm works in the following way: at
* each point where we want to constrain $\vec u$, we first collect all
* normal vectors that adjacent cells might compute at this point. We then
- * do not constrain $\vec n \cdot \vec u=0$ for <i>each</i> of these normal
- * vectors but only for the <i>average</i> of the normal vectors. In the
- * example above, we therefore record only a single constraint $\vec n \cdot
- * \vec {\bar u}=0$, where $\vec {\bar u}$ is the average of the two
- * indicated normal vectors.
+ * do not constrain $\vec u \cdot \vec n=\vec u_\Gamma \cdot \vec n$ for
+ * <i>each</i> of these normal vectors but only for the <i>average</i> of
+ * the normal vectors. In the example above, we therefore record only a
+ * single constraint $\vec u \cdot \vec {\bar n}=\vec u_\Gamma \cdot \vec
+ * {\bar n}$, where $\vec {\bar n}$ is the average of the two indicated
+ * normal vectors.
*
* Unfortunately, this is not quite enough. Consider the situation here:
*
* point per invocation (because we consider only one boundary part at a
* time), with the result that the normal vectors will not be averaged. This
* situation also needs to be taken into account when using this function
- * around reentrant corners on Cartesian meshes. If no-normal-flux boundary
+ * around reentrant corners on Cartesian meshes. If normal-flux boundary
* conditions are to be enforced on non-Cartesian meshes around reentrant
* corners, one may even get cycles in the constraints as one will in
* general constrain different components from the two sides. In that case,
* front faces of the left cell belong to the boundary selected whereas only
* the top face of the right cell belongs to it, maybe indicating the the entire
* front part of the domain is a smooth manifold whereas the top really forms
- * two separate manifolds that meet in a ridge, and that no-flux boundary
+ * two separate manifolds that meet in a ridge, and that normal-flux boundary
* conditions are only desired on the front manifold and the right one on top.
* In cases like these, it's difficult to define what should happen. The
* current implementation simply ignores the one contribution from the
*/
template <int dim, template <int, int> class DH, int spacedim>
void
+ compute_nonzero_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ typename FunctionMap<spacedim>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping = StaticMappingQ1<dim>::mapping);
+
+ /**
+ * Same as above for homogeneous normal-flux constraints.
+ *
+ * @ingroup constraints
+ *
+ * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
+ */
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
compute_no_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
const unsigned int first_vector_component,
const std::set<types::boundary_id> &boundary_ids,
/**
* Compute the constraints that correspond to boundary conditions of the
- * form $\vec n \times \vec u=0$, i.e. flow normal to the boundary if $\vec
- * u$ is a vector-valued quantity. This function constrains exactly those
- * vector-valued components that are left unconstrained by
- * compute_no_normal_flux_constraints, and leaves the one component
- * unconstrained that is constrained by compute_no_normal_flux_constraints.
+ * form $\vec u \times \vec n=\vec u_\Gamma \times \vec n$, i.e. tangential
+ * flow constraints if $\vec u$ is a vector-valued quantity. This function
+ * constrains exactly those vector-valued components that are left
+ * unconstrained by compute_no_normal_flux_constraints, and leaves the one
+ * component unconstrained that is constrained by
+ * compute_no_normal_flux_constraints.
+ *
+ * @ingroup constraints
+ *
+ * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
+ */
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+ compute_nonzero_tangential_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ typename FunctionMap<spacedim>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping = StaticMappingQ1<dim>::mapping);
+
+ /**
+ * Same as above for homogeneous tangential-flux constraints.
+ *
+ * @ingroup constraints
+ *
+ * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
*/
template <int dim, template <int, int> class DH, int spacedim>
void
#include <cmath>
#include <limits>
#include <set>
+#include <list>
DEAL_II_NAMESPACE_OPEN
// will be used
template <class DH,
template <int,int> class M_or_MC,
- int dim_>
+ int dim_>
static inline
void
do_interpolate_boundary_values (const M_or_MC<DH::dimension, DH::space_dimension> &mapping,
/**
* Add the constraint
- * $\vec n \cdot \vec u = 0$
+ * $\vec n \cdot \vec u = inhom$
* to the list of constraints.
*
* Here, $\vec u$ is represented
void
add_constraint (const VectorDoFTuple<dim> &dof_indices,
const Tensor<1,dim> &constraining_vector,
- ConstraintMatrix &constraints)
+ ConstraintMatrix &constraints,
+ const double inhomogeneity=0)
{
// choose the DoF that has the
constraints.add_entry (dof_indices.dof_indices[0],
dof_indices.dof_indices[1],
-constraining_vector[1]/constraining_vector[0]);
+
+ if (std::fabs (inhomogeneity/constraining_vector[0])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[0],
+ inhomogeneity/constraining_vector[0]);
}
}
else
constraints.add_entry (dof_indices.dof_indices[1],
dof_indices.dof_indices[0],
-constraining_vector[0]/constraining_vector[1]);
+
+ if (std::fabs (inhomogeneity/constraining_vector[1])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[1],
+ inhomogeneity/constraining_vector[1]);
}
}
break;
constraints.add_entry (dof_indices.dof_indices[0],
dof_indices.dof_indices[2],
-constraining_vector[2]/constraining_vector[0]);
+
+ if (std::fabs (inhomogeneity/constraining_vector[0])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[0],
+ inhomogeneity/constraining_vector[0]);
}
}
else if ((std::fabs(constraining_vector[1])+1e-10 >= std::fabs(constraining_vector[0]))
constraints.add_entry (dof_indices.dof_indices[1],
dof_indices.dof_indices[2],
-constraining_vector[2]/constraining_vector[1]);
+
+ if (std::fabs (inhomogeneity/constraining_vector[1])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[1],
+ inhomogeneity/constraining_vector[1]);
}
}
else
constraints.add_entry (dof_indices.dof_indices[2],
dof_indices.dof_indices[1],
-constraining_vector[1]/constraining_vector[2]);
+
+ if (std::fabs (inhomogeneity/constraining_vector[2])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[2],
+ inhomogeneity/constraining_vector[2]);
}
}
/**
- * Add the constraint $\vec u \|
+ * Add the constraint $(\vec u-\vec u_\Gamma) \|
* \vec t$ to the list of
* constraints. In 2d, this is a
* single constraint, in 3d these
*/
template <int dim>
void
- add_tangentiality_constraints (const VectorDoFTuple<dim> &dof_indices,
- const Tensor<1,dim> &tangent_vector,
- ConstraintMatrix &constraints)
+ add_tangentiality_constraints
+ (const VectorDoFTuple<dim> &dof_indices,
+ const Tensor<1,dim> &tangent_vector,
+ ConstraintMatrix &constraints,
+ const Vector<double> &b_values = Vector<double>(dim))
{
// choose the DoF that has the
// component 0 of the tangent
// vector t is largest by
// magnitude, then
- // x1=t[1]/t[0]*x_0, etc.
+ // x1=(b[1]*t[0]-b[0]*t[1])/t[0]+t[1]/t[0]*x_0, etc.
unsigned int largest_component = 0;
for (unsigned int d=1; d<dim; ++d)
if (std::fabs(tangent_vector[d]) > std::fabs(tangent_vector[largest_component]) + 1e-10)
constraints.add_entry (dof_indices.dof_indices[d],
dof_indices.dof_indices[largest_component],
tangent_vector[d]/tangent_vector[largest_component]);
+
+ const double inhomogeneity
+ = (b_values(d)*tangent_vector[largest_component]
+ -b_values(largest_component)*tangent_vector[d])
+ /tangent_vector[largest_component];
+
+ if (std::fabs(inhomogeneity)
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(dof_indices.dof_indices[d],
+ inhomogeneity);
}
}
+ values[q_point] (first_vector_component + 1)
* tangentials[q_point] (1))
* (fe_values[vec].value (fe.face_to_cell_index (i, face), q_point)
- * tangentials[q_point])
- / std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
- * jacobians[q_point][0][face_coordinate_direction[face]]
- + jacobians[q_point][1][face_coordinate_direction[face]]
- * jacobians[q_point][1][face_coordinate_direction[face]]);
+ * tangentials[q_point]);
if (q_point == 0)
dofs_processed[i] = true;
const std::set<types::boundary_id> &boundary_ids,
ConstraintMatrix &constraints,
const Mapping<dim, spacedim> &mapping)
+ {
+ ZeroFunction<dim>zero_function(dim);
+ typename FunctionMap<spacedim>::type function_map;
+ std::set<types::boundary_id>::const_iterator it
+ = boundary_ids.begin();
+ for (;it != boundary_ids.end(); ++it)
+ function_map[*it] = &zero_function;
+ compute_nonzero_normal_flux_constraints(dof_handler,
+ first_vector_component,
+ boundary_ids,
+ function_map,
+ constraints,
+ mapping);
+ }
+
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+ compute_nonzero_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ typename FunctionMap<spacedim>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping)
{
Assert (dim > 1,
ExcMessage ("This function is not useful in 1d because it amounts "
// FE
hp::QCollection<dim-1> face_quadrature_collection;
for (unsigned int i=0; i<fe_collection.size(); ++i)
- {
- const std::vector<Point<dim-1> > &
- unit_support_points = fe_collection[i].get_unit_face_support_points();
+ {
+ const std::vector<Point<dim-1> > &
+ unit_support_points = fe_collection[i].get_unit_face_support_points();
- Assert (unit_support_points.size() == fe_collection[i].dofs_per_face,
- ExcInternalError());
+ Assert (unit_support_points.size() == fe_collection[i].dofs_per_face,
+ ExcInternalError());
- face_quadrature_collection
- .push_back (Quadrature<dim-1> (unit_support_points));
- }
+ face_quadrature_collection.push_back (Quadrature<dim-1> (unit_support_points));
+ }
// now create the object with which we will generate the normal vectors
hp::FEFaceValues<dim,spacedim> x_fe_face_values (mapping_collection,
std::multimap<internal::VectorDoFTuple<dim>,
std::pair<Tensor<1,dim>, typename DH<dim,spacedim>::active_cell_iterator> >
DoFToNormalsMap;
+ std::map<internal::VectorDoFTuple<dim>, Vector<double> >
+ dof_vector_to_b_values;
DoFToNormalsMap dof_to_normals_map;
typename DH<dim,spacedim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
+ std::set<types::boundary_id>::iterator b_id;
for (; cell!=endc; ++cell)
if (!cell->is_artificial())
for (unsigned int face_no=0; face_no < GeometryInfo<dim>::faces_per_cell;
++face_no)
- if (boundary_ids.find(cell->face(face_no)->boundary_indicator())
+ if ((b_id=boundary_ids.find(cell->face(face_no)->boundary_indicator()))
!= boundary_ids.end())
- {
- const FiniteElement<dim> &fe = cell->get_fe ();
- typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
+ {
+ const FiniteElement<dim> &fe = cell->get_fe ();
+ typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
- // get the indices of the dofs on this cell...
- face_dofs.resize (fe.dofs_per_face);
- face->get_dof_indices (face_dofs, cell->active_fe_index());
+ // get the indices of the dofs on this cell...
+ face_dofs.resize (fe.dofs_per_face);
+ face->get_dof_indices (face_dofs, cell->active_fe_index());
- x_fe_face_values.reinit (cell, face_no);
- const FEFaceValues<dim> &fe_values = x_fe_face_values.get_present_fe_values();
+ x_fe_face_values.reinit (cell, face_no);
+ const FEFaceValues<dim> &fe_values = x_fe_face_values.get_present_fe_values();
- // then identify which of them correspond to the selected set of
- // vector components
- for (unsigned int i=0; i<face_dofs.size(); ++i)
- if (fe.face_system_to_component_index(i).first ==
- first_vector_component)
- {
- // find corresponding other components of vector
- internal::VectorDoFTuple<dim> vector_dofs;
- vector_dofs.dof_indices[0] = face_dofs[i];
-
- Assert(first_vector_component+dim<=fe.n_components(),
- ExcMessage("Error: the finite element does not have enough components "
- "to define a normal direction."));
-
- for (unsigned int k=0; k<fe.dofs_per_face; ++k)
- if ((k != i)
- &&
- (face_quadrature_collection[cell->active_fe_index()].point(k) ==
- face_quadrature_collection[cell->active_fe_index()].point(i))
- &&
- (fe.face_system_to_component_index(k).first >=
- first_vector_component)
- &&
- (fe.face_system_to_component_index(k).first <
- first_vector_component + dim))
- vector_dofs.dof_indices[fe.face_system_to_component_index(k).first -
- first_vector_component]
- = face_dofs[k];
-
- for (unsigned int d=0; d<dim; ++d)
- Assert (vector_dofs.dof_indices[d] < dof_handler.n_dofs(),
- ExcInternalError());
-
- // we need the normal vector on this face. we know that it
- // is a vector of length 1 but at least with higher order
- // mappings it isn't always possible to guarantee that
- // each component is exact up to zero tolerance. in
- // particular, as shown in the deal.II/no_flux_06 test, if
- // we just take the normal vector as given by the
- // fe_values object, we can get entries in the normal
- // vectors of the unit cube that have entries up to
- // several times 1e-14.
- //
- // the problem with this is that this later yields
- // constraints that are circular (e.g., in the testcase,
- // we get constraints of the form
- //
- // x22 = 2.93099e-14*x21 + 2.93099e-14*x23
- // x21 = -2.93099e-14*x22 + 2.93099e-14*x21
- //
- // in both of these constraints, the small numbers should
- // be zero and the constraints should simply be
- // x22 = x21 = 0
- //
- // to achieve this, we utilize that we know that the
- // normal vector has (or should have) length 1 and that we
- // can simply set small elements to zero (without having
- // to check that they are small *relative to something
- // else*). we do this and then normalize the length of the
- // vector back to one, just to be on the safe side
- //
- // one more point: we would like to use the "real" normal
- // vector here, as provided by the boundary description
- // and as opposed to what we get from the FEValues object.
- // we do this in the immediately next line, but as is
- // obvious, the boundary only has a vague idea which side
- // of a cell it is on -- indicated by the face number. in
- // other words, it may provide the inner or outer normal.
- // by and large, there is no harm from this, since the
- // tangential vector we compute is still the same. however,
- // we do average over normal vectors from adjacent cells
- // and if they have recorded normal vectors from the inside
- // once and from the outside the other time, then this
- // averaging is going to run into trouble. as a consequence
- // we ask the mapping after all for its normal vector,
- // but we only ask it so that we can possibly correct the
- // sign of the normal vector provided by the boundary
- // if they should point in different directions. this is the
- // case in tests/deal.II/no_flux_11.
- std::vector<Point<dim> > vertices(GeometryInfo<dim>::vertices_per_face);
- for(unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
- vertices[v] = cell->face(face_no)->vertex(v);
- Point<dim> normal_vector
- = (cell->face(face_no)->get_boundary()
- .normal_vector (vertices, fe_values.quadrature_point(i)));
- if (normal_vector * fe_values.normal_vector(i) < 0)
- normal_vector *= -1;
- Assert (std::fabs(normal_vector.norm() - 1) < 1e-14,
- ExcInternalError());
- for (unsigned int d=0; d<dim; ++d)
- if (std::fabs(normal_vector[d]) < 1e-13)
- normal_vector[d] = 0;
- normal_vector /= normal_vector.norm();
-
- // now enter the (dofs,(normal_vector,cell)) entry into
- // the map
- dof_to_normals_map
- .insert (std::make_pair (vector_dofs,
- std::make_pair (normal_vector,
- cell)));
+ // then identify which of them correspond to the selected set of
+ // vector components
+ for (unsigned int i=0; i<face_dofs.size(); ++i)
+ if (fe.face_system_to_component_index(i).first ==
+ first_vector_component)
+ {
+ // find corresponding other components of vector
+ internal::VectorDoFTuple<dim> vector_dofs;
+ vector_dofs.dof_indices[0] = face_dofs[i];
+
+ Assert(first_vector_component+dim<=fe.n_components(),
+ ExcMessage("Error: the finite element does not have enough components "
+ "to define a normal direction."));
+
+ for (unsigned int k=0; k<fe.dofs_per_face; ++k)
+ if ((k != i)
+ &&
+ (face_quadrature_collection[cell->active_fe_index()].point(k) ==
+ face_quadrature_collection[cell->active_fe_index()].point(i))
+ &&
+ (fe.face_system_to_component_index(k).first >=
+ first_vector_component)
+ &&
+ (fe.face_system_to_component_index(k).first <
+ first_vector_component + dim))
+ vector_dofs.dof_indices[fe.face_system_to_component_index(k).first -
+ first_vector_component]
+ = face_dofs[k];
+
+ for (unsigned int d=0; d<dim; ++d)
+ Assert (vector_dofs.dof_indices[d] < dof_handler.n_dofs(),
+ ExcInternalError());
+
+ // we need the normal vector on this face. we know that it
+ // is a vector of length 1 but at least with higher order
+ // mappings it isn't always possible to guarantee that
+ // each component is exact up to zero tolerance. in
+ // particular, as shown in the deal.II/no_flux_06 test, if
+ // we just take the normal vector as given by the
+ // fe_values object, we can get entries in the normal
+ // vectors of the unit cube that have entries up to
+ // several times 1e-14.
+ //
+ // the problem with this is that this later yields
+ // constraints that are circular (e.g., in the testcase,
+ // we get constraints of the form
+ //
+ // x22 = 2.93099e-14*x21 + 2.93099e-14*x23
+ // x21 = -2.93099e-14*x22 + 2.93099e-14*x21
+ //
+ // in both of these constraints, the small numbers should
+ // be zero and the constraints should simply be
+ // x22 = x21 = 0
+ //
+ // to achieve this, we utilize that we know that the
+ // normal vector has (or should have) length 1 and that we
+ // can simply set small elements to zero (without having
+ // to check that they are small *relative to something
+ // else*). we do this and then normalize the length of the
+ // vector back to one, just to be on the safe side
+ //
+ // one more point: we would like to use the "real" normal
+ // vector here, as provided by the boundary description
+ // and as opposed to what we get from the FEValues object.
+ // we do this in the immediately next line, but as is
+ // obvious, the boundary only has a vague idea which side
+ // of a cell it is on -- indicated by the face number. in
+ // other words, it may provide the inner or outer normal.
+ // by and large, there is no harm from this, since the
+ // tangential vector we compute is still the same. however,
+ // we do average over normal vectors from adjacent cells
+ // and if they have recorded normal vectors from the inside
+ // once and from the outside the other time, then this
+ // averaging is going to run into trouble. as a consequence
+ // we ask the mapping after all for its normal vector,
+ // but we only ask it so that we can possibly correct the
+ // sign of the normal vector provided by the boundary
+
+ // if they should point in different directions. this is the
+ // case in tests/deal.II/no_flux_11.
+ AssertThrow(false, ExcNotImplemented());
+ // ============================================================
+ // Commented from HERE
+
+ // Point<dim> normal_vector
+ // = (cell->face(face_no)->get_boundary().normal_vector
+ // (cell->face(face_no), fe_values.quadrature_point(i)));
+ // if (normal_vector * fe_values.normal_vector(i) < 0)
+ // normal_vector *= -1;
+ // Assert (std::fabs(normal_vector.norm() - 1) < 1e-14,
+ // ExcInternalError());
+ // for (unsigned int d=0; d<dim; ++d)
+ // if (std::fabs(normal_vector[d]) < 1e-13)
+ // normal_vector[d] = 0;
+ // normal_vector /= normal_vector.norm();
+
+ // const Point<dim> point
+ // = fe_values.quadrature_point(i);
+ // Vector<double> b_values(dim);
+ // function_map[*b_id]->vector_value(point, b_values);
+
+ // // now enter the (dofs,(normal_vector,cell)) entry into
+ // // the map
+ // dof_to_normals_map.insert
+ // (std::make_pair (vector_dofs,
+ // std::make_pair (normal_vector,cell)));
+ // dof_vector_to_b_values.insert
+ // (std::make_pair(vector_dofs, b_values));
+
+ // ============================================================
+ // TO HERE
#ifdef DEBUG_NO_NORMAL_FLUX
- std::cout << "Adding normal vector:" << std::endl
- << " dofs=" << vector_dofs << std::endl
- << " cell=" << cell << " at " << cell->center() << std::endl
- << " normal=" << normal_vector << std::endl;
+ std::cout << "Adding normal vector:" << std::endl
+ << " dofs=" << vector_dofs << std::endl
+ << " cell=" << cell << " at " << cell->center() << std::endl
+ << " normal=" << normal_vector << std::endl;
#endif
- }
- }
+ }
+ }
// Now do something with the collected information. To this end, loop
// through all sets of pairs (dofs,normal_vector) and identify which
p = dof_to_normals_map.begin();
while (p != dof_to_normals_map.end())
- {
- // first find the range of entries in the multimap that corresponds to
- // the same vector-dof tuple. as usual, we define the range
- // half-open. the first entry of course is 'p'
- typename DoFToNormalsMap::const_iterator same_dof_range[2]
- = { p };
- for (++p; p != dof_to_normals_map.end(); ++p)
- if (p->first != same_dof_range[0]->first)
- {
- same_dof_range[1] = p;
- break;
- }
- if (p == dof_to_normals_map.end())
- same_dof_range[1] = dof_to_normals_map.end();
+ {
+ // first find the range of entries in the multimap that corresponds to
+ // the same vector-dof tuple. as usual, we define the range
+ // half-open. the first entry of course is 'p'
+ typename DoFToNormalsMap::const_iterator same_dof_range[2] = { p };
+ for (++p; p != dof_to_normals_map.end(); ++p)
+ if (p->first != same_dof_range[0]->first)
+ {
+ same_dof_range[1] = p;
+ break;
+ }
+ if (p == dof_to_normals_map.end())
+ same_dof_range[1] = dof_to_normals_map.end();
#ifdef DEBUG_NO_NORMAL_FLUX
- std::cout << "For dof indices <" << p->first << ">, found the following normals"
+ std::cout << "For dof indices <" << p->first << ">, found the following normals"
+ << std::endl;
+ for (typename DoFToNormalsMap::const_iterator
+ q = same_dof_range[0];
+ q != same_dof_range[1]; ++q)
+ std::cout << " " << q->second.first
+ << " from cell " << q->second.second
<< std::endl;
- for (typename DoFToNormalsMap::const_iterator
- q = same_dof_range[0];
- q != same_dof_range[1]; ++q)
- std::cout << " " << q->second.first
- << " from cell " << q->second.second
- << std::endl;
#endif
- // now compute the reverse mapping: for each of the cells that
- // contributed to the current set of vector dofs, add up the normal
- // vectors. the values of the map are pairs of normal vectors and
- // number of cells that have contributed
- typedef
- std::map
- <typename DH<dim,spacedim>::active_cell_iterator,
- std::pair<Tensor<1,dim>, unsigned int> >
+ // now compute the reverse mapping: for each of the cells that
+ // contributed to the current set of vector dofs, add up the normal
+ // vectors. the values of the map are pairs of normal vectors and
+ // number of cells that have contributed
+ typedef std::map<typename DH<dim,spacedim>::active_cell_iterator,
+ std::pair<Tensor<1,dim>, unsigned int> >
CellToNormalsMap;
- CellToNormalsMap cell_to_normals_map;
- for (typename DoFToNormalsMap::const_iterator
- q = same_dof_range[0];
- q != same_dof_range[1]; ++q)
- if (cell_to_normals_map.find (q->second.second)
+ CellToNormalsMap cell_to_normals_map;
+ for (typename DoFToNormalsMap::const_iterator
+ q = same_dof_range[0];
+ q != same_dof_range[1]; ++q)
+ if (cell_to_normals_map.find (q->second.second)
== cell_to_normals_map.end())
cell_to_normals_map[q->second.second]
= std::make_pair (q->second.first, 1U);
- else
- {
- const Tensor<1,dim> old_normal
+ else
+ {
+ const Tensor<1,dim> old_normal
= cell_to_normals_map[q->second.second].first;
- const unsigned int old_count
+ const unsigned int old_count
= cell_to_normals_map[q->second.second].second;
- Assert (old_count > 0, ExcInternalError());
+ Assert (old_count > 0, ExcInternalError());
- // in the same entry, store again the now averaged normal vector
- // and the new count
- cell_to_normals_map[q->second.second]
- = std::make_pair ((old_normal * old_count + q->second.first) / (old_count + 1),
- old_count + 1);
- }
- Assert (cell_to_normals_map.size() >= 1, ExcInternalError());
+ // in the same entry, store again the now averaged normal vector
+ // and the new count
+ cell_to_normals_map[q->second.second]
+ = std::make_pair ((old_normal * old_count + q->second.first) / (old_count + 1),
+ old_count + 1);
+ }
+ Assert (cell_to_normals_map.size() >= 1, ExcInternalError());
#ifdef DEBUG_NO_NORMAL_FLUX
- std::cout << " cell_to_normals_map:" << std::endl;
- for (typename CellToNormalsMap::const_iterator
- x = cell_to_normals_map.begin();
- x != cell_to_normals_map.end(); ++x)
- std::cout << " " << x->first << " -> ("
- << x->second.first << ',' << x->second.second << ')'
- << std::endl;
+ std::cout << " cell_to_normals_map:" << std::endl;
+ for (typename CellToNormalsMap::const_iterator
+ x = cell_to_normals_map.begin();
+ x != cell_to_normals_map.end(); ++x)
+ std::cout << " " << x->first << " -> ("
+ << x->second.first << ',' << x->second.second << ')'
+ << std::endl;
#endif
- // count the maximum number of contributions from each cell
- unsigned int max_n_contributions_per_cell = 1;
- for (typename CellToNormalsMap::const_iterator
- x = cell_to_normals_map.begin();
- x != cell_to_normals_map.end(); ++x)
+ // count the maximum number of contributions from each cell
+ unsigned int max_n_contributions_per_cell = 1;
+ for (typename CellToNormalsMap::const_iterator
+ x = cell_to_normals_map.begin();
+ x != cell_to_normals_map.end(); ++x)
max_n_contributions_per_cell
= std::max (max_n_contributions_per_cell,
x->second.second);
- // verify that each cell can have only contributed at most dim times,
- // since that is the maximum number of faces that come together at a
- // single place
- Assert (max_n_contributions_per_cell <= dim, ExcInternalError());
-
- switch (max_n_contributions_per_cell)
- {
- // first deal with the case that a number of cells all have
- // registered that they have a normal vector defined at the
- // location of a given vector dof, and that each of them have
- // encountered this vector dof exactly once while looping over all
- // their faces. as stated in the documentation, this is the case
- // where we want to simply average over all normal vectors
- //
- // the typical case is in 2d where multiple cells meet at one
- // vertex sitting on the boundary. same in 3d for a vertex that
- // is associated with only one of the boundary indicators passed
- // to this function
- case 1:
- {
-
- // compute the average normal vector from all the ones that have
- // the same set of dofs. we could add them up and divide them by
- // the number of additions, or simply normalize them right away
- // since we want them to have unit length anyway
- Tensor<1,dim> normal;
- for (typename CellToNormalsMap::const_iterator
- x = cell_to_normals_map.begin();
- x != cell_to_normals_map.end(); ++x)
- normal += x->second.first;
- normal /= normal.norm();
-
- // normalize again
- for (unsigned int d=0; d<dim; ++d)
- if (std::fabs(normal[d]) < 1e-13)
- normal[d] = 0;
- normal /= normal.norm();
+ // verify that each cell can have only contributed at most dim times,
+ // since that is the maximum number of faces that come together at a
+ // single place
+ Assert (max_n_contributions_per_cell <= dim, ExcInternalError());
- // then construct constraints from this:
- const internal::VectorDoFTuple<dim> &
- dof_indices = same_dof_range[0]->first;
- internal::add_constraint (dof_indices, normal,
- constraints);
-
- break;
- }
+ switch (max_n_contributions_per_cell)
+ {
+ // first deal with the case that a number of cells all have
+ // registered that they have a normal vector defined at the
+ // location of a given vector dof, and that each of them have
+ // encountered this vector dof exactly once while looping over all
+ // their faces. as stated in the documentation, this is the case
+ // where we want to simply average over all normal vectors
+ //
+ // the typical case is in 2d where multiple cells meet at one
+ // vertex sitting on the boundary. same in 3d for a vertex that
+ // is associated with only one of the boundary indicators passed
+ // to this function
+ case 1:
+ {
+ // compute the average normal vector from all the ones that have
+ // the same set of dofs. we could add them up and divide them by
+ // the number of additions, or simply normalize them right away
+ // since we want them to have unit length anyway
+ Tensor<1,dim> normal;
+ for (typename CellToNormalsMap::const_iterator
+ x = cell_to_normals_map.begin();
+ x != cell_to_normals_map.end(); ++x)
+ normal += x->second.first;
+ normal /= normal.norm();
+
+ // normalize again
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::fabs(normal[d]) < 1e-13)
+ normal[d] = 0;
+ normal /= normal.norm();
+
+ // then construct constraints from this:
+ const internal::VectorDoFTuple<dim> &
+ dof_indices = same_dof_range[0]->first;
+ double normal_value = 0.;
+ const Vector<double> b_values = dof_vector_to_b_values[dof_indices];
+ for (unsigned int i=0; i<dim; ++i)
+ normal_value += b_values[i]*normal[i];
+ internal::add_constraint (dof_indices, normal,
+ constraints, normal_value);
+
+ break;
+ }
+ // this is the slightly more complicated case that a single cell has
+ // contributed with exactly DIM normal vectors to the same set of
+ // vector dofs. this is what happens in a corner in 2d and 3d (but
+ // not on an edge in 3d, where we have only 2, i.e. <DIM,
+ // contributions. Here we do not want to average the normal
+ // vectors. Since we have DIM contributions, let's assume (and
+ // verify) that they are in fact all linearly independent; in that
+ // case, all vector components are constrained and we need to set all
+ // of them to the corresponding boundary values
+ case dim:
+ {
+ // assert that indeed only a single cell has contributed
+ Assert (cell_to_normals_map.size() == 1,
+ ExcInternalError());
- // this is the slightly more complicated case that a single cell has
- // contributed with exactly DIM normal vectors to the same set of
- // vector dofs. this is what happens in a corner in 2d and 3d (but
- // not on an edge in 3d, where we have only 2, i.e. <DIM,
- // contributions. Here we do not want to average the normal
- // vectors. Since we have DIM contributions, let's assume (and
- // verify) that they are in fact all linearly independent; in that
- // case, all vector components are constrained and we need to set
- // them to zero
- case dim:
+ // check linear independence by computing the determinant of the
+ // matrix created from all the normal vectors. if they are
+ // linearly independent, then the determinant is nonzero. if they
+ // are orthogonal, then the matrix is in fact equal to 1 (since
+ // they are all unit vectors); make sure the determinant is larger
+ // than 1e-3 to avoid cases where cells are degenerate
{
- // assert that indeed only a single cell has contributed
- Assert (cell_to_normals_map.size() == 1,
- ExcInternalError());
+ Tensor<2,dim> t;
+
+ typename DoFToNormalsMap::const_iterator x = same_dof_range[0];
+ for (unsigned int i=0; i<dim; ++i, ++x)
+ for (unsigned int j=0; j<dim; ++j)
+ t[i][j] = x->second.first[j];
+
+ Assert (std::fabs(determinant (t)) > 1e-3,
+ ExcMessage("Found a set of normal vectors that are nearly collinear."));
+ }
- // check linear independence by computing the determinant of the
- // matrix created from all the normal vectors. if they are
- // linearly independent, then the determinant is nonzero. if they
- // are orthogonal, then the matrix is in fact equal to 1 (since
- // they are all unit vectors); make sure the determinant is larger
- // than 1e-3 to avoid cases where cells are degenerate
+ // so all components of this vector dof are constrained. enter
+ // this into the constraint matrix
+ //
+ // ignore dofs already constrained
+ const internal::VectorDoFTuple<dim> &
+ dof_indices = same_dof_range[0]->first;
+ const Vector<double> b_values = dof_vector_to_b_values[dof_indices];
+ for (unsigned int i=0; i<dim; ++i)
+ if (!constraints.is_constrained(same_dof_range[0]->first.dof_indices[i])
+ &&
+ constraints.can_store_line(same_dof_range[0]->first.dof_indices[i]))
{
- Tensor<2,dim> t;
-
- typename DoFToNormalsMap::const_iterator x = same_dof_range[0];
- for (unsigned int i=0; i<dim; ++i, ++x)
- for (unsigned int j=0; j<dim; ++j)
- t[i][j] = x->second.first[j];
-
- Assert (std::fabs(determinant (t)) > 1e-3,
- ExcMessage("Found a set of normal vectors that are nearly collinear."));
+ const types::global_dof_index line
+ = dof_indices.dof_indices[i];
+ constraints.add_line (line);
+ if (std::fabs(b_values[i])
+ > std::numeric_limits<double>::epsilon())
+ constraints.set_inhomogeneity(line, b_values[i]);
+ // no add_entries here
}
- // so all components of this vector dof are constrained. enter
- // this into the constraint matrix
- //
- // ignore dofs already constrained
- for (unsigned int i=0; i<dim; ++i)
- if (!constraints.is_constrained (same_dof_range[0]
- ->first.dof_indices[i])
- &&
- constraints.can_store_line(
- same_dof_range[0]->first.dof_indices[i]))
- {
- constraints.add_line (same_dof_range[0]->first.dof_indices[i]);
- // no add_entries here
- }
-
break;
}
-
- // this is the case of an edge contribution in 3d, i.e. the vector
- // is constrained in two directions but not the third.
- default:
- {
- Assert (dim >= 3, ExcNotImplemented());
- Assert (max_n_contributions_per_cell == 2, ExcInternalError());
-
- // as described in the documentation, let us first collect what
- // each of the cells contributed at the current point. we use a
- // std::list instead of a std::set (which would be more natural)
- // because std::set requires that the stored elements are
- // comparable with operator<
- typedef
- std::map<typename DH<dim,spacedim>::active_cell_iterator, std::list<Tensor<1,dim> > >
+ // this is the case of an edge contribution in 3d, i.e. the vector
+ // is constrained in two directions but not the third.
+ default:
+ {
+ Assert (dim >= 3, ExcNotImplemented());
+ Assert (max_n_contributions_per_cell == 2, ExcInternalError());
+
+ // as described in the documentation, let us first collect what
+ // each of the cells contributed at the current point. we use a
+ // std::list instead of a std::set (which would be more natural)
+ // because std::set requires that the stored elements are
+ // comparable with operator<
+ typedef std::map<typename DH<dim,spacedim>::active_cell_iterator,
+ std::list<Tensor<1,dim> > >
CellContributions;
- CellContributions cell_contributions;
-
- for (typename DoFToNormalsMap::const_iterator
- q = same_dof_range[0];
- q != same_dof_range[1]; ++q)
- cell_contributions[q->second.second].push_back (q->second.first);
- Assert (cell_contributions.size() >= 1, ExcInternalError());
-
- // now for each cell that has contributed determine the number of
- // normal vectors it has contributed. we currently only implement
- // if this is dim-1 for all cells (if a single cell has
- // contributed dim, or if all adjacent cells have contributed 1
- // normal vector, this is already handled above).
- //
- // we only implement the case that all cells contribute
- // dim-1 because we assume that we are following an edge
- // of the domain (think: we are looking at a vertex
- // located on one of the edges of a refined cube where the
- // boundary indicators of the two adjacent faces of the
- // cube are both listed in the set of boundary indicators
- // passed to this function). in that case, all cells along
- // that edge of the domain are assumed to have contributed
- // dim-1 normal vectors. however, there are cases where
- // this assumption is not justified (see the lengthy
- // explanation in test no_flux_12.cc) and in those cases
- // we simply ignore the cell that contributes only
- // once. this is also discussed at length in the
- // documentation of this function.
- //
- // for each contributing cell compute the tangential vector that
- // remains unconstrained
- std::list<Tensor<1,dim> > tangential_vectors;
- for (typename CellContributions::const_iterator
- contribution = cell_contributions.begin();
- contribution != cell_contributions.end();
- ++contribution)
- {
+ CellContributions cell_contributions;
+
+ for (typename DoFToNormalsMap::const_iterator
+ q = same_dof_range[0];
+ q != same_dof_range[1]; ++q)
+ cell_contributions[q->second.second].push_back (q->second.first);
+ Assert (cell_contributions.size() >= 1, ExcInternalError());
+
+ // now for each cell that has contributed determine the number of
+ // normal vectors it has contributed. we currently only implement
+ // if this is dim-1 for all cells (if a single cell has
+ // contributed dim, or if all adjacent cells have contributed 1
+ // normal vector, this is already handled above).
+ //
+ // we only implement the case that all cells contribute
+ // dim-1 because we assume that we are following an edge
+ // of the domain (think: we are looking at a vertex
+ // located on one of the edges of a refined cube where the
+ // boundary indicators of the two adjacent faces of the
+ // cube are both listed in the set of boundary indicators
+ // passed to this function). in that case, all cells along
+ // that edge of the domain are assumed to have contributed
+ // dim-1 normal vectors. however, there are cases where
+ // this assumption is not justified (see the lengthy
+ // explanation in test no_flux_12.cc) and in those cases
+ // we simply ignore the cell that contributes only
+ // once. this is also discussed at length in the
+ // documentation of this function.
+ //
+ // for each contributing cell compute the tangential vector that
+ // remains unconstrained
+ std::list<Tensor<1,dim> > tangential_vectors;
+ for (typename CellContributions::const_iterator
+ contribution = cell_contributions.begin();
+ contribution != cell_contributions.end();
+ ++contribution)
+ {
#ifdef DEBUG_NO_NORMAL_FLUX
- std::cout << " Treating edge case with dim-1 contributions." << std::endl
- << " Looking at cell " << contribution->first
- << " which has contributed these normal vectors:"
- << std::endl;
- for (typename std::list<Tensor<1,dim> >::const_iterator
- t = contribution->second.begin();
- t != contribution->second.end();
- ++t)
- std::cout << " " << *t << std::endl;
+ std::cout << " Treating edge case with dim-1 contributions." << std::endl
+ << " Looking at cell " << contribution->first
+ << " which has contributed these normal vectors:"
+ << std::endl;
+ for (typename std::list<Tensor<1,dim> >::const_iterator
+ t = contribution->second.begin();
+ t != contribution->second.end();
+ ++t)
+ std::cout << " " << *t << std::endl;
#endif
- // as mentioned above, simply ignore cells that only
- // contribute once
- if (contribution->second.size() < dim-1)
- continue;
-
- Tensor<1,dim> normals[dim-1];
- {
- unsigned int index=0;
- for (typename std::list<Tensor<1,dim> >::const_iterator
- t = contribution->second.begin();
- t != contribution->second.end();
- ++t, ++index)
- normals[index] = *t;
- Assert (index == dim-1, ExcInternalError());
- }
-
- // calculate the tangent as the outer product of the normal
- // vectors. since these vectors do not need to be orthogonal
- // (think, for example, the case of the deal.II/no_flux_07
- // test: a sheared cube in 3d, with Q2 elements, where we have
- // constraints from the two normal vectors of two faces of the
- // sheared cube that are not perpendicular to each other), we
- // have to normalize the outer product
- Tensor<1,dim> tangent;
- switch (dim)
- {
- case 3:
- // take cross product between normals[0] and
- // normals[1]. write it in the current form (with [dim-2])
- // to make sure that compilers don't warn about
- // out-of-bounds accesses -- the warnings are bogus since
- // we get here only for dim==3, but at least one isn't
- // quite smart enough to notice this and warns when
- // compiling the function in 2d
- cross_product (tangent, normals[0], normals[dim-2]);
- break;
- default:
- Assert (false, ExcNotImplemented());
- }
-
- Assert (std::fabs (tangent.norm()) > 1e-12,
- ExcMessage("Two normal vectors from adjacent faces are almost "
- "parallel."));
- tangent /= tangent.norm();
-
- tangential_vectors.push_back (tangent);
- }
+ // as mentioned above, simply ignore cells that only
+ // contribute once
+ if (contribution->second.size() < dim-1)
+ continue;
+
+ Tensor<1,dim> normals[dim-1];
+ {
+ unsigned int index=0;
+ for (typename std::list<Tensor<1,dim> >::const_iterator
+ t = contribution->second.begin();
+ t != contribution->second.end();
+ ++t, ++index)
+ normals[index] = *t;
+ Assert (index == dim-1, ExcInternalError());
+ }
- // go through the list of tangents and make sure that they all
- // roughly point in the same direction as the first one (i.e. have
- // an angle less than 90 degrees); if they don't then flip their
- // sign
+ // calculate the tangent as the outer product of the normal
+ // vectors. since these vectors do not need to be orthogonal
+ // (think, for example, the case of the deal.II/no_flux_07
+ // test: a sheared cube in 3d, with Q2 elements, where we have
+ // constraints from the two normal vectors of two faces of the
+ // sheared cube that are not perpendicular to each other), we
+ // have to normalize the outer product
+ Tensor<1,dim> tangent;
+ switch (dim)
{
- const Tensor<1,dim> first_tangent = tangential_vectors.front();
- typename std::list<Tensor<1,dim> >::iterator
- t = tangential_vectors.begin();
- ++t;
- for (; t != tangential_vectors.end(); ++t)
- if (*t * first_tangent < 0)
- *t *= -1;
+ case 3:
+ // take cross product between normals[0] and
+ // normals[1]. write it in the current form (with [dim-2])
+ // to make sure that compilers don't warn about
+ // out-of-bounds accesses -- the warnings are bogus since
+ // we get here only for dim==3, but at least one isn't
+ // quite smart enough to notice this and warns when
+ // compiling the function in 2d
+ cross_product (tangent, normals[0], normals[dim-2]);
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
}
- // now compute the average tangent and normalize it
- Tensor<1,dim> average_tangent;
- for (typename std::list<Tensor<1,dim> >::const_iterator
- t = tangential_vectors.begin();
- t != tangential_vectors.end();
- ++t)
- average_tangent += *t;
- average_tangent /= average_tangent.norm();
+ Assert (std::fabs (tangent.norm()) > 1e-12,
+ ExcMessage("Two normal vectors from adjacent faces are almost "
+ "parallel."));
+ tangent /= tangent.norm();
- // now all that is left is that we add the constraints that the
- // vector is parallel to the tangent
- const internal::VectorDoFTuple<dim> &
- dof_indices = same_dof_range[0]->first;
- internal::add_tangentiality_constraints (dof_indices,
- average_tangent,
- constraints);
+ tangential_vectors.push_back (tangent);
}
+
+ // go through the list of tangents and make sure that they all
+ // roughly point in the same direction as the first one (i.e. have
+ // an angle less than 90 degrees); if they don't then flip their
+ // sign
+ {
+ const Tensor<1,dim> first_tangent = tangential_vectors.front();
+ typename std::list<Tensor<1,dim> >::iterator
+ t = tangential_vectors.begin();
+ ++t;
+ for (; t != tangential_vectors.end(); ++t)
+ if (*t * first_tangent < 0)
+ *t *= -1;
}
+
+ // now compute the average tangent and normalize it
+ Tensor<1,dim> average_tangent;
+ for (typename std::list<Tensor<1,dim> >::const_iterator
+ t = tangential_vectors.begin();
+ t != tangential_vectors.end();
+ ++t)
+ average_tangent += *t;
+ average_tangent /= average_tangent.norm();
+
+ // now all that is left is that we add the constraints that the
+ // vector is parallel to the tangent
+ const internal::VectorDoFTuple<dim> &
+ dof_indices = same_dof_range[0]->first;
+ const Vector<double> b_values = dof_vector_to_b_values[dof_indices];
+ internal::add_tangentiality_constraints (dof_indices,
+ average_tangent,
+ constraints,
+ b_values);
+ }
}
+ }
}
const std::set<types::boundary_id> &boundary_ids,
ConstraintMatrix &constraints,
const Mapping<dim, spacedim> &mapping)
+ {
+ ZeroFunction<dim>zero_function(dim);
+ typename FunctionMap<spacedim>::type function_map;
+ std::set<types::boundary_id>::const_iterator it
+ = boundary_ids.begin();
+ for (;it != boundary_ids.end(); ++it)
+ function_map[*it] = &zero_function;
+ compute_nonzero_tangential_flux_constraints(dof_handler,
+ first_vector_component,
+ boundary_ids,
+ function_map,
+ constraints,
+ mapping);
+ }
+
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+ compute_nonzero_tangential_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ typename FunctionMap<spacedim>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping)
{
ConstraintMatrix no_normal_flux_constraints(constraints.get_local_lines());
- compute_no_normal_flux_constraints (dof_handler,
- first_vector_component,
- boundary_ids,
- no_normal_flux_constraints,
- mapping);
+ compute_nonzero_normal_flux_constraints (dof_handler,
+ first_vector_component,
+ boundary_ids,
+ function_map,
+ no_normal_flux_constraints,
+ mapping);
+
+ hp::FECollection<dim,spacedim> fe_collection (dof_handler.get_fe());
+ hp::MappingCollection<dim,spacedim> mapping_collection;
+ for (unsigned int i=0; i<fe_collection.size(); ++i)
+ mapping_collection.push_back (mapping);
+
+ // now also create a quadrature collection for the faces of a cell. fill
+ // it with a quadrature formula with the support points on faces for each
+ // FE
+ hp::QCollection<dim-1> face_quadrature_collection;
+ for (unsigned int i=0; i<fe_collection.size(); ++i)
+ {
+ const std::vector<Point<dim-1> > &
+ unit_support_points = fe_collection[i].get_unit_face_support_points();
+
+ Assert (unit_support_points.size() == fe_collection[i].dofs_per_face,
+ ExcInternalError());
+
+ face_quadrature_collection.push_back (Quadrature<dim-1> (unit_support_points));
+ }
+
+ // now create the object with which we will generate the normal vectors
+ hp::FEFaceValues<dim,spacedim> x_fe_face_values (mapping_collection,
+ fe_collection,
+ face_quadrature_collection,
+ update_q_points |
+ update_normal_vectors);
// Extract a list that collects all vector components that belong to the
// same node (scalar basis function). When creating that list, we use an
std::set<std_cxx1x::array<types::global_dof_index,dim>, PointComparator<dim> > vector_dofs;
std::vector<types::global_dof_index> face_dofs;
+ std::map<std_cxx1x::array<types::global_dof_index,dim>, Vector<double> >
+ dof_vector_to_b_values;
+
+ std::set<types::boundary_id>::iterator b_id;
std::vector<std_cxx1x::array<types::global_dof_index,dim> > cell_vector_dofs;
for (typename DH<dim,spacedim>::active_cell_iterator cell =
dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
if (!cell->is_artificial())
for (unsigned int face_no=0; face_no < GeometryInfo<dim>::faces_per_cell;
++face_no)
- if (boundary_ids.find(cell->face(face_no)->boundary_indicator())
+ if ((b_id=boundary_ids.find(cell->face(face_no)->boundary_indicator()))
!= boundary_ids.end())
{
const FiniteElement<dim> &fe = cell->get_fe();
face_dofs.resize (fe.dofs_per_face);
face->get_dof_indices (face_dofs, cell->active_fe_index());
+ x_fe_face_values.reinit (cell, face_no);
+ const FEFaceValues<dim> &fe_values = x_fe_face_values.get_present_fe_values();
+
+ std::map<types::global_dof_index, double> dof_to_b_value;
+
unsigned int n_scalar_indices = 0;
cell_vector_dofs.resize(fe.dofs_per_face);
for (unsigned int i=0; i<fe.dofs_per_face; ++i)
+ {
if (fe.face_system_to_component_index(i).first >= first_vector_component &&
fe.face_system_to_component_index(i).first < first_vector_component + dim)
- {
- n_scalar_indices =
- std::max(n_scalar_indices,
- fe.face_system_to_component_index(i).second+1);
- cell_vector_dofs[fe.face_system_to_component_index(i).second]
- [fe.face_system_to_component_index(i).first-first_vector_component]
- = face_dofs[i];
- }
+ {
+ const unsigned int component
+ = fe.face_system_to_component_index(i).first
+ -first_vector_component;
+ n_scalar_indices =
+ std::max(n_scalar_indices,
+ fe.face_system_to_component_index(i).second+1);
+ cell_vector_dofs[fe.face_system_to_component_index(i).second]
+ [component]
+ = face_dofs[i];
+
+ const Point<dim> point
+ = fe_values.quadrature_point(i);
+ const double b_value
+ = function_map[*b_id]->value(point, component);
+ dof_to_b_value.insert
+ (std::make_pair(face_dofs[i], b_value));
+ }
+ }
// now we identified the vector indices on the cell, so next
// insert them into the set (it would be expensive to directly
// insert incomplete points into the set)
for (unsigned int i=0; i<n_scalar_indices; ++i)
+ {
vector_dofs.insert(cell_vector_dofs[i]);
+ Vector<double> b_values(dim);
+ for (unsigned int j=0; j<dim; ++j)
+ b_values[j]=dof_to_b_value[cell_vector_dofs[i][j]];
+ dof_vector_to_b_values.insert
+ (std::make_pair(cell_vector_dofs[i], b_values));
+ }
+
}
// iterate over the list of all vector components we found and see if we
// if more than one no-flux constraint is present, we need to
// constrain all vector degrees of freedom (we are in a corner
// where several faces meet and to get a continuous FE solution we
- // need to set all conditions to zero).
+ // need to set all conditions corresponding to the boundary function.).
if (n_constraints > 1)
{
+ const Vector<double> b_value = dof_vector_to_b_values[*it];
for (unsigned int d=0; d<dim; ++d)
+ {
constraints.add_line((*it)[d]);
+ constraints.set_inhomogeneity((*it)[d], b_value(d));
+ }
continue;
}
Assert (index != -1, ExcInternalError());
normal[index] = (*constrained)[c].second;
}
+ Vector<double> boundary_value = dof_vector_to_b_values[*it];
for (unsigned int d=0; d<dim; ++d)
{
if (is_constrained[d])
if (std::abs(normal[d]) > 1e-13)
constraints.add_entry(new_index, (*it)[constrained_index],
-normal[d]);
+ constraints.set_inhomogeneity(new_index, boundary_value[d]);
}
}
}
#
SOVERSION "${DEAL_II_PACKAGE_VERSION}"
LINK_FLAGS "${DEAL_II_LINKER_FLAGS} ${DEAL_II_LINKER_FLAGS_${build}}"
+ LINKER_LANGUAGE "CXX"
COMPILE_DEFINITIONS "${DEAL_II_DEFINITIONS};${DEAL_II_DEFINITIONS_${build}}"
- COMPILE_FLAGS "${DEAL_II_CXX_FLAGS_${build}}"
+ COMPILE_FLAGS "${DEAL_II_CXX_FLAGS} ${DEAL_II_CXX_FLAGS_${build}}"
INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${DEAL_II_LIBRARY_RELDIR}"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DEAL_II_LIBRARY_RELDIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${DEAL_II_LIBRARY_RELDIR}"
namespace Algorithms
{
+ OperatorBase::~OperatorBase()
+ {}
+
+ void OperatorBase::notify(const Event &e)
+ {
+ notifications += e;
+ }
+
+ void
+ OperatorBase::clear_events ()
+ {
+ notifications.clear();
+ }
+
+
#include "operator.inst"
}
memory_consumption.cc
mpi.cc
multithread_info.cc
+ named_selection.cc
parallel.cc
parameter_handler.cc
parsed_function.cc
tensor_product_polynomials_const.cc
thread_management.cc
timer.cc
+ time_stepping.cc
utilities.cc
)
SET(_inst
data_out_base.inst.in
+ time_stepping.inst.in
)
FILE(GLOB _header
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
:
n_data_sets,
patch->data.n_rows()));
- Assert (patch->data.n_cols() == Utilities::fixed_power<dim>(n_subdivisions+1),
+ Assert ((n_data_sets == 0)
+ ||
+ (patch->data.n_cols() == Utilities::fixed_power<dim>(n_subdivisions+1)),
ExcInvalidDatasetSize (patch->data.n_cols(), n_subdivisions+1));
for (unsigned int i=0; i<patch->data.n_cols(); ++i, ++next_value)
Point<3> v_min, v_max, v_inter;
// Use the Bubblesort algorithm to sort the points with respect to the third coordinate
- int i, j;
-
- for (i = 0; i < 2; ++i)
+ for (int i = 0; i < 2; ++i)
{
- for (j = 0; j < 2-i; ++j)
+ for (int j = 0; j < 2-i; ++j)
{
if (points[j][2] > points[j + 1][2])
{
}
// max. and min. heigth of solution
- typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
- Assert(patch!=patches.end(), ExcInternalError());
- double hmin=patch->data(0,0);
- double hmax=patch->data(0,0);
+ Assert(patches.size()>0, ExcInternalError());
+ double hmin=patches[0].data(0,0);
+ double hmax=patches[0].data(0,0);
- for (; patch != patches.end(); ++patch)
+ for (typename std::vector<Patch<dim,spacedim> >::const_iterator patch=patches.begin();
+ patch != patches.end(); ++patch)
{
const unsigned int n_subdivisions = patch->n_subdivisions;
herr_t status;
unsigned int local_node_cell_count[2], global_node_cell_count[2], global_node_cell_offsets[2];
hsize_t count[2], offset[2], node_ds_dim[2], cell_ds_dim[2];
- bool empty_proc = false;
std::vector<double> node_data_vec;
std::vector<unsigned int> cell_data_vec;
- if (data_filter.n_nodes() == 0) empty_proc = true;
-
// If HDF5 is not parallel and we're using multiple processes, abort
#ifndef H5_HAVE_PARALLEL
-#ifdef DEAL_II_WITH_MPI
+# ifdef DEAL_II_WITH_MPI
int world_size;
MPI_Comm_size(comm, &world_size);
AssertThrow (world_size <= 1,
ExcMessage ("Serial HDF5 output on multiple processes is not yet supported."));
-#endif
+# endif
#endif
local_node_cell_count[0] = data_filter.n_nodes();
// all vector data, then handle the
// scalar data sets that have been
// left over
- unsigned int i, n, q, r, pt_data_vector_dim;
+ unsigned int i, pt_data_vector_dim;
std::string vector_name;
for (i=0; i<data_filter.n_data_sets(); ++i)
{
#include <deal.II/base/utilities.h>
#include <deal.II/lac/vector.h>
-#ifdef DEAL_II_WITH_FUNCTIONPARSER
-#include <fparser.hh>
-namespace fparser
-{
- class FunctionParser: public ::FunctionParser
- {};
-}
+
+#ifdef DEAL_II_WITH_MUPARSER
+#include <muParser.h>
#else
namespace fparser
class FunctionParser
{};
}
-
#endif
DEAL_II_NAMESPACE_OPEN
FunctionParser<dim>::FunctionParser(const unsigned int n_components,
const double initial_time)
:
- Function<dim>(n_components, initial_time),
- fp (0)
-{
- fp = new fparser::FunctionParser[n_components];
-}
+ Function<dim>(n_components, initial_time)
+{}
template <int dim>
FunctionParser<dim>::~FunctionParser()
-{
- delete[] fp;
-}
+{}
-
-#ifdef DEAL_II_WITH_FUNCTIONPARSER
+#ifdef DEAL_II_WITH_MUPARSER
template <int dim>
void FunctionParser<dim>::initialize (const std::string &variables,
const std::vector<std::string> &expressions,
use_degrees);
}
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string &vars,
+ const std::vector<std::string> &expressions,
+ const std::map<std::string, double> &constants,
+ const bool time_dependent)
+ {
+ initialize(vars, expressions, constants, time_dependent, false);
+ }
+
+namespace internal
+{
+ // convert double into int
+ int mu_round(double val)
+ {
+ return static_cast<int>(val + ((val>=0.0) ? 0.5 : -0.5) );
+ }
+
+ double mu_if(double condition, double thenvalue, double elsevalue)
+ {
+ if (mu_round(condition))
+ return thenvalue;
+ else
+ return elsevalue;
+ }
+
+ double mu_or(double left, double right)
+ {
+ return (mu_round(left)) || (mu_round(right));
+ }
+
+ double mu_and(double left, double right)
+ {
+ return (mu_round(left)) && (mu_round(right));
+ }
+
+ double mu_int(double value)
+ {
+ return static_cast<double>(mu_round(value));
+ }
+ double mu_ceil(double value)
+ {
+ return ceil(value);
+ }
+ double mu_floor(double value)
+ {
+ return floor(value);
+ }
+ double mu_cot(double value)
+ {
+ return 1.0/tan(value);
+ }
+ double mu_csc(double value)
+ {
+ return 1.0/sin(value);
+ }
+ double mu_sec(double value)
+ {
+ return 1.0/cos(value);
+ }
+ double mu_log(double value)
+ {
+ return log(value);
+ }
+
+
+
+}
+template <int dim>
+void FunctionParser<dim>:: init_muparser() const
+{
+ if (fp.get().size()>0)
+ return;
+
+ fp.get().resize(this->n_components);
+ vars.get().resize(var_names.size());
+ for (unsigned int i=0; i<this->n_components; ++i)
+ {
+ std::map< std::string, double >::const_iterator
+ constant = constants.begin(),
+ endc = constants.end();
+
+ for (; constant != endc; ++constant)
+ {
+ fp.get()[i].DefineConst(constant->first.c_str(), constant->second);
+ }
+
+ for (unsigned int iv=0;iv<var_names.size();++iv)
+ fp.get()[i].DefineVar(var_names[iv].c_str(), &vars.get()[iv]);
+
+ // define some compatibility functions:
+ fp.get()[i].DefineFun("if",internal::mu_if, true);
+ fp.get()[i].DefineOprt("|", internal::mu_or, 1);
+ fp.get()[i].DefineOprt("&", internal::mu_and, 2);
+ fp.get()[i].DefineFun("int", internal::mu_int, true);
+ fp.get()[i].DefineFun("ceil", internal::mu_ceil, true);
+ fp.get()[i].DefineFun("cot", internal::mu_cot, true);
+ fp.get()[i].DefineFun("csc", internal::mu_csc, true);
+ fp.get()[i].DefineFun("floor", internal::mu_floor, true);
+ fp.get()[i].DefineFun("sec", internal::mu_sec, true);
+ fp.get()[i].DefineFun("log", internal::mu_log, true);
+
+ try
+ {
+ fp.get()[i].SetExpr(expressions[i]);
+ }
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: " << e.GetMsg() << "\n";
+ std::cerr << "Formula: " << e.GetExpr() << "\n";
+ std::cerr << "Token: " << e.GetToken() << "\n";
+ std::cerr << "Position: " << e.GetPos() << "\n";
+ std::cerr << "Errc: " << e.GetCode() << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg().c_str()));
+ }
+ }
+}
template <int dim>
void FunctionParser<dim>::initialize (const std::string &variables,
const bool time_dependent,
const bool use_degrees)
{
+
+ this->fp.clear(); // this will reset all thread-local objects
+
+ this->constants = constants;
+ this->var_names = Utilities::split_string_list(variables, ',');
+ this->expressions = expressions;
+ AssertThrow(((time_dependent)?dim+1:dim) == var_names.size(),
+ ExcMessage("wrong number of variables"));
+ AssertThrow(!use_degrees, ExcNotImplemented());
+
// We check that the number of
// components of this function
// matches the number of components
ExcInvalidExpressionSize(this->n_components,
expressions.size()) );
+ // we no longer support units:
+ AssertThrow(units.size()==0, ExcNotImplemented());
-
- for (unsigned int i=0; i<this->n_components; ++i)
- {
-
- // Add the various units to
- // the parser.
- std::map< std::string, double >::const_iterator
- unit = units.begin(),
- endu = units.end();
- for (; unit != endu; ++unit)
- {
- const bool success = fp[i].AddUnit(unit->first, unit->second);
- AssertThrow (success,
- ExcMessage("Invalid Unit Name [error adding a unit]"));
- }
-
-
-
- // Add the various constants to
- // the parser.
- std::map< std::string, double >::const_iterator
- constant = constants.begin(),
- endc = constants.end();
- for (; constant != endc; ++constant)
- {
- const bool success = fp[i].AddConstant(constant->first, constant->second);
- AssertThrow (success, ExcMessage("Invalid Constant Name"));
- }
-
- const int ret_value = fp[i].Parse(expressions[i],
- variables,
- use_degrees);
- AssertThrow (ret_value == -1,
- ExcParseError(ret_value, fp[i].ErrorMsg()));
-
- // The fact that the parser did
- // not throw an error does not
- // mean that everything went
- // ok... we can still have
- // problems with the number of
- // variables...
- }
// Now we define how many variables
// we expect to read in. We
// distinguish between two cases:
else
n_vars = dim;
- /*
- // Let's check if the number of
- // variables is correct...
- AssertThrow (n_vars == fp[0].NVars(),
- ! ~~~~~~~
- ! not available anymore in fparser-4.5, maier 2012
- ExcDimensionMismatch(n_vars,fp[0].NVars()));
- */
-
+ init_muparser();
+
// Now set the initialization bit.
initialized = true;
}
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string &vars,
+ const std::string &expression,
+ const std::map<std::string, double> &constants,
+ const bool time_dependent)
+{
+ initialize(vars, expression, constants, time_dependent, false);
+}
template <int dim>
Assert (component < this->n_components,
ExcIndexRange(component, 0, this->n_components));
- // Statically allocate dim+1
- // double variables.
- double vars[dim+1];
+ // initialize if not done so on this thread yet:
+ init_muparser();
for (unsigned int i=0; i<dim; ++i)
- vars[i] = p(i);
-
- // We need the time variable only
- // if the number of variables is
- // different from the dimension. In
- // this case it can only be dim+1,
- // otherwise an exception would
- // have already been thrown
+ vars.get()[i] = p(i);
if (dim != n_vars)
- vars[dim] = this->get_time();
-
- double my_value = fp[component].Eval((double *)vars);
+ vars.get()[dim] = this->get_time();
- AssertThrow (fp[component].EvalError() == 0,
- ExcMessage(fp[component].ErrorMsg()));
- return my_value;
+ try
+ {
+ return fp.get()[component].Eval();
+ }
+ catch (mu::ParserError &e)
+ {
+ std::cerr << "Message: " << e.GetMsg() << "\n";
+ std::cerr << "Formula: " << e.GetExpr() << "\n";
+ std::cerr << "Token: " << e.GetToken() << "\n";
+ std::cerr << "Position: " << e.GetPos() << "\n";
+ std::cerr << "Errc: " << e.GetCode() << std::endl;
+ AssertThrow(false, ExcParseError(e.GetCode(), e.GetMsg().c_str()));
+ return 0.0;
+ }
}
Assert (values.size() == this->n_components,
ExcDimensionMismatch (values.size(), this->n_components));
- // Statically allocates dim+1
- // double variables.
- double vars[dim+1];
+
+ // initialize if not done so on this thread yet:
+ init_muparser();
for (unsigned int i=0; i<dim; ++i)
- vars[i] = p(i);
-
- // We need the time variable only
- // if the number of variables is
- // different from the dimension. In
- // this case it can only be dim+1,
- // otherwise an exception would
- // have already been thrown
+ vars.get()[i] = p(i);
if (dim != n_vars)
- vars[dim] = this->get_time();
-
+ vars.get()[dim] = this->get_time();
+
for (unsigned int component = 0; component < this->n_components;
++component)
- {
- values(component) = fp[component].Eval((double *)vars);
- AssertThrow(fp[component].EvalError() == 0,
- ExcMessage(fp[component].ErrorMsg()));
- }
+ values(component) = fp.get()[component].Eval();
}
#else
+
template <int dim>
void
FunctionParser<dim>::initialize(const std::string &,
Assert(false, ExcNeedsFunctionparser());
}
+template <int dim>
+void
+FunctionParser<dim>::initialize(const std::string &,
+ const std::vector<std::string> &,
+ const std::map<std::string, double> &,
+ const bool)
+{
+ Assert(false, ExcNeedsFunctionparser());
+}
+
+template <int dim>
+void
+FunctionParser<dim>::initialize(const std::string &,
+ const std::string &,
+ const std::map<std::string, double> &,
+ const bool)
+{
+ Assert(false, ExcNeedsFunctionparser());
+}
+
+
template <int dim>
double FunctionParser<dim>::value (
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005 - 2013 by the deal.II authors
+// Copyright (C) 2005 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
MPI_InitFinalize::MPI_InitFinalize (int &argc,
char ** &argv,
- unsigned int max_num_threads)
+ const unsigned int max_num_threads)
:
owns_mpi (true)
{
void
MPI_InitFinalize::do_init(int &argc,
char ** &argv,
- unsigned int max_num_threads)
+ const unsigned int max_num_threads)
{
static bool constructor_has_already_run = false;
Assert (constructor_has_already_run == false,
constructor_has_already_run = true;
- //set maximum number of threads:
+ // set maximum number of threads (also respecting the environment
+ // variable that the called function evaluates)
multithread_info.set_thread_limit(max_num_threads);
}
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: logstream.cc 31932 2013-12-08 02:15:54Z heister $
+//
+// Copyright (C) 1998 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/named_data.h>
+#include <deal.II/algorithms/any_data.h>
+
+DEAL_II_NAMESPACE_OPEN
+
+void
+NamedSelection::initialize(const AnyData &data)
+{
+ indices.resize(names.size());
+ for (unsigned int i=0; i<names.size(); ++i)
+ indices[i] = data.find(names[i]);
+}
+
+DEAL_II_NAMESPACE_CLOSE
+
int lineno=0;
bool status = true;
- while (input)
+ while (getline (input, line))
{
++lineno;
- getline (input, line);
status &= scan_line (line, filename, lineno);
}
const std::string value = p->second.get<std::string>("value");
// print name
- out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n\n"
+ out << "\\item {\\it Parameter name:} {\\tt " << demangle(p->first) << "}\n"
+ << "\\phantomsection\\label{parameters:";
+ for (unsigned int i=0; i<subsection_path.size(); ++i)
+ out << subsection_path[i] << "/";
+ out << demangle(p->first);
+ out << "}\n\n"
<< std::endl;
out << "\\index[prmindex]{"
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2000 - 2013 by the deal.II authors
+// Copyright (C) 2000 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
#include <deal.II/base/thread_management.h>
#include <cmath>
+#include <algorithm>
#include <limits>
DEAL_II_NAMESPACE_OPEN
}
+template <int dim>
+QSorted<dim>::QSorted(Quadrature<dim> quad) :
+ Quadrature<dim>(quad.size())
+{
+ std::vector< std::pair<double, Point<dim> > > wp;
+ for (unsigned int i=0; i<quad.size(); ++i)
+ wp.push_back(std::pair<double, Point<dim> >(quad.weight(i),
+ quad.point(i)));
+ sort(wp.begin(), wp.end(), *this);
+ for(unsigned int i=0; i<quad.size(); ++i)
+ {
+ this->weights[i] = wp[i].first;
+ this->quadrature_points[i] = wp[i].second;
+ }
+}
+
+
+template <int dim>
+bool QSorted<dim>::operator()(const std::pair<double, Point<dim> > &a,
+ const std::pair<double, Point<dim> > &b)
+{
+ return (a.first < b.first);
+}
+
+
// construct the quadrature formulae in higher dimensions by
// tensor product of lower dimensions
template class QMilne<3>;
template class QWeddle<3>;
+template class QSorted<1>;
+template class QSorted<2>;
+template class QSorted<3>;
+
DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.cc 30037 2013-07-18 16:55:40Z maier $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/time_stepping.templates.h>
+#include <deal.II/lac/vector.h>
+#include <deal.II/lac/block_vector.h>
+#include <deal.II/lac/parallel_vector.h>
+#include <deal.II/lac/parallel_block_vector.h>
+#include <deal.II/lac/petsc_vector.h>
+#include <deal.II/lac/petsc_block_vector.h>
+#include <deal.II/lac/petsc_parallel_vector.h>
+#include <deal.II/lac/petsc_parallel_block_vector.h>
+#include <deal.II/lac/trilinos_vector.h>
+#include <deal.II/lac/trilinos_block_vector.h>
+#include <deal.II/lac/trilinos_parallel_block_vector.h>
+
+DEAL_II_NAMESPACE_OPEN
+namespace TimeStepping
+{
+#include "time_stepping.inst"
+}
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id: time_stepping.inst.in 30049 2013-07-18 19:42:40Z maier $
+//
+// Copyright (C) 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+for (S : REAL_SCALARS; V : DEAL_II_VEC_TEMPLATES)
+{
+ template class ExplicitRungeKutta<V<S> >;
+ template class ImplicitRungeKutta<V<S> >;
+ template class EmbeddedExplicitRungeKutta<V<S> >;
+}
+
+for (S : REAL_SCALARS; V : DEAL_II_VEC_TEMPLATES)
+{
+ template class ExplicitRungeKutta<parallel::distributed::V<S> >;
+ template class ImplicitRungeKutta<parallel::distributed::V<S> >;
+ template class EmbeddedExplicitRungeKutta<parallel::distributed::V<S> >;
+}
+
+for (V : EXTERNAL_SEQUENTIAL_VECTORS)
+{
+ template class ExplicitRungeKutta<V>;
+ template class ImplicitRungeKutta<V>;
+ template class EmbeddedExplicitRungeKutta<V>;
+}
+
+for (V : EXTERNAL_PARALLEL_VECTORS)
+{
+ template class ExplicitRungeKutta<V>;
+ template class ImplicitRungeKutta<V>;
+ template class EmbeddedExplicitRungeKutta<V>;
+}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2010 - 2013 by the deal.II authors
+// Copyright (C) 2010 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
\}
\}
#endif
+
+
+#if deal_II_dimension == 3
+
+namespace parallel
+\{
+ namespace distributed
+ \{
+ namespace GridRefinement
+ \{
+ template
+ void
+ refine_and_coarsen_fixed_number<deal_II_dimension-1,dealii::Vector<S>,deal_II_dimension>
+ (parallel::distributed::Triangulation<deal_II_dimension-1,deal_II_dimension> &,
+ const dealii::Vector<S> &,
+ const double,
+ const double);
+
+ template
+ void
+ refine_and_coarsen_fixed_fraction<deal_II_dimension-1,dealii::Vector<S>,deal_II_dimension>
+ (parallel::distributed::Triangulation<deal_II_dimension-1,deal_II_dimension> &,
+ const dealii::Vector<S> &,
+ const double,
+ const double);
+ \}
+ \}
+\}
+
+#endif
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
types<2>::balance_type btype,
p4est_init_t init_fn);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ p4est_gloidx_t (&partition) (types<2>::forest *p4est,
+ int partition_for_coarsening,
+ p4est_weight_t weight_fn);
+#else
static
void (&partition) (types<2>::forest *p4est,
int partition_for_coarsening,
p4est_weight_t weight_fn);
+#endif
static
void (&save) (const char *filename,
types<2>::forest *p4est,
int save_data);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<2>::forest *(&load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<2>::connectivity **p4est);
+#else
static
types<2>::forest *(&load) (const char *filename,
MPI_Comm mpicomm,
int load_data,
void *user_pointer,
types<2>::connectivity **p4est);
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ int (&connectivity_save) (const char *filename,
+ types<2>::connectivity *connectivity);
+#else
static
void (&connectivity_save) (const char *filename,
types<2>::connectivity *connectivity);
+#endif
static
int (&connectivity_is_valid) (types<2>::connectivity *connectivity);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<2>::connectivity *(&connectivity_load) (const char *filename,
+ long unsigned *length);
+#else
static
types<2>::connectivity *(&connectivity_load) (const char *filename,
long *length);
+#endif
static
unsigned int (&checksum) (types<2>::forest *p4est);
p4est_init_t init_fn)
= p4est_balance;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ p4est_gloidx_t (&functions<2>::partition) (types<2>::forest *p4est,
+ int partition_for_coarsening,
+ p4est_weight_t weight_fn)
+ = p4est_partition_ext;
+#else
void (&functions<2>::partition) (types<2>::forest *p4est,
int partition_for_coarsening,
p4est_weight_t weight_fn)
= p4est_partition_ext;
+#endif
void (&functions<2>::save) (const char *filename,
types<2>::forest *p4est,
int save_data)
= p4est_save;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<2>::forest *
+ (&functions<2>::load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<2>::connectivity **p4est)
+ = p4est_load_ext;
+#else
types<2>::forest *
(&functions<2>::load) (const char *filename,
MPI_Comm mpicomm,
void *user_pointer,
types<2>::connectivity **p4est)
= p4est_load;
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ int (&functions<2>::connectivity_save) (const char *filename,
+ types<2>::connectivity *connectivity)
+ = p4est_connectivity_save;
+#else
void (&functions<2>::connectivity_save) (const char *filename,
types<2>::connectivity *connectivity)
= p4est_connectivity_save;
+#endif
int (&functions<2>::connectivity_is_valid) (types<2>::connectivity
*connectivity)
= p4est_connectivity_is_valid;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<2>::connectivity *
+ (&functions<2>::connectivity_load) (const char *filename,
+ long unsigned *length)
+ = p4est_connectivity_load;
+#else
types<2>::connectivity *
(&functions<2>::connectivity_load) (const char *filename,
long *length)
= p4est_connectivity_load;
+#endif
unsigned int (&functions<2>::checksum) (types<2>::forest *p4est)
= p4est_checksum;
types<3>::balance_type btype,
p8est_init_t init_fn);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ p4est_gloidx_t (&partition) (types<3>::forest *p8est,
+ int partition_for_coarsening,
+ p8est_weight_t weight_fn);
+#else
static
void (&partition) (types<3>::forest *p8est,
int partition_for_coarsening,
p8est_weight_t weight_fn);
+#endif
static
void (&save) (const char *filename,
types<3>::forest *p4est,
int save_data);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<3>::forest *(&load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<3>::connectivity **p4est);
+#else
static
types<3>::forest *(&load) (const char *filename,
MPI_Comm mpicomm,
int load_data,
void *user_pointer,
types<3>::connectivity **p4est);
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ int (&connectivity_save) (const char *filename,
+ types<3>::connectivity *connectivity);
+#else
static
void (&connectivity_save) (const char *filename,
types<3>::connectivity *connectivity);
+#endif
static
int (&connectivity_is_valid) (types<3>::connectivity *connectivity);
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ static
+ types<3>::connectivity *(&connectivity_load) (const char *filename,
+ long unsigned *length);
+#else
static
types<3>::connectivity *(&connectivity_load) (const char *filename,
long *length);
+#endif
static
unsigned int (&checksum) (types<3>::forest *p8est);
p8est_init_t init_fn)
= p8est_balance;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ p4est_gloidx_t (&functions<3>::partition) (types<3>::forest *p8est,
+ int partition_for_coarsening,
+ p8est_weight_t weight_fn)
+ = p8est_partition_ext;
+#else
void (&functions<3>::partition) (types<3>::forest *p8est,
int partition_for_coarsening,
p8est_weight_t weight_fn)
= p8est_partition_ext;
+#endif
void (&functions<3>::save) (const char *filename,
types<3>::forest *p4est,
int save_data)
= p8est_save;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<3>::forest *
+ (&functions<3>::load_ext) (const char *filename,
+ MPI_Comm mpicomm,
+ std::size_t data_size,
+ int load_data,
+ int autopartition,
+ int broadcasthead,
+ void *user_pointer,
+ types<3>::connectivity **p4est)
+ = p8est_load_ext;
+#else
types<3>::forest *
(&functions<3>::load) (const char *filename,
MPI_Comm mpicomm,
void *user_pointer,
types<3>::connectivity **p4est)
= p8est_load;
+#endif
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ int (&functions<3>::connectivity_save) (const char *filename,
+ types<3>::connectivity *connectivity)
+ = p8est_connectivity_save;
+#else
void (&functions<3>::connectivity_save) (const char *filename,
types<3>::connectivity *connectivity)
= p8est_connectivity_save;
+#endif
int (&functions<3>::connectivity_is_valid) (types<3>::connectivity
*connectivity)
= p8est_connectivity_is_valid;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ types<3>::connectivity *
+ (&functions<3>::connectivity_load) (const char *filename,
+ long unsigned *length)
+ = p8est_connectivity_load;
+#else
types<3>::connectivity *
(&functions<3>::connectivity_load) (const char *filename,
long *length)
= p8est_connectivity_load;
+#endif
unsigned int (&functions<3>::checksum) (types<3>::forest *p8est)
= p8est_checksum;
// orientation
//
// while we're at it, also copy the neighborship information between cells
- typename Triangulation<dim>::active_cell_iterator
+ typename Triangulation<dim, spacedim>::active_cell_iterator
cell = triangulation.begin_active(),
endc = triangulation.end();
for (; cell != endc; ++cell)
update_number_cache ();
}
+ template <int dim, int spacedim>
+ bool
+ Triangulation<dim,spacedim>::has_hanging_nodes () const
+ {
+ // if there are any active cells with level less than n_global_levels()-1, then
+ // there is obviously also one with level n_global_levels()-1, and
+ // consequently there must be a hanging node somewhere.
+ //
+ // the problem is that we cannot just ask for the first active cell, but
+ // instead need to filter over locally owned cells
+ bool res_local = false;
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator cell = this->begin_active();
+ (cell != this->end()) && (cell->level() < (int)(n_global_levels()-1));
+ cell++)
+ if (cell->is_locally_owned())
+ {
+ res_local = true;
+ break;
+ }
+
+ // reduce over MPI
+ bool res;
+ MPI_Allreduce(&res_local, &res, 1, MPI::BOOL, MPI_LOR, mpi_communicator);
+ return res;
+ }
+
template <int dim, int spacedim>
template <int dim, int spacedim>
void
Triangulation<dim,spacedim>::
- load(const char *filename)
+ load (const char *filename,
+ const bool autopartition)
{
- Assert(this->n_cells()>0, ExcMessage("load() only works if Triangulation already contains the same coarse mesh!"));
+ Assert(this->n_cells()>0, ExcMessage("load() only works if the Triangulation already contains a coarse mesh!"));
Assert(this->n_levels()==1, ExcMessage("Triangulation may only contain coarse cells when calling load()."));
Assert(version == 2, ExcMessage("Incompatible version found in .info file."));
Assert(this->n_cells(0) == n_coarse_cells, ExcMessage("Number of coarse cells differ!"));
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+#else
+ AssertThrow(numcpus <= Utilities::MPI::n_mpi_processes (mpi_communicator),
+ ExcMessage("parallel::distributed::Triangulation::load() only supports loading "
+ "saved data with a greater or equal number of processes than were used to "
+ "save() when using p4est 0.3.4.2."));
+#endif
attached_data_size = 0;
n_attached_datas = 0;
n_attached_deserialize = attached_count;
+#if DEAL_II_P4EST_VERSION_GTE(0,3,4,3)
+ parallel_forest = dealii::internal::p4est::functions<dim>::load_ext (
+ filename, mpi_communicator,
+ attached_size, attached_size>0,
+ autopartition, 0,
+ this,
+ &connectivity);
+#else
parallel_forest = dealii::internal::p4est::functions<dim>::load (
filename, mpi_communicator,
attached_size, attached_size>0,
this,
&connectivity);
-
+#endif
if (numcpus != Utilities::MPI::n_mpi_processes (mpi_communicator))
{
// We are changing the number of CPUs so we need to repartition.
}
}
- template <>
- void
- Triangulation<1,1>::
- fill_vertices_with_ghost_neighbors
- (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
- &vertices_with_ghost_neighbors)
- {
- Assert (false, ExcNotImplemented());
- }
-
- template <>
- void
- Triangulation<1,2>::
- fill_vertices_with_ghost_neighbors
- (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
- &vertices_with_ghost_neighbors)
- {
- Assert (false, ExcNotImplemented());
- }
-
- template <>
- void
- Triangulation<1,3>::
- fill_vertices_with_ghost_neighbors
- (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
- &vertices_with_ghost_neighbors)
- {
- Assert (false, ExcNotImplemented());
- }
/**
* Determine the neighboring subdomains that are adjacent to each vertex.
- * This is achieved via the p4est_iterate tool
+ * This is achieved via the p4est_iterate/p8est_iterate tool
*/
- template <>
+ template <int dim, int spacedim>
void
- Triangulation<2,2>::
+ Triangulation<dim,spacedim>::
fill_vertices_with_ghost_neighbors
(std::map<unsigned int, std::set<dealii::types::subdomain_id> >
&vertices_with_ghost_neighbors)
{
- struct find_ghosts<2,2> fg;
-
- fg.subids = sc_array_new (sizeof (dealii::types::subdomain_id));
- fg.triangulation = this;
- fg.vertices_with_ghost_neighbors = &(vertices_with_ghost_neighbors);
-
- p4est_iterate (this->parallel_forest, this->parallel_ghost, static_cast<void *>(&fg),
- NULL, find_ghosts_face<2,2>, find_ghosts_corner<2,2>);
-
- sc_array_destroy (fg.subids);
- }
+ Assert (dim>1, ExcNotImplemented());
- /**
- * Determine the neighboring subdomains that are adjacent to each vertex.
- * This is achieved via the p4est_iterate tool
- */
- template <>
- void
- Triangulation<2,3>::
- fill_vertices_with_ghost_neighbors
- (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
- &vertices_with_ghost_neighbors)
- {
- struct find_ghosts<2,3> fg;
+ struct find_ghosts<dim,spacedim> fg;
fg.subids = sc_array_new (sizeof (dealii::types::subdomain_id));
fg.triangulation = this;
- fg.vertices_with_ghost_neighbors = &(vertices_with_ghost_neighbors);
+ fg.vertices_with_ghost_neighbors = &vertices_with_ghost_neighbors;
- p4est_iterate (this->parallel_forest, this->parallel_ghost, static_cast<void *>(&fg),
- NULL, find_ghosts_face<2,3>, find_ghosts_corner<2,3>);
+ // switch between functions. to make the compiler happy, we need to cast
+ // the first two arguments to the type p[48]est_iterate wants to see. this
+ // cast is the identity cast in each of the two branches, so it is safe.
+ switch (dim)
+ {
+ case 2:
+ p4est_iterate (reinterpret_cast<dealii::internal::p4est::types<2>::forest*>(this->parallel_forest),
+ reinterpret_cast<dealii::internal::p4est::types<2>::ghost*>(this->parallel_ghost),
+ static_cast<void *>(&fg),
+ NULL, find_ghosts_face<2,spacedim>, find_ghosts_corner<2,spacedim>);
+ break;
+
+ case 3:
+ p8est_iterate (reinterpret_cast<dealii::internal::p4est::types<3>::forest*>(this->parallel_forest),
+ reinterpret_cast<dealii::internal::p4est::types<3>::ghost*>(this->parallel_ghost),
+ static_cast<void *>(&fg),
+ NULL, find_ghosts_face<3,spacedim>, find_ghosts_edge<3,spacedim>, find_ghosts_corner<3,spacedim>);
+ break;
+
+ default:
+ Assert (false, ExcNotImplemented());
+ }
sc_array_destroy (fg.subids);
}
- /**
- * Determine the neighboring subdomains that are adjacent to each vertex.
- * This is achieved via the p8est_iterate tool
- */
- template <>
- void
- Triangulation<3,3>::
- fill_vertices_with_ghost_neighbors
- (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
- &vertices_with_ghost_neighbors)
- {
- struct find_ghosts<3,3> fg;
-
- fg.subids = sc_array_new (sizeof (dealii::types::subdomain_id));
- fg.triangulation = this;
- fg.vertices_with_ghost_neighbors = &(vertices_with_ghost_neighbors);
-
- p8est_iterate (this->parallel_forest, this->parallel_ghost, static_cast<void *>(&fg),
- NULL, find_ghosts_face<3,3>, find_ghosts_edge<3,3>, find_ghosts_corner<3,3>);
-
- sc_array_destroy (fg.subids);
- }
template <int dim, int spacedim>
MPI_Comm
return mpi_communicator;
}
+
template<int dim, int spacedim>
void
Triangulation<dim,spacedim>::add_periodicity
for (i = 0; i < l; i++)
{
typename dealii::Triangulation<dim,spacedim>::cell_iterator cell (triangulation, i, dealii_index);
- child_id = internal::p4est::functions<dim>::quadrant_ancestor_id (&quad, i + 1);
+ child_id = dealii::internal::p4est::functions<dim>::quadrant_ancestor_id (&quad, i + 1);
Assert (cell->has_children (), ExcMessage ("p4est quadrant does not correspond to a cell!"));
dealii_index = cell->child_index(child_id);
}
- // TODO: again problems with specialization in only one template argument
- template <>
- Triangulation<1,1>::Triangulation (MPI_Comm)
+ template <int spacedim>
+ Triangulation<1,spacedim>::Triangulation (MPI_Comm)
{
Assert (false, ExcNotImplemented());
}
- template <>
- Triangulation<1,1>::~Triangulation ()
+ template <int spacedim>
+ Triangulation<1,spacedim>::~Triangulation ()
{
Assert (false, ExcNotImplemented());
}
- template <>
+ template <int spacedim>
types::subdomain_id
- Triangulation<1,1>::locally_owned_subdomain () const
+ Triangulation<1,spacedim>::locally_owned_subdomain () const
{
Assert (false, ExcNotImplemented());
return 0;
}
- template <>
+ template <int spacedim>
types::global_dof_index
- Triangulation<1,1>::n_global_active_cells () const
+ Triangulation<1,spacedim>::n_global_active_cells () const
{
Assert (false, ExcNotImplemented());
return 0;
}
- template <>
+ template <int spacedim>
unsigned int
- Triangulation<1,1>::n_global_levels () const
+ Triangulation<1,spacedim>::n_global_levels () const
{
Assert (false, ExcNotImplemented());
return 0;
}
- template <>
+ template <int spacedim>
MPI_Comm
- Triangulation<1,1>::get_communicator () const
+ Triangulation<1,spacedim>::get_communicator () const
{
return MPI_COMM_WORLD;
}
- template <>
+ template <int spacedim>
const std::vector<types::global_dof_index> &
- Triangulation<1,1>::get_p4est_tree_to_coarse_cell_permutation() const
+ Triangulation<1,spacedim>::get_p4est_tree_to_coarse_cell_permutation() const
{
static std::vector<types::global_dof_index> a;
return a;
}
-
- template <>
- Triangulation<1,2>::Triangulation (MPI_Comm)
- {
- Assert (false, ExcNotImplemented());
- }
-
-
- template <>
- Triangulation<1,2>::~Triangulation ()
- {
- Assert (false, ExcNotImplemented());
- }
-
-
-
- template <>
- types::subdomain_id
- Triangulation<1,2>::locally_owned_subdomain () const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- types::global_dof_index
- Triangulation<1,2>::n_global_active_cells () const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- unsigned int
- Triangulation<1,2>::n_global_levels () const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- MPI_Comm
- Triangulation<1,2>::get_communicator () const
- {
- return MPI_COMM_WORLD;
- }
-
-
- template <>
- Triangulation<1,3>::Triangulation (MPI_Comm)
- {
- Assert (false, ExcNotImplemented());
- }
-
-
- template <>
- Triangulation<1,3>::~Triangulation ()
- {
- Assert (false, ExcNotImplemented());
- }
-
-
-
- template <>
- types::subdomain_id
- Triangulation<1,3>::locally_owned_subdomain () const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- types::global_dof_index
- Triangulation<1,3>::n_global_active_cells () const
- {
- Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- unsigned int
- Triangulation<1,3>::n_global_levels () const
+ template <int spacedim>
+ void
+ Triangulation<1,spacedim>::
+ fill_vertices_with_ghost_neighbors
+ (std::map<unsigned int, std::set<dealii::types::subdomain_id> >
+ &vertices_with_ghost_neighbors)
{
Assert (false, ExcNotImplemented());
- return 0;
- }
-
-
- template <>
- MPI_Comm
- Triangulation<1,3>::get_communicator () const
- {
- return MPI_COMM_WORLD;
}
}
}
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell; ++cell)
+ for (level_cell_iterator cell = begin(level); cell != end(level); ++cell)
for (unsigned int line=0; line < GeometryInfo<2>::faces_per_cell; ++line)
cell->face(line)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
-
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell ; ++cell)
+ for (level_cell_iterator cell = begin(level) ; cell != end(level) ; ++cell)
for (unsigned int line=0; line < GeometryInfo<3>::lines_per_cell; ++line)
cell->line(line)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- level_cell_iterator cell = begin(level),
- endcell = end(level);
- for ( ; cell != endcell ; ++cell)
+ for (level_cell_iterator cell = begin(level) ; cell != end(level); ++cell)
for (unsigned int quad=0; quad < GeometryInfo<3>::faces_per_cell; ++quad)
cell->face(quad)->set_user_flag();
// level, as those lines logically belong to the same
// level as the cell, at least for for isotropic
// refinement
- typename DoFHandler<2,spacedim>::level_cell_iterator cell = dof_handler.begin(level),
- endcell = dof_handler.end(level);
- for ( ; cell != endcell; ++cell)
+ for (typename DoFHandler<2,spacedim>::level_cell_iterator cell = dof_handler.begin(level);
+ cell != dof_handler.end(level); ++cell)
for (unsigned int line=0; line < GeometryInfo<2>::faces_per_cell; ++line)
cell->face(line)->set_user_flag();
tr->clear_user_flags ();
//mark all own cells for transfer
- typename DoFHandler<dim,spacedim>::active_cell_iterator
- cell, endc = dof_handler.end();
- for (cell = dof_handler.begin_active(); cell != endc; ++cell)
+ for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active();
+ cell != dof_handler.end(); ++cell)
if (!cell->is_artificial())
cell->set_user_flag();
//check that we are really done
{
std::vector<dealii::types::global_dof_index> local_dof_indices;
- typename DoFHandler<dim,spacedim>::active_cell_iterator
- cell, endc = dof_handler.end();
- for (cell = dof_handler.begin_active(); cell != endc; ++cell)
+ for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active();
+ cell != dof_handler.end(); ++cell)
if (!cell->is_artificial())
{
local_dof_indices.resize (cell->get_fe().dofs_per_cell);
const bool use_constraints,
const std::vector<types::global_dof_index> &starting_indices)
{
- std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
+ std::vector<types::global_dof_index> renumbering(dof_handler.locally_owned_dofs().n_elements(),
DH::invalid_dof_index);
compute_Cuthill_McKee(renumbering, dof_handler, reversed_numbering,
use_constraints, starting_indices);
const bool use_constraints,
const std::vector<types::global_dof_index> &starting_indices)
{
- // make the connection graph. in
- // more than 2d use an intermediate
- // compressed sparsity pattern
- // since the we don't have very
- // good estimates for
- // max_couplings_between_dofs() in
- // 3d and this then leads to
- // excessive memory consumption
+ // make the connection graph. in 2d/3d use an intermediate compressed
+ // sparsity pattern since the we don't have very good estimates for
+ // max_couplings_between_dofs() in 3d and this then leads to excessive
+ // memory consumption
//
- // note that if constraints are not
- // requested, then the
- // 'constraints' object will be
- // empty, and calling condense with
- // it is a no-op
+ // note that if constraints are not requested, then the 'constraints'
+ // object will be empty and nothing happens
ConstraintMatrix constraints;
if (use_constraints)
DoFTools::make_hanging_node_constraints (dof_handler, constraints);
constraints.close ();
+ IndexSet locally_owned = dof_handler.locally_owned_dofs();
SparsityPattern sparsity;
if (DH::dimension < 2)
{
else
{
CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
- dof_handler.n_dofs());
+ dof_handler.n_dofs(),
+ dof_handler.locally_owned_dofs());
DoFTools::make_sparsity_pattern (dof_handler, csp, constraints);
- sparsity.copy_from (csp);
+
+ // If the index set is not complete, need to get indices in local
+ // index space.
+ if (dof_handler.locally_owned_dofs().n_elements() !=
+ dof_handler.locally_owned_dofs().size())
+ {
+ // Create sparsity pattern from csp by transferring its indices to
+ // processor-local index space and doing Cuthill-McKee there
+ std::vector<unsigned int> row_lengths(locally_owned.n_elements());
+ for (unsigned int i=0; i<locally_owned.n_elements(); ++i)
+ row_lengths[i] = csp.row_length(locally_owned.nth_index_in_set(i));
+ sparsity.reinit(locally_owned.n_elements(), locally_owned.n_elements(),
+ row_lengths);
+ std::vector<types::global_dof_index> row_entries;
+ for (unsigned int i=0; i<locally_owned.n_elements(); ++i)
+ {
+ const types::global_dof_index row = locally_owned.nth_index_in_set(i);
+ row_entries.resize(0);
+ for (CompressedSimpleSparsityPattern::row_iterator it =
+ csp.row_begin(row); it != csp.row_end(row); ++it)
+ if (*it != row && locally_owned.is_element(*it))
+ row_entries.push_back(locally_owned.index_within_set(*it));
+ sparsity.add_entries(i, row_entries.begin(), row_entries.end(),
+ true);
+ }
+ sparsity.compress();
+ }
+ else
+ sparsity.copy_from(csp);
}
// constraints are not needed anymore
if (reversed_numbering)
new_indices = Utilities::reverse_permutation (new_indices);
+
+ // convert indices back to global index space
+ for (std::size_t i=0; i<new_indices.size(); ++i)
+ new_indices[i] = locally_owned.nth_index_in_set(new_indices[i]);
}
tria->get_p4est_tree_to_coarse_cell_permutation() [c];
const typename DoFHandler<dim>::level_cell_iterator
- cell (tria, 0, coarse_cell_index, &dof_handler);
+ this_cell (tria, 0, coarse_cell_index, &dof_handler);
next_free = compute_hierarchical_recursive<dim> (next_free,
renumbering,
- cell,
+ this_cell,
locally_owned);
}
#else
Assert (component_mask.represents_n_components(n_components),
ExcDimensionMismatch(n_components,
component_mask.size()));
- std::vector<unsigned int> localized_component (n_components,
- numbers::invalid_unsigned_int);
- unsigned int n_components_selected = 0;
- for (unsigned int i=0; i<n_components; ++i)
- if (component_mask[i] == true)
- localized_component[i] = n_components_selected++;
std::vector<unsigned char> dofs_by_component (dof_handler.n_locally_owned_dofs());
internal::get_component_association (dof_handler, component_mask,
if (component_mask[dofs_by_component[i]])
component_numbering[i] = count++;
- // First count the number of dofs in the current component.
- constant_modes.resize (n_components_selected, std::vector<bool>(n_selected_dofs,
- false));
-
- // Loop over all owned cells and ask the element for the constant modes
+ // get the element constant modes and find a translation table between
+ // index in the constant modes and the components.
+ //
+ // TODO: We might be able to extend this also for elements which do not
+ // have the same constant modes, but that is messy...
const dealii::hp::FECollection<DH::dimension,DH::space_dimension>
fe_collection (dof_handler.get_fe());
std::vector<Table<2,bool> > element_constant_modes;
+ std::vector<std::vector<std::pair<unsigned int, unsigned int> > >
+ constant_mode_to_component_translation(n_components);
+ unsigned int n_constant_modes = 0;
for (unsigned int f=0; f<fe_collection.size(); ++f)
- element_constant_modes.push_back(fe_collection[f].get_constant_modes());
+ {
+ std::pair<Table<2,bool>, std::vector<unsigned int> > data
+ = fe_collection[f].get_constant_modes();
+ element_constant_modes.push_back(data.first);
+ if (f==0)
+ for (unsigned int i=0; i<data.second.size(); ++i)
+ if (component_mask[data.second[i]])
+ constant_mode_to_component_translation[data.second[i]].
+ push_back(std::make_pair(n_constant_modes++,i));
+ AssertDimension(element_constant_modes.back().n_rows(),
+ element_constant_modes[0].n_rows());
+ }
+
+ // First count the number of dofs in the current component.
+ constant_modes.clear ();
+ constant_modes.resize (n_constant_modes, std::vector<bool>(n_selected_dofs,
+ false));
+
+ // Loop over all owned cells and ask the element for the constant modes
typename DH::active_cell_iterator cell = dof_handler.begin_active(),
endc = dof_handler.end();
locally_owned_dofs.index_within_set(dof_indices[i]);
const unsigned int comp = dofs_by_component[loc_index];
if (component_mask[comp])
- constant_modes[localized_component[comp]][component_numbering[loc_index]] =
- element_constant_modes[cell->active_fe_index()](comp,i);
+ for (unsigned int j=0; j<constant_mode_to_component_translation[comp].size(); ++j)
+ constant_modes[constant_mode_to_component_translation[comp][j].first]
+ [component_numbering[loc_index]] =
+ element_constant_modes[cell->active_fe_index()]
+ (constant_mode_to_component_translation[comp][j].second,i);
}
}
}
vertex_dof_count[vg] = 0;
// Create a mapping from all vertices to the ones used here
- unsigned int i=0;
+ unsigned int n_vertex_count=0;
for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
if (vertex_dof_count[vg] != 0)
- vertex_mapping[vg] = i++;
+ vertex_mapping[vg] = n_vertex_count++;
// Compactify dof count
for (unsigned int vg=0; vg<vertex_mapping.size(); ++vg)
// Now that we have all the data, we reduce it to the part we actually
// want
- vertex_dof_count.resize(i);
+ vertex_dof_count.resize(n_vertex_count);
// At this point, the list of patches is ready. Now we enter the dofs
// into the sparsity pattern.
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2009 - 2013 by the deal.II authors
+// Copyright (C) 2009 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// ---------------------------------------------------------------------
+
+
+
+
for (SP : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
{
template void
for (deal_II_dimension : DIMENSIONS)
{
+
+#if deal_II_dimension > 1
+ template
+ void
+ DoFTools::extract_locally_relevant_dofs<DoFHandler<deal_II_dimension-1,deal_II_dimension > >
+ (const DoFHandler<deal_II_dimension-1,deal_II_dimension > & dof_handler,
+ IndexSet & dof_set);
+#endif
+
template
void DoFTools::make_vertex_patches (SparsityPattern&, const DoFHandler<deal_II_dimension>&,
unsigned int, bool, bool, bool, bool);
const ComponentMask &,
std::vector<bool> &,
const std::set<types::boundary_id> &);
+
template
void
DoFTools::extract_boundary_dofs<hp::DoFHandler<deal_II_dimension> >
std::vector<bool> &,
const std::set<types::boundary_id> &);
+template
+void
+DoFTools::extract_boundary_dofs<DoFHandler<deal_II_dimension> >
+(const DoFHandler<deal_II_dimension> &,
+ const ComponentMask &,
+ IndexSet &,
+ const std::set<types::boundary_id> &);
+
+template
+void
+DoFTools::extract_boundary_dofs<hp::DoFHandler<deal_II_dimension> >
+(const hp::DoFHandler<deal_II_dimension> &,
+ const ComponentMask &,
+ IndexSet &,
+ const std::set<types::boundary_id> &);
+
template
void
DoFTools::extract_dofs_with_support_on_boundary<DoFHandler<deal_II_dimension> >
const ComponentMask &,
std::vector<bool> &,
const std::set<types::boundary_id> &);
+
+template
+void
+DoFTools::extract_boundary_dofs<DoFHandler<deal_II_dimension,deal_II_dimension+1> >
+ (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
+ const ComponentMask &,
+ IndexSet &,
+ const std::set<types::boundary_id> &);
+
template
unsigned int
DoFTools::count_dofs_with_subdomain_association<DoFHandler<deal_II_dimension,deal_II_dimension+1> >
(const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const types::subdomain_id);
+
template
IndexSet
DoFTools::dof_indices_with_subdomain_association<DoFHandler<deal_II_dimension,deal_II_dimension+1> >
std::vector<bool> &,
const std::set<types::boundary_id> &);
+template
+void
+DoFTools::extract_boundary_dofs<DoFHandler<1,3> >
+ (const DoFHandler<1,3> &,
+ const ComponentMask &,
+ IndexSet &,
+ const std::set<types::boundary_id> &);
+
template
void
DoFTools::get_subdomain_association<DoFHandler<1,3> >
local_dof_indices_col(dofs_per_cell_col);
cell_row_child->get_dof_indices (local_dof_indices_row);
cell_col->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
+ for (unsigned int r=0; r<dofs_per_cell_row; ++r)
+ sparsity.add_entries (local_dof_indices_row[r],
local_dof_indices_col.begin(),
local_dof_indices_col.end());
}
local_dof_indices_col(dofs_per_cell_col);
cell_row->get_dof_indices (local_dof_indices_row);
cell_col_child->get_dof_indices (local_dof_indices_col);
- for (unsigned int i=0; i<dofs_per_cell_row; ++i)
- sparsity.add_entries (local_dof_indices_row[i],
+ for (unsigned int r=0; r<dofs_per_cell_row; ++r)
+ sparsity.add_entries (local_dof_indices_row[r],
local_dof_indices_col.begin(),
local_dof_indices_col.end());
}
if (cell->neighbor_is_coarser(face))
continue;
- typename DH::face_iterator cell_face = cell->face(face);
const unsigned int
neighbor_face = cell->neighbor_of_neighbor(face);
if (cell->neighbor_is_coarser(face))
continue;
- typename dealii::hp::DoFHandler<dim,spacedim>::face_iterator
- cell_face = cell->face(face);
const unsigned int
neighbor_face = cell->neighbor_of_neighbor(face);
fe_system.cc
fe_tools.cc
fe_tools_interpolate.cc
+ fe_trace.cc
fe_values.cc
fe_values_inst2.cc
mapping_c1.cc
fe_system.inst.in
fe_tools.inst.in
fe_tools_interpolate.inst.in
+ fe_trace.inst.in
fe_values.decl.1.inst.in
fe_values.decl.2.inst.in
fe_values.impl.1.inst.in
for (unsigned int i=0; i<nc; ++i)
{
- if (!isotropic_restriction_only || ref_case==RefinementCase<dim>::isotropic_refinement)
+ if (this->restriction[ref_case-1][i].m() != this->dofs_per_cell
+ &&
+ (!isotropic_restriction_only || ref_case==RefinementCase<dim>::isotropic_refinement))
this->restriction[ref_case-1][i].reinit (this->dofs_per_cell,
this->dofs_per_cell);
- if (!isotropic_prolongation_only || ref_case==RefinementCase<dim>::isotropic_refinement)
+ if (this->prolongation[ref_case-1][i].m() != this->dofs_per_cell
+ &&
+ (!isotropic_prolongation_only || ref_case==RefinementCase<dim>::isotropic_refinement))
this->prolongation[ref_case-1][i].reinit (this->dofs_per_cell,
this->dofs_per_cell);
}
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FiniteElement<dim,spacedim>::get_constant_modes () const
{
Assert (false, ExcNotImplemented());
- return Table<2,bool>(this->n_components(), this->dofs_per_cell);
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (Table<2,bool>(this->n_components(), this->dofs_per_cell),
+ std::vector<unsigned int>(this->n_components()));
}
const unsigned int n_dofs = this->dofs_per_cell;
- this->mapping_type = mapping_piola;
+ this->mapping_type = mapping_bdm;
// These must be done first, since
// they change the evaluation of
// basis functions
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_DGP<dim,spacedim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
constant_modes(0,0) = true;
- return constant_modes;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
}
std::vector<ComponentMask>(FiniteElementData<dim>(
get_dpo_vector(degree),1, degree).dofs_per_cell, std::vector<bool>(1,true)))
{
- // Reinit the vectors of
- // restriction and prolongation
- // matrices to the right sizes
- this->reinit_restriction_and_prolongation_matrices();
-
- // Fill prolongation matrices with
- // embedding operators and
- // restriction with L2 projection
- //
- // we can call the respective
- // functions in the case
- // dim==spacedim, but they are not
- // currently implemented for the
- // codim-1 case. there's no harm
- // here, though, since these
- // matrices are independent of the
- // space dimension and so we can
- // copy them from the respective
- // elements (not cheap, but works)
- if (dim == spacedim)
- {
- FETools::compute_embedding_matrices (*this, this->prolongation);
- FETools::compute_projection_matrices (*this, this->restriction);
- }
- else
- {
- FE_DGQ<dim> tmp (degree);
- this->prolongation = tmp.prolongation;
- this->restriction = tmp.restriction;
- }
-
-
- // finally fill in support points
+ // fill in support points
if (degree == 0)
{
// constant elements, take
};
};
- // note: no face support points for
- // DG elements
+ // do not initialize embedding and restriction here. these matrices are
+ // initialized on demand in get_restriction_matrix and
+ // get_prolongation_matrix
+
+ // note: no face support points for DG elements
}
std::vector<ComponentMask>(FiniteElementData<dim>(
get_dpo_vector(points.size()-1),1, points.size()-1).dofs_per_cell, std::vector<bool>(1,true)))
{
- // Reinit the vectors of
- // restriction and prolongation
- // matrices to the right sizes
- this->reinit_restriction_and_prolongation_matrices();
- // Fill prolongation matrices with embedding operators
- FETools::compute_embedding_matrices<dim, double, spacedim> (*this, this->prolongation);
- // Fill restriction matrices with L2-projection
- FETools::compute_projection_matrices<dim, double, spacedim> (*this, this->restriction);
-
// Compute support points, which
// are the tensor product of the
// Lagrange interpolation points in
// the constructor.
Quadrature<dim> support_quadrature(points);
this->unit_support_points = support_quadrature.get_points();
+
+
+ // do not initialize embedding and restriction here. these matrices are
+ // initialized on demand in get_restriction_matrix and
+ // get_prolongation_matrix
}
// source FE is also a
// DGQ element
typedef FiniteElement<dim, spacedim> FE;
- AssertThrow ((x_source_fe.get_name().find ("FE_DGQ<") == 0)
- ||
- (dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
+ AssertThrow ((dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
typename FE::ExcInterpolationNotImplemented() );
// ok, source is a Q element, so
// is necessarily empty -- i.e. there isn't
// much we need to do here.
typedef FiniteElement<dim,spacedim> FE;
- AssertThrow ((x_source_fe.get_name().find ("FE_DGQ<") == 0)
- ||
- (dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
+ AssertThrow ((dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
typename FE::ExcInterpolationNotImplemented());
Assert (interpolation_matrix.m() == 0,
// is necessarily empty -- i.e. there isn't
// much we need to do here.
typedef FiniteElement<dim, spacedim> FE;
- AssertThrow ((x_source_fe.get_name().find ("FE_DGQ<") == 0)
- ||
- (dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
+ AssertThrow ((dynamic_cast<const FE_DGQ<dim, spacedim>*>(&x_source_fe) != 0),
typename FE::ExcInterpolationNotImplemented());
Assert (interpolation_matrix.m() == 0,
+template <int dim, int spacedim>
+const FullMatrix<double> &
+FE_DGQ<dim,spacedim>
+::get_prolongation_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case) const
+{
+ Assert (refinement_case<RefinementCase<dim>::isotropic_refinement+1,
+ ExcIndexRange(refinement_case,0,RefinementCase<dim>::isotropic_refinement+1));
+ Assert (refinement_case!=RefinementCase<dim>::no_refinement,
+ ExcMessage("Prolongation matrices are only available for refined cells!"));
+ Assert (child<GeometryInfo<dim>::n_children(refinement_case),
+ ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
+
+ // initialization upon first request
+ if (this->prolongation[refinement_case-1][child].n() == 0)
+ {
+ Threads::Mutex::ScopedLock lock(this->mutex);
+
+ // if matrix got updated while waiting for the lock
+ if (this->prolongation[refinement_case-1][child].n() ==
+ this->dofs_per_cell)
+ return this->prolongation[refinement_case-1][child];
+
+ // now do the work. need to get a non-const version of data in order to
+ // be able to modify them inside a const function
+ FE_DGQ<dim,spacedim> &this_nonconst = const_cast<FE_DGQ<dim,spacedim>& >(*this);
+ if (refinement_case == RefinementCase<dim>::isotropic_refinement)
+ {
+ std::vector<std::vector<FullMatrix<double> > >
+ isotropic_matrices(RefinementCase<dim>::isotropic_refinement);
+ isotropic_matrices.back().
+ resize(GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)),
+ FullMatrix<double>(this->dofs_per_cell, this->dofs_per_cell));
+ if (dim == spacedim)
+ FETools::compute_embedding_matrices (*this, isotropic_matrices, true);
+ else
+ FETools::compute_embedding_matrices (FE_DGQ<dim>(this->degree),
+ isotropic_matrices, true);
+ this_nonconst.prolongation[refinement_case-1].swap(isotropic_matrices.back());
+ }
+ else
+ {
+ // must compute both restriction and prolongation matrices because
+ // we only check for their size and the reinit call initializes them
+ // all
+ this_nonconst.reinit_restriction_and_prolongation_matrices();
+ if (dim == spacedim)
+ {
+ FETools::compute_embedding_matrices (*this, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (*this, this_nonconst.restriction);
+ }
+ else
+ {
+ FE_DGQ<dim> tmp(this->degree);
+ FETools::compute_embedding_matrices (tmp, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (tmp, this_nonconst.restriction);
+ }
+ }
+ }
+
+ // finally return the matrix
+ return this->prolongation[refinement_case-1][child];
+}
+
+
+
+template <int dim, int spacedim>
+const FullMatrix<double> &
+FE_DGQ<dim,spacedim>
+::get_restriction_matrix (const unsigned int child,
+ const RefinementCase<dim> &refinement_case) const
+{
+ Assert (refinement_case<RefinementCase<dim>::isotropic_refinement+1,
+ ExcIndexRange(refinement_case,0,RefinementCase<dim>::isotropic_refinement+1));
+ Assert (refinement_case!=RefinementCase<dim>::no_refinement,
+ ExcMessage("Restriction matrices are only available for refined cells!"));
+ Assert (child<GeometryInfo<dim>::n_children(refinement_case),
+ ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
+
+ // initialization upon first request
+ if (this->restriction[refinement_case-1][child].n() == 0)
+ {
+ Threads::Mutex::ScopedLock lock(this->mutex);
+
+ // if matrix got updated while waiting for the lock...
+ if (this->restriction[refinement_case-1][child].n() ==
+ this->dofs_per_cell)
+ return this->restriction[refinement_case-1][child];
+
+ // now do the work. need to get a non-const version of data in order to
+ // be able to modify them inside a const function
+ FE_DGQ<dim,spacedim> &this_nonconst = const_cast<FE_DGQ<dim,spacedim>& >(*this);
+ if (refinement_case == RefinementCase<dim>::isotropic_refinement)
+ {
+ std::vector<std::vector<FullMatrix<double> > >
+ isotropic_matrices(RefinementCase<dim>::isotropic_refinement);
+ isotropic_matrices.back().
+ resize(GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)),
+ FullMatrix<double>(this->dofs_per_cell, this->dofs_per_cell));
+ if (dim == spacedim)
+ FETools::compute_projection_matrices (*this, isotropic_matrices, true);
+ else
+ FETools::compute_projection_matrices (FE_DGQ<dim>(this->degree),
+ isotropic_matrices, true);
+ this_nonconst.restriction[refinement_case-1].swap(isotropic_matrices.back());
+ }
+ else
+ {
+ // must compute both restriction and prolongation matrices because
+ // we only check for their size and the reinit call initializes them
+ // all
+ this_nonconst.reinit_restriction_and_prolongation_matrices();
+ if (dim == spacedim)
+ {
+ FETools::compute_embedding_matrices (*this, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (*this, this_nonconst.restriction);
+ }
+ else
+ {
+ FE_DGQ<dim> tmp(this->degree);
+ FETools::compute_embedding_matrices (tmp, this_nonconst.prolongation);
+ FETools::compute_projection_matrices (tmp, this_nonconst.restriction);
+ }
+ }
+ }
+
+ // finally return the matrix
+ return this->restriction[refinement_case-1][child];
+}
+
+
+
template <int dim, int spacedim>
bool
FE_DGQ<dim, spacedim>::hp_constraints_are_implemented () const
unsigned int n = this->degree+1;
- // for DGQ(0) elements, the single
- // shape functions is constant and
+ // for DGQ(0) elements or arbitrary node DGQ with support points not located
+ // at the element boundary, the single shape functions is constant and
// therefore lives on the boundary
- if (this->degree == 0)
+ bool support_points_on_boundary = true;
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::abs(this->unit_support_points[0][d]) > 1e-13)
+ support_points_on_boundary = false;
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::abs(this->unit_support_points.back()[d]-1.) > 1e-13)
+ support_points_on_boundary = false;
+ if (support_points_on_boundary == false)
return true;
unsigned int n2 = n*n;
// (==face 0 in some sense), the
// second on face 1:
return (((shape_index == 0) && (face_index == 0)) ||
- ((shape_index == 1) && (face_index == 1)));
+ ((shape_index == this->degree) && (face_index == 1)));
};
case 2:
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_DGQ<dim,spacedim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
- for (unsigned int i=0; i<this->dofs_per_cell; ++i)
- constant_modes(0,i) = true;
- return constant_modes;
+ constant_modes.fill(true);
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
}
std::string
FE_DGQArbitraryNodes<dim,spacedim>::get_name () const
{
- // note that the
- // FETools::get_fe_from_name
- // function does not work for
- // FE_DGQArbitraryNodes since
- // there is no initialization by
- // a degree value.
+ // note that the FETools::get_fe_from_name function does not work for
+ // FE_DGQArbitraryNodes since there is no initialization by a degree value.
std::ostringstream namebuf;
+ bool equidistant = true;
+ std::vector<double> points(this->degree+1);
- bool type = true;
- const unsigned int n_points = this->degree +1;
- std::vector<double> points(n_points);
- const unsigned int dofs_per_cell = this->dofs_per_cell;
- const std::vector<Point<dim> > &unit_support_points = this->unit_support_points;
- unsigned int index = 0;
+ std::vector<unsigned int> lexicographic = this->poly_space.get_numbering_inverse();
+ for (unsigned int j=0; j<=this->degree; j++)
+ points[j] = this->unit_support_points[lexicographic[j]][0];
- // Decode the support points
- // in one coordinate direction.
- for (unsigned int j=0; j<dofs_per_cell; j++)
- {
- if ((dim>1) ? (unit_support_points[j](1)==0 &&
- ((dim>2) ? unit_support_points[j](2)==0: true)) : true)
- {
- points[index++] = unit_support_points[j](0);
- }
- }
- Assert (index == n_points,
- ExcMessage ("Could not decode support points in one coordinate direction."));
-
- // Check whether the support
- // points are equidistant.
- for (unsigned int j=0; j<n_points; j++)
+ // Check whether the support points are equidistant.
+ for (unsigned int j=0; j<=this->degree; j++)
if (std::fabs(points[j] - (double)j/this->degree) > 1e-15)
{
- type = false;
+ equidistant = false;
break;
}
- if (type == true)
+ if (equidistant == true)
namebuf << "FE_DGQ<" << dim << ">(" << this->degree << ")";
else
{
- // Check whether the support
- // points come from QGaussLobatto.
- const QGaussLobatto<1> points_gl(n_points);
- type = true;
- for (unsigned int j=0; j<n_points; j++)
+ // Check whether the support points come from QGaussLobatto.
+ const QGaussLobatto<1> points_gl(this->degree+1);
+ bool gauss_lobatto = true;
+ for (unsigned int j=0; j<=this->degree; j++)
if (points[j] != points_gl.point(j)(0))
{
- type = false;
+ gauss_lobatto = false;
break;
}
- if (type == true)
+ if (gauss_lobatto == true)
namebuf << "FE_DGQArbitraryNodes<" << dim << ">(QGaussLobatto(" << this->degree+1 << "))";
else
namebuf << "FE_DGQArbitraryNodes<" << dim << ">(QUnknownNodes(" << this->degree << "))";
FiniteElement<dim,spacedim> *
FE_DGQArbitraryNodes<dim,spacedim>::clone() const
{
- // TODO[Prill] : There must be a better way
- // to extract 1D quadrature points from the
- // tensor product FE.
-
- // Construct a dummy quadrature formula
- // containing the FE's nodes:
+ // Construct a dummy quadrature formula containing the FE's nodes:
std::vector<Point<1> > qpoints(this->degree+1);
+ std::vector<unsigned int> lexicographic = this->poly_space.get_numbering_inverse();
for (unsigned int i=0; i<=this->degree; ++i)
- qpoints[i] = Point<1>(this->unit_support_points[i][0]);
+ qpoints[i] = Point<1>(this->unit_support_points[lexicographic[i]][0]);
Quadrature<1> pquadrature(qpoints);
return new FE_DGQArbitraryNodes<dim,spacedim>(pquadrature);
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_FaceQ<dim,spacedim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
for (unsigned int i=0; i<this->dofs_per_cell; ++i)
constant_modes(0,i) = true;
- return constant_modes;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
+}
+
+
+
+// ----------------------------- FE_FaceQ<1,spacedim> ------------------------
+
+template <int spacedim>
+FE_FaceQ<1,spacedim>::FE_FaceQ (const unsigned int degree)
+ :
+ FiniteElement<1,spacedim> (FiniteElementData<1>(get_dpo_vector(degree), 1, degree, FiniteElementData<1>::L2),
+ std::vector<bool>(1,true),
+ std::vector<ComponentMask> (1, ComponentMask(1,true)))
+{
+ this->unit_face_support_points.resize(1);
+
+ // initialize unit support points (this makes it possible to assign initial
+ // values to FE_FaceQ)
+ this->unit_support_points.resize(GeometryInfo<1>::faces_per_cell);
+ this->unit_support_points[1] = Point<1>(1.);
+}
+
+
+
+template <int spacedim>
+FiniteElement<1,spacedim> *
+FE_FaceQ<1,spacedim>::clone() const
+{
+ return new FE_FaceQ<1,spacedim>(this->degree);
+}
+
+
+
+template <int spacedim>
+std::string
+FE_FaceQ<1,spacedim>::get_name () const
+{
+ // note that the FETools::get_fe_from_name function depends on the
+ // particular format of the string this function returns, so they have to be
+ // kept in synch
+ std::ostringstream namebuf;
+ namebuf << "FE_FaceQ<1>(" << this->degree << ")";
+
+ return namebuf.str();
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::
+get_face_interpolation_matrix (const FiniteElement<1,spacedim> &source_fe,
+ FullMatrix<double> &interpolation_matrix) const
+{
+ get_subface_interpolation_matrix (source_fe, numbers::invalid_unsigned_int,
+ interpolation_matrix);
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::
+get_subface_interpolation_matrix (const FiniteElement<1,spacedim> &x_source_fe,
+ const unsigned int subface,
+ FullMatrix<double> &interpolation_matrix) const
+{
+ Assert (interpolation_matrix.n() == this->dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.n(),
+ this->dofs_per_face));
+ Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face,
+ ExcDimensionMismatch (interpolation_matrix.m(),
+ x_source_fe.dofs_per_face));
+ interpolation_matrix(0,0) = 1.;
+}
+
+
+
+template <int spacedim>
+bool
+FE_FaceQ<1,spacedim>::has_support_on_face (
+ const unsigned int shape_index,
+ const unsigned int face_index) const
+{
+ AssertIndexRange(shape_index, 2);
+ return (face_index == shape_index);
+}
+
+
+
+template <int spacedim>
+std::vector<unsigned int>
+FE_FaceQ<1,spacedim>::get_dpo_vector (const unsigned int)
+{
+ std::vector<unsigned int> dpo(2, 0U);
+ dpo[0] = 1;
+ return dpo;
+}
+
+
+
+template <int spacedim>
+bool
+FE_FaceQ<1,spacedim>::hp_constraints_are_implemented () const
+{
+ return true;
+}
+
+
+
+template <int spacedim>
+FiniteElementDomination::Domination
+FE_FaceQ<1,spacedim>::
+compare_for_face_domination (const FiniteElement<1,spacedim> &fe_other) const
+{
+ return FiniteElementDomination::no_requirements;
+}
+
+
+
+template <int spacedim>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
+FE_FaceQ<1,spacedim>::get_constant_modes () const
+{
+ Table<2,bool> constant_modes(1, this->dofs_per_cell);
+ for (unsigned int i=0; i<this->dofs_per_cell; ++i)
+ constant_modes(0,i) = true;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1,0));
+}
+
+
+
+template <int spacedim>
+UpdateFlags
+FE_FaceQ<1,spacedim>::update_once (const UpdateFlags) const
+{
+ return update_default;
+}
+
+
+
+template <int spacedim>
+UpdateFlags
+FE_FaceQ<1,spacedim>::update_each (const UpdateFlags flags) const
+{
+ UpdateFlags out = flags & update_values;
+ if (flags & update_gradients)
+ out |= update_gradients | update_covariant_transformation;
+ if (flags & update_hessians)
+ out |= update_hessians | update_covariant_transformation;
+ if (flags & update_cell_normal_vectors)
+ out |= update_cell_normal_vectors | update_JxW_values;
+
+ return out;
+}
+
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_data (
+ const UpdateFlags,
+ const Mapping<1,spacedim> &,
+ const Quadrature<1> &) const
+{
+ return new typename Mapping<1,spacedim>::InternalDataBase;
+}
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_face_data (
+ const UpdateFlags update_flags,
+ const Mapping<1,spacedim> &,
+ const Quadrature<0>& quadrature) const
+{
+ // generate a new data object and initialize some fields
+ typename Mapping<1,spacedim>::InternalDataBase *data =
+ new typename Mapping<1,spacedim>::InternalDataBase;
+
+ // check what needs to be initialized only once and what on every
+ // cell/face/subface we visit
+ data->update_once = update_once(update_flags);
+ data->update_each = update_each(update_flags);
+ data->update_flags = data->update_once | data->update_each;
+
+ const UpdateFlags flags(data->update_flags);
+ const unsigned int n_q_points = quadrature.size();
+ AssertDimension(n_q_points, 1);
+
+ // No derivatives of this element are implemented.
+ if (flags & update_gradients || flags & update_hessians)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+ return data;
+}
+
+
+
+template <int spacedim>
+typename Mapping<1,spacedim>::InternalDataBase *
+FE_FaceQ<1,spacedim>::get_subface_data (
+ const UpdateFlags flags,
+ const Mapping<1,spacedim> &mapping,
+ const Quadrature<0>& quadrature) const
+{
+ return get_face_data (flags, mapping, quadrature);
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_values
+(const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const Quadrature<1> &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ FEValuesData<1,spacedim> &,
+ CellSimilarity::Similarity &) const
+{
+ // Do nothing, since we do not have values in the interior
+}
+
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_face_values (
+ const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const unsigned int face,
+ const Quadrature<0>& quadrature,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &fedata,
+ FEValuesData<1,spacedim> &data) const
+{
+ const UpdateFlags flags(fedata.update_once | fedata.update_each);
+
+ const unsigned int foffset = face;
+ if (flags & update_values)
+ {
+ for (unsigned int k=0; k<this->dofs_per_cell; ++k)
+ data.shape_values(k,0) = 0.;
+ data.shape_values(foffset,0) = 1;
+ }
+}
+
+
+template <int spacedim>
+void
+FE_FaceQ<1,spacedim>::fill_fe_subface_values (
+ const Mapping<1,spacedim> &,
+ const typename Triangulation<1,spacedim>::cell_iterator &,
+ const unsigned int ,
+ const unsigned int ,
+ const Quadrature<0>& ,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ typename Mapping<1,spacedim>::InternalDataBase &,
+ FEValuesData<1,spacedim> &) const
+{
+ Assert(false, ExcMessage("Should not fille subface values in 1D"));
}
{}
+
template <int dim, int spacedim>
FiniteElement<dim,spacedim> *
FE_FaceP<dim,spacedim>::clone() const
}
+
template <int dim, int spacedim>
std::string
FE_FaceP<dim,spacedim>::get_name () const
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_FaceP<dim,spacedim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
constant_modes(0, face*this->dofs_per_face) = true;
- return constant_modes;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
+}
+
+
+
+template <int spacedim>
+FE_FaceP<1,spacedim>::FE_FaceP (const unsigned int degree)
+ :
+ FE_FaceQ<1,spacedim> (degree)
+{}
+
+
+
+template <int spacedim>
+std::string
+FE_FaceP<1,spacedim>::get_name () const
+{
+ // note that the FETools::get_fe_from_name function depends on the
+ // particular format of the string this function returns, so they have to be
+ // kept in synch
+ std::ostringstream namebuf;
+ namebuf << "FE_FaceP<1>(" << this->degree << ")";
+
+ return namebuf.str();
}
template class FE_PolyFace<TensorProductPolynomials<deal_II_dimension-1> >;
template class FE_PolyFace<PolynomialSpace<deal_II_dimension-1>, deal_II_dimension>;
//template class FE_PolyFace<PolynomialsP<deal_II_dimension>, deal_II_dimension>;
- template class FE_FaceQ<deal_II_dimension>;
- template class FE_FaceP<deal_II_dimension>;
#endif
+ template class FE_FaceQ<deal_II_dimension,deal_II_dimension>;
+ template class FE_FaceP<deal_II_dimension,deal_II_dimension>;
}
// Initialize quadratures to obtain
// quadrature points later on.
const QGauss<dim - 1> reference_edge_quadrature (degree + 1);
- const unsigned int &
- n_edge_points = reference_edge_quadrature.size ();
+ const unsigned int n_edge_points = reference_edge_quadrature.size ();
const unsigned int n_boundary_points
= GeometryInfo<dim>::lines_per_cell * n_edge_points;
- const Quadrature<dim> &edge_quadrature
+ const Quadrature<dim> edge_quadrature
= QProjector<dim>::project_to_all_faces (reference_edge_quadrature);
this->generalized_face_support_points.resize (n_edge_points);
{
// In this case we only need support points
// on the faces of a cell.
- const Quadrature<dim> &edge_quadrature
- = QProjector<dim>::project_to_all_faces
- (reference_edge_quadrature);
-
this->generalized_support_points.resize (n_boundary_points);
for (unsigned int line = 0;
template <int dim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_Nedelec<dim>::get_constant_modes() const
{
Table<2,bool> constant_modes(dim, this->dofs_per_cell);
for (unsigned int d=0; d<dim; ++d)
for (unsigned int i=0; i<this->dofs_per_cell; ++i)
constant_modes(d,i) = true;
- return constant_modes;
+ std::vector<unsigned int> components;
+ for (unsigned int d=0; d<dim; ++d)
+ components.push_back(d);
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, components);
}
// kept in synch
std::ostringstream namebuf;
- bool type = true;
- const unsigned int n_points = this->degree +1;
- std::vector<double> points(n_points);
- const unsigned int dofs_per_cell = this->dofs_per_cell;
- const std::vector<Point<dim> > &unit_support_points = this->unit_support_points;
- unsigned int index = 0;
+ bool equidistant = true;
+ std::vector<double> points(this->degree+1);
// Decode the support points in one coordinate direction.
- for (unsigned int j=0; j<dofs_per_cell; j++)
- {
- if ((dim>1) ? (unit_support_points[j](1)==0 &&
- ((dim>2) ? unit_support_points[j](2)==0: true)) : true)
- {
- if (index == 0)
- points[index] = unit_support_points[j](0);
- else if (index == 1)
- points[n_points-1] = unit_support_points[j](0);
- else
- points[index-1] = unit_support_points[j](0);
-
- index++;
- }
- }
- Assert (index == n_points,
- ExcMessage ("Could not decode support points in one coordinate direction."));
+ std::vector<unsigned int> lexicographic = this->poly_space.get_numbering_inverse();
+ for (unsigned int j=0; j<=this->degree; j++)
+ points[j] = this->unit_support_points[lexicographic[j]][0];
// Check whether the support points are equidistant.
- for (unsigned int j=0; j<n_points; j++)
+ for (unsigned int j=0; j<=this->degree; j++)
if (std::fabs(points[j] - (double)j/this->degree) > 1e-15)
{
- type = false;
+ equidistant = false;
break;
}
- if (type == true)
+ if (equidistant == true)
namebuf << "FE_Q<" << dim << ">(" << this->degree << ")";
else
{
-
// Check whether the support points come from QGaussLobatto.
- const QGaussLobatto<1> points_gl(n_points);
- type = true;
- for (unsigned int j=0; j<n_points; j++)
+ const QGaussLobatto<1> points_gl(this->degree+1);
+ bool gauss_lobatto = true;
+ for (unsigned int j=0; j<=this->degree; j++)
if (points[j] != points_gl.point(j)(0))
{
- type = false;
+ gauss_lobatto = false;
break;
}
- if (type == true)
+ if (gauss_lobatto == true)
namebuf << "FE_Q<" << dim << ">(QGaussLobatto(" << this->degree+1 << "))";
else
namebuf << "FE_Q<" << dim << ">(QUnknownNodes(" << this->degree << "))";
template <typename POLY, int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_Q_Base<POLY,dim,spacedim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
- // leave out last component
- for (unsigned int i=0; i<Utilities::fixed_power<dim>(this->degree+1); ++i)
- constant_modes(0, i) = true;
- return constant_modes;
+ // FE_Q_DG0 should not use this function...
+ AssertDimension(this->dofs_per_cell, Utilities::fixed_power<dim>(this->degree+1));
+ constant_modes.fill(true);
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
}
}
+
+template <int dim, int spacedim>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
+FE_Q_DG0<dim,spacedim>::get_constant_modes () const
+{
+ Table<2,bool> constant_modes(2, this->dofs_per_cell);
+
+ // 1 represented by FE_Q part
+ for (unsigned int i=0; i<this->dofs_per_cell-1; ++i)
+ constant_modes(0, i) = true;
+
+ // 1 represented by DG0 part
+ constant_modes(1, this->dofs_per_cell-1) = true;
+
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int> (2, 0));
+}
+
+
+
// explicit instantiations
#include "fe_q_dg0.inst"
template <int dim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_Q_Hierarchical<dim>::get_constant_modes () const
{
Table<2,bool> constant_modes(1, this->dofs_per_cell);
constant_modes(0,i) = true;
for (unsigned int i=GeometryInfo<dim>::vertices_per_cell; i<this->dofs_per_cell; ++i)
constant_modes(0,i) = false;
- return constant_modes;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
}
template <int dim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FE_RaviartThomas<dim>::get_constant_modes() const
{
Table<2,bool> constant_modes(dim, this->dofs_per_cell);
for (unsigned int d=0; d<dim; ++d)
for (unsigned int i=0; i<this->dofs_per_cell; ++i)
constant_modes(d,i) = true;
- return constant_modes;
+ std::vector<unsigned int> components;
+ for (unsigned int d=0; d<dim; ++d)
+ components.push_back(d);
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, components);
}
{
// if one of the base elements has no support points, then it makes no sense
// to define support points for the composed element, so return an empty
- // array to demonstrate that fact
+ // array to demonstrate that fact. Note that we ignore FE_Nothing in this logic.
for (unsigned int base_el=0; base_el<this->n_base_elements(); ++base_el)
- if (!base_element(base_el).has_support_points())
+ if (!base_element(base_el).has_support_points() && base_element(base_el).dofs_per_cell!=0)
{
this->unit_support_points.resize(0);
return;
= typename FiniteElementData<dim>::Conformity();
{
unsigned int index = 0;
- for (unsigned int index=0; index<fes.size(); ++index)
+ for (index=0; index<fes.size(); ++index)
if (multiplicities[index]>0)
{
total_conformity = fes[index]->conforming_space;
template <int dim, int spacedim>
-Table<2,bool>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
FESystem<dim,spacedim>::get_constant_modes () const
{
+ // Note that this->n_components() is actually only an estimate of how many
+ // constant modes we will need. There might be more than one such mode
+ // (e.g. FE_Q_DG0).
Table<2,bool> constant_modes(this->n_components(), this->dofs_per_cell);
- unsigned int comp=0;
+ std::vector<unsigned int> components;
for (unsigned int i=0; i<base_elements.size(); ++i)
{
- Table<2,bool> base_table = base_elements[i].first->get_constant_modes();
- const unsigned int n_base_components = base_elements[i].first->n_components();
+ std::pair<Table<2,bool>, std::vector<unsigned int> >
+ base_table = base_elements[i].first->get_constant_modes();
+ AssertDimension(base_table.first.n_rows(), base_table.second.size());
+ const unsigned int element_multiplicity = this->element_multiplicity(i);
+
+ // there might be more than one constant mode for some scalar elements,
+ // so make sure the table actually fits: Create a new table with more
+ // rows
+ const unsigned int comp = components.size();
+ if (constant_modes.n_rows() < comp+base_table.first.n_rows()*element_multiplicity)
+ {
+ Table<2,bool> new_constant_modes(comp+base_table.first.n_rows()*
+ element_multiplicity,
+ constant_modes.n_cols());
+ for (unsigned int r=0; r<comp; ++r)
+ for (unsigned int c=0; c<this->dofs_per_cell; ++c)
+ new_constant_modes(r,c) = constant_modes(r,c);
+ constant_modes.swap(new_constant_modes);
+ }
+
+ // next, fill the constant modes from the individual components as well
+ // as the component numbers corresponding to the constant mode rows
for (unsigned int k=0; k<this->dofs_per_cell; ++k)
{
std::pair<std::pair<unsigned int,unsigned int>, unsigned int> ind
= this->system_to_base_index(k);
if (ind.first.first == i)
- for (unsigned int c=0; c<base_table.n_rows(); ++c)
- constant_modes(comp+ind.first.second*n_base_components+c,k)
- = base_table(c,ind.second);
+ for (unsigned int c=0; c<base_table.first.n_rows(); ++c)
+ constant_modes(comp+ind.first.second*base_table.first.n_rows()+c,k)
+ = base_table.first(c,ind.second);
}
- comp += n_base_components * base_elements[i].second;
+ for (unsigned int r=0; r<element_multiplicity; ++r)
+ for (unsigned int c=0; c<base_table.second.size(); ++c)
+ components.push_back(comp+r*this->base_elements[i].first->n_components()
+ +base_table.second[c]);
}
- AssertDimension(comp, this->n_components());
- return constant_modes;
+ AssertDimension(components.size(), constant_modes.n_rows());
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >(constant_modes,
+ components);
}
element.n_blocks()));
types::global_dof_index k=0;
- unsigned int i=0;
+ unsigned int count=0;
for (unsigned int b=0; b<element.n_base_elements(); ++b)
for (unsigned int m=0; m<element.element_multiplicity(b); ++m)
{
- block_data[i++] = (return_start_indices)
+ block_data[count++] = (return_start_indices)
? k
: (element.base_element(b).n_dofs_per_cell());
k += element.base_element(b).n_dofs_per_cell();
}
- Assert (i == element.n_blocks(), ExcInternalError());
+ Assert (count == element.n_blocks(), ExcInternalError());
std::vector<types::global_dof_index> start_indices(block_data.size());
k = 0;
// shape value on the cell.
std::vector<unsigned int> face_c_dofs(n);
std::vector<unsigned int> face_f_dofs(n);
- unsigned int k=0;
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
- {
- const unsigned int offset_c = GeometryInfo<dim>::face_to_cell_vertices(face_coarse, i)
- *fe.dofs_per_vertex;
- const unsigned int offset_f = GeometryInfo<dim>::face_to_cell_vertices(face_fine, i)
- *fe.dofs_per_vertex;
- for (unsigned int j=0; j<fe.dofs_per_vertex; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- for (unsigned int i=1; i<=GeometryInfo<dim>::lines_per_face; ++i)
- {
- const unsigned int offset_c = fe.first_line_index
- + GeometryInfo<dim>::face_to_cell_lines(face_coarse, i-1)
- *fe.dofs_per_line;
- const unsigned int offset_f = fe.first_line_index
- + GeometryInfo<dim>::face_to_cell_lines(face_fine, i-1)
- *fe.dofs_per_line;
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- for (unsigned int i=1; i<=GeometryInfo<dim>::quads_per_face; ++i)
- {
- const unsigned int offset_c = fe.first_quad_index
- + face_coarse
- *fe.dofs_per_quad;
- const unsigned int offset_f = fe.first_quad_index
- + face_fine
- *fe.dofs_per_quad;
- for (unsigned int j=0; j<fe.dofs_per_quad; ++j)
- {
- face_c_dofs[k] = offset_c + j;
- face_f_dofs[k] = offset_f + j;
- ++k;
- }
- }
- Assert (k == fe.dofs_per_face, ExcInternalError());
+ {
+ unsigned int face_dof=0;
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
+ {
+ const unsigned int offset_c = GeometryInfo<dim>::face_to_cell_vertices(face_coarse, i)
+ *fe.dofs_per_vertex;
+ const unsigned int offset_f = GeometryInfo<dim>::face_to_cell_vertices(face_fine, i)
+ *fe.dofs_per_vertex;
+ for (unsigned int j=0; j<fe.dofs_per_vertex; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ for (unsigned int i=1; i<=GeometryInfo<dim>::lines_per_face; ++i)
+ {
+ const unsigned int offset_c = fe.first_line_index
+ + GeometryInfo<dim>::face_to_cell_lines(face_coarse, i-1)
+ *fe.dofs_per_line;
+ const unsigned int offset_f = fe.first_line_index
+ + GeometryInfo<dim>::face_to_cell_lines(face_fine, i-1)
+ *fe.dofs_per_line;
+ for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ for (unsigned int i=1; i<=GeometryInfo<dim>::quads_per_face; ++i)
+ {
+ const unsigned int offset_c = fe.first_quad_index
+ + face_coarse
+ *fe.dofs_per_quad;
+ const unsigned int offset_f = fe.first_quad_index
+ + face_fine
+ *fe.dofs_per_quad;
+ for (unsigned int j=0; j<fe.dofs_per_quad; ++j)
+ {
+ face_c_dofs[face_dof] = offset_c + j;
+ face_f_dofs[face_dof] = offset_f + j;
+ ++face_dof;
+ }
+ }
+ Assert (face_dof == fe.dofs_per_face, ExcInternalError());
+ }
// Set up meshes, one with a single
// reference cell and refine it once
template <int dim>
void
- hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe,
- std::vector<unsigned int> &h2l)
+ hierarchic_to_lexicographic_numbering (unsigned int degree, std::vector<unsigned int>& h2l)
{
- Assert (h2l.size() == fe.dofs_per_cell,
- ExcDimensionMismatch (h2l.size(), fe.dofs_per_cell));
- h2l = hierarchic_to_lexicographic_numbering (fe);
- }
-
+ // number of support points in each
+ // direction
+ const unsigned int n = degree+1;
+ unsigned int dofs_per_cell = n;
+ for (unsigned int i=1;i<dim;++i)
+ dofs_per_cell *= n;
- template <int dim>
- std::vector<unsigned int>
- hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe)
- {
- Assert (fe.n_components() == 1, ExcInvalidFE());
-
- std::vector<unsigned int> h2l (fe.dofs_per_cell);
+ // Assert size maches degree
+ AssertDimension (h2l.size(), dofs_per_cell);
- const unsigned int dofs_per_cell = fe.dofs_per_cell;
// polynomial degree
- const unsigned int degree = fe.dofs_per_line+1;
- // number of grid points in each direction
- const unsigned int n = degree+1;
+ const unsigned int dofs_per_line = degree - 1;
// the following lines of code are somewhat odd, due to the way the
// hierarchic numbering is organized. if someone would really want to
h2l[next_index++] = n*n-1;
// left line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (1+i)*n;
// right line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (2+i)*n-1;
// bottom line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i;
// top line
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*(n-1)+i+1;
// inside quad
- Assert (fe.dofs_per_quad == fe.dofs_per_line*fe.dofs_per_line,
- ExcInternalError());
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = n*(i+1)+j+1;
- Assert (next_index == fe.dofs_per_cell, ExcInternalError());
+ Assert (next_index == dofs_per_cell, ExcInternalError());
break;
}
h2l[next_index++] = (n*n+n+1)*degree; // 7
// line 0
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n;
// line 1
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n;
// line 2
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i;
// line 3
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = 1+i+n*(n-1);
// line 4
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (n-1)*n*n+(i+1)*n;
// line 5
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (n-1)*(n*n+1)+(i+1)*n;
// line 6
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*n*(n-1)+i+1;
// line 7
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n*n*(n-1)+i+1+n*(n-1);
// line 8
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n*n;
// line 9
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n*n;
// line 10
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = (i+1)*n*n+n*(n-1);
// line 11
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
h2l[next_index++] = n-1+(i+1)*n*n+n*(n-1);
// inside quads
- Assert (fe.dofs_per_quad == fe.dofs_per_line*fe.dofs_per_line,
- ExcInternalError());
// face 0
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (i+1)*n*n+n*(j+1);
// face 1
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (i+1)*n*n+n-1+n*(j+1);
// face 2, note the orientation!
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (j+1)*n*n+i+1;
// face 3, note the orientation!
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (j+1)*n*n+n*(n-1)+i+1;
// face 4
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = n*(i+1)+j+1;
// face 5
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
h2l[next_index++] = (n-1)*n*n+n*(i+1)+j+1;
// inside hex
- Assert (fe.dofs_per_hex == fe.dofs_per_quad*fe.dofs_per_line,
- ExcInternalError());
- for (unsigned int i=0; i<fe.dofs_per_line; ++i)
- for (unsigned int j=0; j<fe.dofs_per_line; ++j)
- for (unsigned int k=0; k<fe.dofs_per_line; ++k)
+ for (unsigned int i=0; i<dofs_per_line; ++i)
+ for (unsigned int j=0; j<dofs_per_line; ++j)
+ for (unsigned int k=0; k<dofs_per_line; ++k)
h2l[next_index++] = n*n*(i+1)+n*(j+1)+k+1;
- Assert (next_index == fe.dofs_per_cell, ExcInternalError());
+ Assert (next_index == dofs_per_cell, ExcInternalError());
break;
}
default:
Assert (false, ExcNotImplemented());
}
+ }
- return h2l;
+
+
+ template <int dim>
+ void
+ hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe,
+ std::vector<unsigned int> &h2l)
+ {
+ Assert (h2l.size() == fe.dofs_per_cell,
+ ExcDimensionMismatch (h2l.size(), fe.dofs_per_cell));
+ hierarchic_to_lexicographic_numbering<dim> (fe.dofs_per_line+1, h2l);
}
+ template <int dim>
+ std::vector<unsigned int>
+ hierarchic_to_lexicographic_numbering (const FiniteElementData<dim> &fe)
+ {
+ Assert (fe.n_components() == 1, ExcInvalidFE());
+ std::vector<unsigned int> h2l(fe.dofs_per_cell);
+ hierarchic_to_lexicographic_numbering<dim> (fe.dofs_per_line+1, h2l);
+ return (h2l);
+ }
+
template <int dim>
void
lexicographic_to_hierarchic_numbering (const FiniteElementData<dim> &fe,
FullMatrix<double> &);
#endif
+ template
+ void
+ hierarchic_to_lexicographic_numbering<deal_II_dimension>
+ (unsigned int,
+ std::vector<unsigned int> &);
+
template
void
hierarchic_to_lexicographic_numbering<deal_II_dimension>
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/config.h>
+#include <deal.II/base/tensor_product_polynomials.h>
+#include <deal.II/fe/fe_poly_face.h>
+#include <deal.II/fe/fe_tools.h>
+#include <deal.II/fe/fe_trace.h>
+
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+
+template <int dim, int spacedim>
+FE_TraceQ<dim,spacedim>::FE_TraceQ (const unsigned int degree)
+ :
+ FE_PolyFace<TensorProductPolynomials<dim-1>, dim, spacedim> (
+ TensorProductPolynomials<dim-1>(Polynomials::LagrangeEquidistant::generate_complete_basis(degree)),
+ FiniteElementData<dim>(get_dpo_vector(degree), 1, degree, FiniteElementData<dim>::L2),
+ std::vector<bool>(1,true))
+{
+ Assert (degree > 0,
+ ExcMessage ("FE_Trace can only be used for polynomial degrees "
+ "greater than zero"));
+ std::vector<unsigned int> renumber (this->dofs_per_face);
+ FETools::hierarchic_to_lexicographic_numbering<dim-1> (degree, renumber);
+ this->poly_space.set_numbering(renumber);
+}
+
+
+template <int dim, int spacedim>
+FiniteElement<dim,spacedim>*
+FE_TraceQ<dim,spacedim>::clone() const
+{
+ return new FE_TraceQ<dim,spacedim>(this->degree);
+}
+
+
+template <int dim, int spacedim>
+std::string
+FE_TraceQ<dim,spacedim>::get_name () const
+{
+ // note that the
+ // FETools::get_fe_from_name
+ // function depends on the
+ // particular format of the string
+ // this function returns, so they
+ // have to be kept in synch
+
+ std::ostringstream namebuf;
+ namebuf << "FE_TraceQ<" << dim << ">(" << this->degree << ")";
+
+ return namebuf.str();
+}
+
+template <int dim, int spacedim>
+bool
+FE_TraceQ<dim,spacedim>::has_support_on_face (const unsigned int shape_index,
+ const unsigned int face_index) const
+{
+ Assert (shape_index < this->dofs_per_cell,
+ ExcIndexRange (shape_index, 0, this->dofs_per_cell));
+ Assert (face_index < GeometryInfo<dim>::faces_per_cell,
+ ExcIndexRange (face_index, 0, GeometryInfo<dim>::faces_per_cell));
+
+ // let's see whether this is a
+ // vertex
+ if (shape_index < this->first_line_index)
+ {
+ // for Q elements, there is
+ // one dof per vertex, so
+ // shape_index==vertex_number. check
+ // whether this vertex is
+ // on the given face. thus,
+ // for each face, give a
+ // list of vertices
+ const unsigned int vertex_no = shape_index;
+ Assert (vertex_no < GeometryInfo<dim>::vertices_per_cell,
+ ExcInternalError());
+
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
+ if (GeometryInfo<dim>::face_to_cell_vertices(face_index, v) == vertex_no)
+ return true;
+
+ return false;
+ }
+ else if (shape_index < this->first_quad_index)
+ // ok, dof is on a line
+ {
+ const unsigned int line_index
+ = (shape_index - this->first_line_index) / this->dofs_per_line;
+ Assert (line_index < GeometryInfo<dim>::lines_per_cell,
+ ExcInternalError());
+
+ // in 2d, the line is the
+ // face, so get the line
+ // index
+ if (dim == 2)
+ return (line_index == face_index);
+ else if (dim == 3)
+ {
+ // see whether the
+ // given line is on the
+ // given face.
+ for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
+ if (GeometryInfo<3>::face_to_cell_lines(face_index, l) == line_index)
+ return true;
+
+ return false;
+ }
+ else
+ Assert (false, ExcNotImplemented());
+ }
+ else if (shape_index < this->first_hex_index)
+ // dof is on a quad
+ {
+ const unsigned int quad_index
+ = (shape_index - this->first_quad_index) / this->dofs_per_quad;
+ Assert (static_cast<signed int>(quad_index) <
+ static_cast<signed int>(GeometryInfo<dim>::quads_per_cell),
+ ExcInternalError());
+
+ // in 2d, cell bubble are
+ // zero on all faces. but
+ // we have treated this
+ // case above already
+ Assert (dim != 2, ExcInternalError());
+
+ // in 3d,
+ // quad_index=face_index
+ if (dim == 3)
+ return (quad_index == face_index);
+ else
+ Assert (false, ExcNotImplemented());
+ }
+ else
+ // dof on hex
+ {
+ // can only happen in 3d,
+ // but this case has
+ // already been covered
+ // above
+ Assert (false, ExcNotImplemented());
+ return false;
+ }
+
+ // we should not have gotten here
+ Assert (false, ExcInternalError());
+ return false;
+}
+
+
+
+template <int dim, int spacedim>
+std::pair<Table<2,bool>, std::vector<unsigned int> >
+FE_TraceQ<dim,spacedim>::get_constant_modes () const
+{
+ Table<2,bool> constant_modes(1, this->dofs_per_cell);
+ for (unsigned int i=0; i<this->dofs_per_cell; ++i)
+ constant_modes(0,i) = true;
+ return std::pair<Table<2,bool>, std::vector<unsigned int> >
+ (constant_modes, std::vector<unsigned int>(1, 0));
+}
+
+
+
+template <int dim, int spacedim>
+std::vector<unsigned int>
+FE_TraceQ<dim,spacedim>::get_dpo_vector (const unsigned int deg)
+{
+ AssertThrow(deg>0,ExcMessage("FE_TraceQ needs to be of degree > 0."));
+ std::vector<unsigned int> dpo(dim+1, 1U);
+ dpo[dim]=0;
+ dpo[0]=1;
+ for (unsigned int i=1;i<dim;++i)
+ dpo[i] = dpo[i-1]*(deg-1);
+ return dpo;
+}
+
+// explicit instantiations
+#include "fe_trace.inst"
+
+
+DEAL_II_NAMESPACE_CLOSE
--- /dev/null
+// ---------------------------------------------------------------------
+// $Id$
+//
+// Copyright (C) 2000 - 2013 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+for (deal_II_dimension : DIMENSIONS)
+ {
+#if deal_II_dimension > 1
+ template class FE_TraceQ<deal_II_dimension>;
+#endif
+ }
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
DEAL_II_NAMESPACE_OPEN
-
namespace GridGenerator
{
namespace
template <int dim, int spacedim>
void hyper_cube (Triangulation<dim,spacedim> &tria,
const double left,
- const double right)
+ const double right,
+ const bool colorize)
{
Assert (left < right,
ExcMessage ("Invalid left-to-right bounds of hypercube"));
p1(i) = left;
p2(i) = right;
}
- hyper_rectangle (tria, p1, p2);
+ hyper_rectangle (tria, p1, p2, colorize);
}
cell->face(i)->set_boundary_indicator(1);
for (unsigned int j=0; j<GeometryInfo<3>::lines_per_face; ++j)
{
- const Point<3> vertices[2]
+ const Point<3> line_vertices[2]
= { cell->face(i)->line(j)->vertex(0),
cell->face(i)->line(j)->vertex(1)
};
- if ((std::fabs(vertices[0].distance(center)-radius) >
+ if ((std::fabs(line_vertices[0].distance(center)-radius) >
1e-5*radius)
||
- (std::fabs(vertices[1].distance(center)-radius) >
+ (std::fabs(line_vertices[1].distance(center)-radius) >
1e-5*radius))
cell->face(i)->line(j)->set_boundary_indicator(1);
}
cells.push_back (this_cell);
}
- // throw out duplicated vertices from the two meshes
- // and create the triangulation
+ // throw out duplicated vertices from the two meshes, reorder vertices as
+ // necessary and create the triangulation
SubCellData subcell_data;
std::vector<unsigned int> considered_vertices;
- GridTools::delete_duplicated_vertices (vertices, cells, subcell_data, considered_vertices);
+ GridTools::delete_duplicated_vertices (vertices, cells,
+ subcell_data,
+ considered_vertices);
+
+ // reorder the cells to ensure that they satisfy the convention for
+ // edge and face directions
+ GridReordering<dim, spacedim>::reorder_cells(cells, true);
result.clear ();
result.create_triangulation (vertices, cells, subcell_data);
}
// Implementation for 1D only
template <>
void laplace_transformation (Triangulation<1> &,
- const std::map<unsigned int,Point<1> > &)
+ const std::map<unsigned int,Point<1> > &,
+ const Function<1> *)
{
Assert(false, ExcNotImplemented());
}
// Implementation for dimensions except 1
template <int dim>
void laplace_transformation (Triangulation<dim> &tria,
- const std::map<unsigned int,Point<dim> > &new_points)
+ const std::map<unsigned int,Point<dim> > &new_points,
+ const Function<dim> *coefficient)
{
// first provide everything that is
// needed for solving a Laplace
QGauss<dim> quadrature(4);
- MatrixCreator::create_laplace_matrix(mapping_q1, dof_handler, quadrature, S);
+ MatrixCreator::create_laplace_matrix(mapping_q1, dof_handler, quadrature, S,coefficient);
// set up the boundary values for
// the laplace problem
std::vector<std::map<unsigned int,double> > m(dim);
- typename std::map<unsigned int,Point<dim> >::const_iterator map_iter;
typename std::map<unsigned int,Point<dim> >::const_iterator map_end=new_points.end();
// fill these maps using the data
// given by new_points
typename DoFHandler<dim>::cell_iterator cell=dof_handler.begin_active(),
- endc=dof_handler.end();
- typename DoFHandler<dim>::face_iterator face;
+ endc=dof_handler.end();
for (; cell!=endc; ++cell)
{
- if (cell->at_boundary())
- for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
- {
- face=cell->face(face_no);
- if (face->at_boundary())
- for (unsigned int vertex_no=0;
- vertex_no<GeometryInfo<dim>::vertices_per_face; ++vertex_no)
- {
- const unsigned int vertex_index=face->vertex_index(vertex_no);
- map_iter=new_points.find(vertex_index);
+ for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
+ {
+ const typename DoFHandler<dim>::face_iterator face=cell->face(face_no);
- if (map_iter!=map_end)
- for (unsigned int i=0; i<dim; ++i)
- m[i].insert(std::pair<unsigned int,double> (
- face->vertex_dof_index(vertex_no, 0), map_iter->second(i)));
- }
- }
+ // loop over all vertices of the cell and see if it is listed in the map
+ // given as first argument of the function
+ for (unsigned int vertex_no=0;
+ vertex_no<GeometryInfo<dim>::vertices_per_face; ++vertex_no)
+ {
+ const unsigned int vertex_index=face->vertex_index(vertex_no);
+
+ const typename std::map<unsigned int,Point<dim> >::const_iterator map_iter
+ = new_points.find(vertex_index);
+
+ if (map_iter!=map_end)
+ for (unsigned int i=0; i<dim; ++i)
+ m[i].insert(std::pair<unsigned int,double> (
+ face->vertex_dof_index(vertex_no, 0), map_iter->second(i)));
+ }
+ }
}
// solve the dim problems with
template void
hyper_cube<deal_II_dimension, deal_II_space_dimension> (
- Triangulation<deal_II_dimension, deal_II_space_dimension> &, const double, const double);
+ Triangulation<deal_II_dimension, deal_II_space_dimension> &, const double, const double, const bool);
template
void
#if deal_II_dimension > 1
template void
laplace_transformation<deal_II_dimension> (Triangulation<deal_II_dimension> &,
- const std::map<unsigned int,Point<deal_II_dimension> > &);
+ const std::map<unsigned int,Point<deal_II_dimension> > &,
+ const Function<deal_II_dimension> *);
#endif
\}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1999 - 2013 by the deal.II authors
+// Copyright (C) 1999 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
{
Assert((dim == 2)||(dim == 3), ExcNotImplemented());
std::string line;
- std::string text[4];
- text[0] = "# vtk DataFile Version 3.0";
- text[1] = "vtk output";
- text[2] = "ASCII";
- text[3] = "DATASET UNSTRUCTURED_GRID";
- for (unsigned int i = 0; i < 4; i++) //Checking for the match between initial strings/text in the file.
+ // verify that the first, third and fourth lines match
+ // expectations. the second line of the file may essentially be
+ // anything the author of the file chose to identify what's in
+ // there, so we just ensure that we can read it
+ {
+ std::string text[4];
+ text[0] = "# vtk DataFile Version 3.0";
+ text[1] = "****";
+ text[2] = "ASCII";
+ text[3] = "DATASET UNSTRUCTURED_GRID";
+
+ for (unsigned int i = 0; i < 4; ++i)
{
getline(in,line);
-
- AssertThrow (line.compare(text[i]) == 0,
- ExcMessage(std::string("While reading VTK file, failed to find <") +
- text[i] + ">"));
+ if (i != 1)
+ AssertThrow (line.compare(text[i]) == 0,
+ ExcMessage(std::string("While reading VTK file, failed to find a header line with text <") +
+ text[i] + ">"));
}
+ }
///////////////////Declaring storage and mappings//////////////////
std::map<int, int> quad_indices; // # quad in unv (key) ---> # quad in deal.II (value)
std::map<int, int> line_indices; // # line in unv(key) ---> # line in deal.II (value)
- unsigned int no_vertices, no_quads=0,no_lines=0;
+ unsigned int no_vertices, no_quads=0, no_lines=0;
std::string keyword;
in >> keyword;
- unsigned int total_cells, no_cells = 0, type, j = 0;// declaring counters, refer to the order of declaring variables for an idea of what is what!
+ unsigned int total_cells, no_cells = 0, type;// declaring counters, refer to the order of declaring variables for an idea of what is what!
///////////////////Processing the CELLS section that contains cells(cells) and bound_quads(subcelldata)///////////////////////
cells.push_back(CellData<dim>());
- for (j = 0; j < type; j++) //loop to feed data
+ for (unsigned int j = 0; j < type; j++) //loop to feed data
in >> cells.back().vertices[j];
+
cells.back().material_id = 0;
- for (j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
{
cells.back().vertices[j] = vertex_indices[cells.back().vertices[j]];
}
{
subcelldata.boundary_quads.push_back(CellData<2>());
- int no_quads = 0;
- for (j = 0; j < type; j++) //loop to feed the data to the boundary
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data to the boundary
{
in >> subcelldata.boundary_quads.back().vertices[j];
}
{
subcelldata.boundary_quads.back().vertices[j] = vertex_indices[subcelldata.boundary_quads.back().vertices[j]];
}
- quad_indices[count] = count + 1;
+ quad_indices[no_quads] = no_quads + 1;
no_quads++;
}
{
cells.push_back(CellData<dim>());
- for (j = 0; j < type; j++) //loop to feed data
+ for (unsigned int j = 0; j < type; j++) //loop to feed data
in >> cells.back().vertices[j];
cells.back().material_id = 0;
- for (j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data of the vertices to the cell
{
cells.back().vertices[j] = vertex_indices[cells.back().vertices[j]];
}
//If this is encountered, the pointer comes out of the loop
//and starts processing boundaries.
subcelldata.boundary_lines.push_back(CellData<1>());
- int no_lines = 0;
- for (j = 0; j < type; j++) //loop to feed the data to the boundary
+ for (unsigned int j = 0; j < type; j++) //loop to feed the data to the boundary
{
in >> subcelldata.boundary_lines.back().vertices[j];
}
{
subcelldata.boundary_lines.back().vertices[j] = vertex_indices[subcelldata.boundary_lines.back().vertices[j]];
}
- line_indices[count] = count + 1;
+ line_indices[no_lines] = no_lines + 1;
no_lines++;
}
for (unsigned int i = 0; i < 2; i++)
{
- getline(in,linenew);
-
- if (linenew.compare(textnew[i]) == 0)
- {}
- else
- AssertThrow (false,
- ExcMessage (std::string("While reading VTK file, failed to find <") +
- textnew[i] + "> section"));
+ getline(in, linenew);
+ if (i == 0)
+ if (linenew.size() > textnew[0].size())
+ linenew.resize(textnew[0].size());
+
+ AssertThrow (linenew.compare(textnew[i]) == 0,
+ ExcMessage (std::string("While reading VTK file, failed to find <") +
+ textnew[i] + "> section"));
}
for (unsigned int i = 0; i < no_cells; i++) //assigning IDs to cells.
}
}
}
- else
- AssertThrow (false,
- ExcMessage ("While reading VTK file, failed to find CELL_DATA section"));
-
Assert(subcelldata.check_consistency(dim), ExcInternalError());
const unsigned int n_lines = (n_entities%2 == 0)?(n_entities/2):((n_entities+1)/2);
- for (unsigned int no_line = 0; no_line < n_lines; no_line++)
+ for (unsigned int line = 0; line < n_lines; line++)
{
unsigned int n_fragments;
- if (no_line == n_lines-1)
+ if (line == n_lines-1)
n_fragments = (n_entities%2 == 0)?(2):(1);
else
n_fragments = 2;
AssertThrow(n_vars>=dim,
ExcMessage("Tecplot file must contain at least one variable for each dimension"));
- for (unsigned int i=1; i<dim; ++i)
- AssertThrow(tecplot2deal[i]>0,
+ for (unsigned int d=1; d<dim; ++d)
+ AssertThrow(tecplot2deal[d]>0,
ExcMessage("Tecplot file must contain at least one variable for each dimension."));
}
else if (Utilities::match_at_string_start(entries[i],"ZONETYPE=ORDERED"))
#include <deal.II/grid/grid_out.h>
#include <deal.II/base/parameter_handler.h>
+#include <deal.II/base/exceptions.h>
#include <deal.II/base/point.h>
#include <deal.II/base/quadrature.h>
#include <deal.II/base/qprojector.h>
const bool label_material_id,
const bool label_subdomain_id,
const bool draw_colorbar,
- const bool draw_legend) :
- line_thickness(line_thickness),
- boundary_line_thickness(boundary_line_thickness),
- margin(margin),
- background(background),
- azimuth_angle(azimuth_angle),
- polar_angle(polar_angle),
- coloring(coloring),
- convert_level_number_to_height(convert_level_number_to_height),
- label_level_number(label_level_number),
- label_cell_index(label_cell_index),
- label_material_id(label_material_id),
- label_subdomain_id(label_subdomain_id),
- label_level_subdomain_id(false),
- draw_colorbar(draw_colorbar),
- draw_legend(draw_legend)
+ const bool draw_legend)
+ :
+ height(1000),
+ width(0),
+ line_thickness(line_thickness),
+ boundary_line_thickness(boundary_line_thickness),
+ margin(margin),
+ background(background),
+ azimuth_angle(azimuth_angle),
+ polar_angle(polar_angle),
+ coloring(coloring),
+ convert_level_number_to_height(convert_level_number_to_height),
+ level_height_factor(0.3f),
+ label_level_number(label_level_number),
+ label_cell_index(label_cell_index),
+ label_material_id(label_material_id),
+ label_subdomain_id(label_subdomain_id),
+ label_level_subdomain_id(false),
+ draw_colorbar(draw_colorbar),
+ draw_legend(draw_legend)
{}
MathGL::MathGL ()
{
draw_bounding_box = param.get_bool ("Draw bounding box");
}
-
} // end namespace GridOutFlags
mathgl_flags = flags;
}
+void GridOut::set_flags (const GridOutFlags::Vtk &flags)
+{
+ vtk_flags = flags;
+}
+
+void GridOut::set_flags (const GridOutFlags::Vtu &flags)
+{
+ vtu_flags = flags;
+}
+
std::string
GridOut::default_suffix (const OutputFormat output_format)
{
return ".svg";
case mathgl:
return ".mathgl";
+ case vtk:
+ return ".vtk";
+ case vtu:
+ return ".vtu";
default:
Assert (false, ExcNotImplemented());
return "";
if (format_name == "mathgl")
return mathgl;
+ if (format_name == "vtk")
+ return vtk;
+
+ if (format_name == "vtu")
+ return vtu;
+
AssertThrow (false, ExcInvalidState ());
// return something weird
return OutputFormat(-1);
std::string GridOut::get_output_format_names ()
{
- return "none|dx|gnuplot|eps|ucd|xfig|msh|svg|mathgl";
+ return "none|dx|gnuplot|eps|ucd|xfig|msh|svg|mathgl|vtk|vtu";
}
param.enter_subsection("MathGL");
GridOutFlags::MathGL::declare_parameters(param);
param.leave_subsection();
+
+ param.enter_subsection("Vtk");
+ GridOutFlags::Vtk::declare_parameters(param);
+ param.leave_subsection();
+
+ param.enter_subsection("Vtu");
+ GridOutFlags::Vtu::declare_parameters(param);
+ param.leave_subsection();
}
param.enter_subsection("MathGL");
mathgl_flags.parse_parameters(param);
param.leave_subsection();
+
+ param.enter_subsection("Vtk");
+ vtk_flags.parse_parameters(param);
+ param.leave_subsection();
+
+ param.enter_subsection("Vtu");
+ vtu_flags.parse_parameters(param);
+ param.leave_subsection();
}
sizeof(eps_flags_3) +
sizeof(xfig_flags) +
sizeof(svg_flags) +
- sizeof(mathgl_flags));
+ sizeof(mathgl_flags) +
+ sizeof(vtk_flags) +
+ sizeof(vtu_flags));
}
// grid to 4000 and adapt the number of width
// elements with respect to the bounding box of
// the given triangulation.
- const unsigned int height = 4000; // TODO [CW]: consider other options, especially if the polar angle approaches 90°
- unsigned int width;
+ unsigned int height = svg_flags.height;
+ unsigned int width = svg_flags.width;
+ Assert (height != 0 || width != 0, ExcMessage("You have to set at least one of width and height"));
unsigned int margin_in_percent = 0;
if (svg_flags.margin || svg_flags.background == GridOutFlags::Svg::dealii)
// initial font size for cell labels
unsigned int cell_label_font_size;
- // font size for date, time, legend, and colorbar
- unsigned int font_size = static_cast<unsigned int>(.5 + (height/100.) * 1.75);
-
// get date and time
// time_t time_stamp;
// tm *now;
float x_dimension_perspective, y_dimension_perspective;
- Triangulation<2,2>::cell_iterator cell = tria.begin(), endc = tria.end();
-
// auxiliary variables for the bounding box and the range of cell levels
- double x_min = cell->vertex(0)[0];
- double x_max = cell->vertex(0)[0];
- double y_min = cell->vertex(0)[1];
- double y_max = cell->vertex(0)[1];
+ double x_min = tria.begin()->vertex(0)[0];
+ double x_max = tria.begin()->vertex(0)[0];
+ double y_min = tria.begin()->vertex(0)[1];
+ double y_max = tria.begin()->vertex(0)[1];
double x_dimension, y_dimension;
- min_level = cell->level();
- max_level = cell->level();
+ min_level = max_level = tria.begin()->level();
// auxiliary array for the materials being used (material ids 255 max.)
unsigned int materials[256];
// bounding box of the given triangulation and check
// the cells for material id, level number, subdomain id
// (, and level subdomain id).
- for (; cell != endc; ++cell)
+ for (Triangulation<2,2>::cell_iterator cell = tria.begin(); cell != tria.end(); ++cell)
{
for (unsigned int vertex_index = 0; vertex_index < 4; vertex_index++)
{
// determine the bounding box of the given triangulation on the projection plane of the camera viewing system
- cell = tria.begin();
- endc = tria.end();
-
- point[0] = cell->vertex(0)[0];
- point[1] = cell->vertex(0)[1];
+ point[0] = tria.begin()->vertex(0)[0];
+ point[1] = tria.begin()->vertex(0)[1];
point[2] = 0;
float min_level_min_vertex_distance = 0;
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)tria.begin()->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
y_max_perspective = projection_decomposition[1];
y_min_perspective = projection_decomposition[1];
- for (; cell != endc; ++cell)
+ for (Triangulation<2,2>::cell_iterator cell = tria.begin(); cell != tria.end(); ++cell)
{
point[0] = cell->vertex(0)[0];
point[1] = cell->vertex(0)[1];
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
x_dimension_perspective = x_max_perspective - x_min_perspective;
y_dimension_perspective = y_max_perspective - y_min_perspective;
- cell_label_font_size = static_cast<unsigned int>((int)(.5 + (height/100.) * 2.75) * 9. * (min_level_min_vertex_distance / std::min(x_dimension, y_dimension)));
-
-
// create the svg file with an internal style sheet
- width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
+ if (width == 0)
+ width = static_cast<unsigned int>(.5 + height * (x_dimension_perspective / y_dimension_perspective));
+ else if (height == 0)
+ height = static_cast<unsigned int>(.5 + width * (y_dimension_perspective / x_dimension_perspective));
unsigned int additional_width = 0;
+ // font size for date, time, legend, and colorbar
+ unsigned int font_size = static_cast<unsigned int>(.5 + (height/100.) * 1.75);
+ cell_label_font_size = static_cast<unsigned int>((int)(.5 + (height/100.) * 2.75) * 9. * (min_level_min_vertex_distance / std::min(x_dimension, y_dimension)));
if (svg_flags.draw_legend && (svg_flags.label_level_number || svg_flags.label_cell_index || svg_flags.label_material_id || svg_flags.label_subdomain_id || svg_flags.label_level_subdomain_id ))
{
out << "]]></style>" << '\n' << '\n';
// background rectangle
- out << " <rect class=\"background\" width=\"" << width + additional_width << "\" height=\"" << height << "\"/>" << '\n';
+ out << " <rect class=\"background\" width=\"" << width << "\" height=\"" << height << "\"/>" << '\n';
if (svg_flags.background == GridOutFlags::Svg::dealii)
{
for (unsigned int level_index = min_level; level_index <= max_level; level_index++)
{
- Triangulation<2,2>::cell_iterator cell = tria.begin(level_index), endc = tria.end(level_index);
+ Triangulation<2,2>::cell_iterator
+ cell = tria.begin(level_index),
+ endc = tria.end(level_index);
for (; cell != endc; ++cell)
{
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
float distance_to_camera = sqrt(pow(point[0] - camera_position[0], 2.) + pow(point[1] - camera_position[1], 2.) + pow(point[2] - camera_position[2], 2.));
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
if (svg_flags.convert_level_number_to_height)
{
- point[2] = .3 * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
+ point[2] = svg_flags.level_height_factor * ((float)cell->level() / (float)n_levels) * std::max(x_dimension, y_dimension);
}
projection_decomposition = GridOut::svg_project_point(point, camera_position, camera_direction, camera_horizontal, camera_focus);
}
+
+namespace
+{
+ /**
+ * A function that is able to convert each cell of a triangulation into
+ * a patch that can then be output by the functions in DataOutBase.
+ * This is made particularly simple because the patch only needs to
+ * contain geometry info -- we attach no data at all
+ */
+ template <int dim, int spacedim>
+ std::vector<DataOutBase::Patch<dim,spacedim> >
+ triangulation_to_patches (const Triangulation<dim,spacedim> &triangulation)
+ {
+ std::vector<DataOutBase::Patch<dim,spacedim> > patches;
+ patches.reserve (triangulation.n_active_cells());
+
+ // convert each of the active cells into a patch
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell)
+ {
+ DataOutBase::Patch<dim,spacedim> patch;
+ patch.n_subdivisions = 1;
+
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ patch.vertices[v] = cell->vertex(v);
+
+ // no data
+ patch.data.reinit (0,0);
+
+ patches.push_back (patch);
+ }
+
+ return patches;
+ }
+}
+
+
+
+template <int dim, int spacedim>
+void GridOut::write_vtk (const Triangulation<dim,spacedim> &tria,
+ std::ostream &out) const
+{
+ AssertThrow (out, ExcIO ());
+
+ // convert the cells of the triangulation into a set of patches
+ // and then have them output. since there is no data attached to
+ // the geometry, we also do not have to provide any names, identifying
+ // information, etc.
+ DataOutBase::write_vtk (triangulation_to_patches(tria),
+ std::vector<std::string>(),
+ std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >(),
+ vtk_flags,
+ out);
+
+ AssertThrow (out, ExcIO ());
+}
+
+
+
+template <int dim, int spacedim>
+void GridOut::write_vtu (const Triangulation<dim,spacedim> &tria,
+ std::ostream &out) const
+{
+ AssertThrow (out, ExcIO ());
+
+ // convert the cells of the triangulation into a set of patches
+ // and then have them output. since there is no data attached to
+ // the geometry, we also do not have to provide any names, identifying
+ // information, etc.
+ DataOutBase::write_vtu (triangulation_to_patches(tria),
+ std::vector<std::string>(),
+ std::vector<std_cxx1x::tuple<unsigned int, unsigned int, std::string> >(),
+ vtu_flags,
+ out);
+
+ AssertThrow (out, ExcIO ());
+}
+
+
+
unsigned int GridOut::n_boundary_faces (const Triangulation<1> &) const
{
return 0;
case 2:
{
- typename dealii::Triangulation<dim>::active_cell_iterator
- cell=tria.begin_active(),
- endc=tria.end();
-
- for (; cell!=endc; ++cell)
+ for (typename dealii::Triangulation<dim>::active_cell_iterator
+ cell=tria.begin_active();
+ cell!=tria.end(); ++cell)
for (unsigned int line_no=0;
line_no<GeometryInfo<dim>::lines_per_cell; ++line_no)
{
// boundary faces and
// generate the info from
// them
- typename dealii::Triangulation<dim>::active_cell_iterator
- cell=tria.begin_active ();
- const typename dealii::Triangulation<dim>::active_cell_iterator
- end=tria.end ();
- for (; cell!=end; ++cell)
+ for (typename dealii::Triangulation<dim>::active_cell_iterator
+ cell=tria.begin_active();
+ cell!=tria.end(); ++cell)
for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
{
const typename dealii::Triangulation<dim>::face_iterator
case mathgl:
write_mathgl (tria, out);
return;
+
+ case vtk:
+ write_vtk (tria, out);
+ return;
+
+ case vtu:
+ write_vtu (tria, out);
+ return;
}
Assert (false, ExcInternalError());
template <int dim, int spacedim>
-void GridOut::write (
- const Triangulation<dim, spacedim> &tria,
- std::ostream &out,
- const Mapping<dim,spacedim> *mapping) const
+void GridOut::write (const Triangulation<dim, spacedim> &tria,
+ std::ostream &out,
+ const Mapping<dim,spacedim> *mapping) const
{
write(tria, out, default_format, mapping);
}
(const Triangulation<deal_II_dimension> &,
std::ostream &,
const Mapping<deal_II_dimension,deal_II_dimension> *) const;
+ template void GridOut::write_vtk
+ (const Triangulation<deal_II_dimension>&,
+ std::ostream&) const;
+ template void GridOut::write_vtu
+ (const Triangulation<deal_II_dimension>&,
+ std::ostream&) const;
+
template void GridOut::write<deal_II_dimension>
(const Triangulation<deal_II_dimension> &,
std::ostream &, const OutputFormat,
(const Triangulation<deal_II_dimension,deal_II_dimension+1>&,
std::ostream&,
const Mapping<deal_II_dimension,deal_II_dimension+1>*) const;
+ template void GridOut::write_vtk
+ (const Triangulation<deal_II_dimension,deal_II_dimension+1>&,
+ std::ostream&) const;
+ template void GridOut::write_vtu
+ (const Triangulation<deal_II_dimension,deal_II_dimension+1>&,
+ std::ostream&) const;
#endif
#if deal_II_dimension == 3
template void GridOut::write_ucd
template<>
void
-GridReordering<1>::reorder_cells (std::vector<CellData<1> > &)
+GridReordering<1>::reorder_cells (std::vector<CellData<1> > &,
+ const bool)
{
// there should not be much to do
// in 1d...
template<>
void
-GridReordering<1,2>::reorder_cells (std::vector<CellData<1> > &)
+GridReordering<1,2>::reorder_cells (std::vector<CellData<1> > &,
+ const bool)
{
// there should not be much to do
// in 1d...
template<>
void
-GridReordering<1,3>::reorder_cells (std::vector<CellData<1> > &)
+GridReordering<1,3>::reorder_cells (std::vector<CellData<1> > &,
+ const bool)
{
// there should not be much to do
// in 1d...
} // namespace internal
+// anonymous namespace for internal helper functions
+namespace
+{
+ /**
+ * A set of three functions that
+ * reorder the data from the
+ * "current" to the "classic"
+ * format of vertex numbering of
+ * cells and faces. These functions
+ * do the reordering of their
+ * arguments in-place.
+ */
+ void
+ reorder_new_to_old_style (const std::vector<CellData<1> > &)
+ {
+ // nothing to do here: the format
+ // hasn't changed for 1d
+ }
+
+
+ void
+ reorder_new_to_old_style (std::vector<CellData<2> > &cells)
+ {
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ std::swap(cells[cell].vertices[2], cells[cell].vertices[3]);
+ }
+
+
+ void
+ reorder_new_to_old_style (std::vector<CellData<3> > &cells)
+ {
+ unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ tmp[i] = cells[cell].vertices[i];
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ cells[cell].vertices[i] = tmp[GeometryInfo<3>::ucd_to_deal[i]];
+ }
+ }
+
+
+ /**
+ * And now also in the opposite direction.
+ */
+ void
+ reorder_old_to_new_style (const std::vector<CellData<1> > &)
+ {
+ // nothing to do here: the format
+ // hasn't changed for 1d
+ }
+
+
+ void
+ reorder_old_to_new_style (std::vector<CellData<2> > &cells)
+ {
+ // just invert the permutation:
+ reorder_new_to_old_style(cells);
+ }
+
+
+ void
+ reorder_old_to_new_style (std::vector<CellData<3> > &cells)
+ {
+ // undo the ordering above
+ unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
+ for (unsigned int cell=0; cell<cells.size(); ++cell)
+ {
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ tmp[i] = cells[cell].vertices[i];
+ for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
+ cells[cell].vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
+ }
+ }
+}
template<>
void
-GridReordering<2>::reorder_cells (std::vector<CellData<2> > &original_cells)
+GridReordering<2>::reorder_cells (std::vector<CellData<2> > &cells,
+ const bool use_new_style_ordering)
{
+ // if necessary, convert to old-style format
+ if (use_new_style_ordering)
+ reorder_new_to_old_style(cells);
+
// check if grids are already
// consistent. if so, do
// nothing. if not, then do the
// reordering
- if (internal::GridReordering2d::is_consistent (original_cells))
- return;
+ if (!internal::GridReordering2d::is_consistent (cells))
+ internal::GridReordering2d::GridReordering().reorient(cells);
- internal::GridReordering2d::GridReordering().reorient(original_cells);
+
+ // and convert back if necessary
+ if (use_new_style_ordering)
+ reorder_old_to_new_style(cells);
}
template<>
void
-GridReordering<2,3>::reorder_cells (std::vector<CellData<2> > &original_cells)
+GridReordering<2,3>::reorder_cells (std::vector<CellData<2> > &cells,
+ const bool use_new_style_ordering)
{
- GridReordering<2>::reorder_cells(original_cells);
+ // if necessary, convert to old-style format
+ if (use_new_style_ordering)
+ reorder_new_to_old_style(cells);
+
+ GridReordering<2>::reorder_cells(cells);
+
+
+ // and convert back if necessary
+ if (use_new_style_ordering)
+ reorder_old_to_new_style(cells);
}
// rotation to get the new
// cube
unsigned int temp[8];
- for (unsigned int i=0; i<8; ++i)
- temp[i] = the_cell.nodes[CubePermutations[perm_num][i]];
- for (unsigned int i=0; i<8; ++i)
- the_cell.nodes[i] = temp[i];
+ for (unsigned int v=0; v<8; ++v)
+ temp[v] = the_cell.nodes[CubePermutations[perm_num][v]];
+ for (unsigned int v=0; v<8; ++v)
+ the_cell.nodes[v] = temp[v];
}
}
} // namespace GridReordering3d
template<>
void
-GridReordering<3>::reorder_cells (std::vector<CellData<3> > &incubes)
+GridReordering<3>::reorder_cells (std::vector<CellData<3> > &cells,
+ const bool use_new_style_ordering)
{
+ Assert (cells.size() != 0,
+ ExcMessage("List of elements to orient must have at least one cell"));
- Assert (incubes.size() != 0,
- ExcMessage("List of elements to orient was of zero length"));
+ // if necessary, convert to old-style format
+ if (use_new_style_ordering)
+ reorder_new_to_old_style(cells);
// create a backup to use if GridReordering
// was not successful
- std::vector<CellData<3> > backup=incubes;
+ std::vector<CellData<3> > backup=cells;
// This does the real work
- bool success=
- internal::GridReordering3d::Orienter::orient_mesh (incubes);
+ const bool success=
+ internal::GridReordering3d::Orienter::orient_mesh (cells);
// if reordering was not successful use
- // original connectivity, otherwiese do
+ // original connectivity, otherwise do
// nothing (i.e. use the reordered
// connectivity)
if (!success)
- incubes=backup;
+ cells=backup;
+
+ // and convert back if necessary
+ if (use_new_style_ordering)
+ reorder_old_to_new_style(cells);
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2001 - 2013 by the deal.II authors
+// Copyright (C) 2001 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
for (unsigned int j=i+1; j<considered_vertices.size(); ++j)
{
bool equal=true;
- for (unsigned int d=0; d<dim; ++d)
+ for (unsigned int d=0; d<spacedim; ++d)
equal &= (fabs(vertices[considered_vertices[j]](d)-vertices[considered_vertices[i]](d))<tol);
if (equal)
{
template <int dim>
void
laplace_transform (const std::map<unsigned int,Point<dim> > &new_points,
- Triangulation<dim> &triangulation)
+ Triangulation<dim> &triangulation,
+ const Function<dim> *coefficient)
{
//TODO: Move implementation of this function into the current
// namespace
- GridGenerator::laplace_transformation(triangulation, new_points);
+ GridGenerator::laplace_transformation(triangulation, new_points, coefficient);
}
const Container<dim,spacedim> &container,
const Point<spacedim> &p)
{
- typedef typename Container<dim,spacedim>::active_cell_iterator cell_iterator;
+ typedef typename Container<dim,spacedim>::active_cell_iterator active_cell_iterator;
// The best distance is set to the
// maximum allowable distance from
// max. deviation of 1e-10
double best_distance = 1e-10;
int best_level = -1;
- std::pair<cell_iterator, Point<dim> > best_cell;
+ std::pair<active_cell_iterator, Point<dim> > best_cell;
// Find closest vertex and determine
// all adjacent cells
- unsigned int vertex = find_closest_vertex(container, p);
-
- std::vector<cell_iterator> adjacent_cells_tmp =
- find_cells_adjacent_to_vertex(container, vertex);
+ std::vector<active_cell_iterator> adjacent_cells_tmp
+ = find_cells_adjacent_to_vertex(container,
+ find_closest_vertex(container, p));
// Make sure that we have found
// at least one cell adjacent to vertex.
Assert(adjacent_cells_tmp.size()>0, ExcInternalError());
// Copy all the cells into a std::set
- std::set<cell_iterator> adjacent_cells(adjacent_cells_tmp.begin(), adjacent_cells_tmp.end());
- std::set<cell_iterator> searched_cells;
+ std::set<active_cell_iterator> adjacent_cells (adjacent_cells_tmp.begin(),
+ adjacent_cells_tmp.end());
+ std::set<active_cell_iterator> searched_cells;
// Determine the maximal number of cells
// in the grid.
// the cell and have not searched
// every cell in the triangulation,
// we keep on looking.
- const unsigned int n_cells =get_tria(container).n_cells();
+ const unsigned int n_active_cells = get_tria(container).n_active_cells();
bool found = false;
unsigned int cells_searched = 0;
- while (!found && cells_searched < n_cells)
+ while (!found && cells_searched < n_active_cells)
{
- typename std::set<cell_iterator>::const_iterator
+ typename std::set<active_cell_iterator>::const_iterator
cell = adjacent_cells.begin(),
endc = adjacent_cells.end();
for (; cell != endc; ++cell)
// unit cell (or at least not too far
// outside). If it is, it is also checked
// that the cell has a more refined state
- if (dist < best_distance ||
- (dist == best_distance && (*cell)->level() > best_level))
+ if ((dist < best_distance)
+ ||
+ ((dist == best_distance)
+ &&
+ ((*cell)->level() > best_level)))
{
- found = true;
+ found = true;
best_distance = dist;
best_level = (*cell)->level();
best_cell = std::make_pair(*cell, p_cell);
// to the next
}
}
- //udpate the number of cells searched
+
+ // update the number of cells searched
cells_searched += adjacent_cells.size();
+
// if we have not found the cell in
// question and have not yet searched every
// cell, we expand our search to
// all the not already searched neighbors of
// the cells in adjacent_cells. This is
- // what find_active_cell_around_poin_internal
+ // what find_active_cell_around_point_internal
// is for.
- if (!found && cells_searched < n_cells)
+ if (!found && cells_searched < n_active_cells)
{
- find_active_cell_around_point_internal(container, searched_cells, adjacent_cells);
+ find_active_cell_around_point_internal<dim,Container,spacedim>
+ (container, searched_cells, adjacent_cells);
}
}
// the cells in adjacent_cells.
if (!found && cells_searched < n_cells)
{
- find_active_cell_around_point_internal(container, searched_cells, adjacent_cells);
+ find_active_cell_around_point_internal<dim,hp::DoFHandler,spacedim>
+ (container, searched_cells, adjacent_cells);
}
}
do
{
bool changed = false;
- typename Container<dim-1,spacedim>::active_cell_iterator
- cell = surface_mesh.begin_active(),
- endc = surface_mesh.end();
- for (; cell!=endc; ++cell)
+ for (typename Container<dim-1,spacedim>::active_cell_iterator
+ cell = surface_mesh.begin_active(); cell!=surface_mesh.end(); ++cell)
if (surface_to_volume_mapping[cell]->has_children() == true )
{
cell->set_refine_flag ();
const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
.execute_coarsening_and_refinement();
- typename Container<dim-1,spacedim>::cell_iterator
- cell = surface_mesh.begin(),
- endc = surface_mesh.end();
- for (; cell!=endc; ++cell)
- for (unsigned int c=0; c<cell->n_children(); c++)
- if (surface_to_volume_mapping.find(cell->child(c)) == surface_to_volume_mapping.end())
- surface_to_volume_mapping[cell->child(c)]
- = surface_to_volume_mapping[cell]->child(c);
+ for (typename Container<dim-1,spacedim>::cell_iterator
+ surface_cell = surface_mesh.begin(); surface_cell!=surface_mesh.end(); ++surface_cell)
+ for (unsigned int c=0; c<surface_cell->n_children(); c++)
+ if (surface_to_volume_mapping.find(surface_cell->child(c)) == surface_to_volume_mapping.end())
+ surface_to_volume_mapping[surface_cell->child(c)]
+ = surface_to_volume_mapping[surface_cell]->child(c);
}
else
break;
template
void
laplace_transform (const std::map<unsigned int,Point<deal_II_dimension> > &new_points,
- Triangulation<deal_II_dimension> &triangulation);
+ Triangulation<deal_II_dimension> &triangulation,
+ const Function<deal_II_dimension> *coefficient);
template
Triangulation<deal_II_dimension,deal_II_space_dimension>::DistortedCellList
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// not implemented at
// present for dim=3 or
// higher
+ // TODO: you can steal the code to do this from GridTools::transform()
Assert (dim<=2, ExcNotImplemented());
// compute where the common
ExcTooFewVerticesAllocated());
// first insert new
- // vertex. if dim==spacedim
- // then simply use the
- // midpoint; otherwise we
- // have to ask the manifold
- // object
+ // vertex. We always ask the manifold.
get_default_points_and_weights(sp, wp, cell);
triangulation.vertices[next_unused_vertex] =
for (unsigned int q=0; q<triangulation.faces->quads.cells.size(); ++q)
for (unsigned int l=0; l<GeometryInfo<dim>::lines_per_face; ++l)
{
- const int index=triangulation.faces->quads.cells[q].face(l);
- if (index==old_index_0)
+ const int this_index=triangulation.faces->quads.cells[q].face(l);
+ if (this_index==old_index_0)
triangulation.faces->quads.cells[q].set_face(l,new_index_0);
- else if (index==old_index_1)
+ else if (this_index==old_index_1)
triangulation.faces->quads.cells[q].set_face(l,new_index_1);
}
// now we have to copy
for (unsigned int h=0; h<triangulation.levels[l]->cells.cells.size(); ++h)
for (unsigned int q=0; q<GeometryInfo<dim>::faces_per_cell; ++q)
{
- const int index=triangulation.levels[l]->cells.cells[h].face(q);
- if (index==switch_1_index)
+ const int face_index=triangulation.levels[l]->cells.cells[h].face(q);
+ if (face_index==switch_1_index)
triangulation.levels[l]->cells.cells[h].set_face(q,switch_2_index);
- else if (index==switch_2_index)
+ else if (face_index==switch_2_index)
triangulation.levels[l]->cells.cells[h].set_face(q,switch_1_index);
}
// now we have to copy
// the domain, so we need not
// care about boundary quads
// here
- get_default_points_and_weights(sp, wp, middle_line);
- triangulation.vertices[next_unused_vertex] =
- middle_line->get_manifold().get_new_point(sp, wp);
+ get_default_points_and_weights(sp, wp, middle_line);
+ triangulation.vertices[next_unused_vertex] =
+ middle_line->get_manifold().get_new_point(sp, wp);
triangulation.vertices_used[next_unused_vertex] = true;
// at the outset of the
// next iteration) for
// refinement
- for (unsigned int line=0;
- line<GeometryInfo<dim>::lines_per_cell; ++line)
- if (!cell->line(line)->has_children() &&
+ for (unsigned int l=0;
+ l<GeometryInfo<dim>::lines_per_cell; ++l)
+ if (!cell->line(l)->has_children() &&
(GeometryInfo<dim>::line_refinement_case(cell->refine_flag_set(),
- line)
+ l)
!=RefinementCase<1>::no_refinement))
- cell->line(line)->set_user_flag();
+ cell->line(l)->set_user_flag();
break;
}
}
-
template <int dim, int spacedim>
void
Triangulation<dim, spacedim>::set_manifold (const types::manifold_id m_number,
{
//look, if there is a manifold stored at
//manifold_id number.
- typename std::map<types::manifold_id, SmartPointer<const Manifold<spacedim>, Triangulation<dim, spacedim> > >::const_iterator it
+ typename std::map<types::manifold_id,
+ SmartPointer<const Manifold<spacedim>, Triangulation<dim, spacedim> > >::const_iterator it
= manifold.find(m_number);
if (it != manifold.end())
}
else
{
-//TODO: if boundary_id_t is a real integer type, this might become
-//a humongously large array...
- std::vector<bool> bi_exists(numbers::internal_face_boundary_id, false);
+ std::set<types::boundary_id> b_ids;
active_cell_iterator cell=begin_active();
for (; cell!=end(); ++cell)
for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
if (cell->at_boundary(face))
- bi_exists[cell->face(face)->boundary_indicator()]=true;
-
- const unsigned int n_bi=
- std::count(bi_exists.begin(), bi_exists.end(), true);
-
- std::vector<types::boundary_id> boundary_indicators(n_bi);
- unsigned int bi_counter=0;
- for (unsigned int i=0; i<bi_exists.size(); ++i)
- if (bi_exists[i]==true)
- boundary_indicators[bi_counter++]=i;
-
+ b_ids.insert(cell->face(face)->boundary_indicator());
+ std::vector<types::boundary_id> boundary_indicators(b_ids.begin(), b_ids.end());
return boundary_indicators;
}
}
std::vector<types::manifold_id>
Triangulation<dim, spacedim>::get_manifold_ids () const
{
-//TODO: if manifold_id_t is a real integer type, this might become
-//a humongously large array...
- // Just store all possible values
- std::vector<bool> mi_exists(numbers::invalid_manifold_id+1, false);
+ std::set<types::manifold_id> m_ids;
active_cell_iterator cell=begin_active();
- for (; cell!=end(); ++cell)
- {
- mi_exists[cell->manifold_id()] = true;
- if(dim>1)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- mi_exists[cell->face(face)->manifold_id()]=true;
- }
-
- const unsigned int n_mi=
- std::count(mi_exists.begin(), mi_exists.end(), true)-1;
-
- std::vector<types::manifold_id> manifold_indicators(n_mi);
- unsigned int mi_counter=0;
- for (unsigned int i=0; i<mi_exists.size()-1; ++i)
- if (mi_exists[i]==true)
- manifold_indicators[mi_counter++]=i;
-
+ for (; cell!=end(); ++cell) {
+ m_ids.insert(cell->manifold_id());
+ if(dim>1)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->at_boundary(face))
+ m_ids.insert(cell->face(face)->manifold_id());
+ }
+ std::vector<types::manifold_id> manifold_indicators(m_ids.begin(), m_ids.end());
return manifold_indicators;
}
faces = new internal::Triangulation::TriaFaces<dim>(*old_tria.faces);
- typename std::map<types::boundary_id,
+ typename std::map<types::manifold_id,
SmartPointer<const Manifold<spacedim> , Triangulation<dim, spacedim> > >::const_iterator
bdry_iterator = old_tria.manifold.begin();
for (; bdry_iterator != old_tria.manifold.end() ; bdry_iterator++)
return internal::Triangulation::n_active_cells (number_cache);
}
+template <int dim, int spacedim>
+types::global_dof_index Triangulation<dim, spacedim>::n_global_active_cells () const
+{
+ return n_active_cells();
+}
+
+
template <int dim, int spacedim>
unsigned int Triangulation<dim, spacedim>::n_faces () const
}
+template <int dim, int spacedim>
+bool Triangulation<dim, spacedim>::has_hanging_nodes () const
+{
+ for (unsigned int lvl = 0; lvl<n_global_levels()-1;lvl++)
+ if (n_active_cells(lvl) != 0)
+ return true;
+
+ return false;
+}
+
template <int dim, int spacedim>
unsigned int Triangulation<dim, spacedim>::n_lines () const
-template <int dim, int spacedim>
-types::subdomain_id CellAccessor<dim, spacedim>::subdomain_id () const
-{
- Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
- Assert (this->active(), ExcMessage("subdomains only work on active cells!"));
- return this->tria->levels[this->present_level]->subdomain_ids[this->present_index];
-}
-
-
-
template <int dim, int spacedim>
void
CellAccessor<dim, spacedim>::set_subdomain_id (const types::subdomain_id new_subdomain_id) const
+template <int dim, int spacedim>
+void
+CellAccessor<dim, spacedim>::set_parent (const unsigned int parent_index)
+{
+ Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
+ Assert (this->present_level > 0, TriaAccessorExceptions::ExcCellHasNoParent ());
+ this->tria->levels[this->present_level]->parents[this->present_index / 2]
+ = parent_index;
+}
+
+
+
+template <int dim, int spacedim>
+int
+CellAccessor<dim, spacedim>::
+parent_index () const
+{
+ Assert (this->present_level > 0, TriaAccessorExceptions::ExcCellHasNoParent ());
+
+ // the parent of two consecutive cells
+ // is stored only once, since it is
+ // the same
+ return this->tria->levels[this->present_level]->parents[this->present_index / 2];
+}
+
+
template <int dim, int spacedim>
TriaIterator<CellAccessor<dim,spacedim> >
CellAccessor<dim, spacedim>::parent () const
Assert (this->used(), TriaAccessorExceptions::ExcCellNotUsed());
Assert (this->present_level > 0, TriaAccessorExceptions::ExcCellHasNoParent ());
TriaIterator<CellAccessor<dim,spacedim> >
- q (this->tria, this->present_level-1, this->parent_index ());
+ q (this->tria, this->present_level-1, parent_index ());
return q;
}
//---------------------------------------------------------------------------
- template<int dim, int spacedim>
- MappingQ1<dim,spacedim>& StaticMappingQ1<dim,spacedim>::return_static_mapping_q1()
+ namespace
{
- static MappingQ1<dim,spacedim> mapping;
- return mapping;
+ /**
+ * Create and return a reference to a static MappingQ1 object. We can't
+ * use the one in ::StaticMappingQ1 to initialize the static object below
+ * since we can't make sure that the constructor for that object is run
+ * before we want to use the object (when constructing mapping_collection
+ * below). Therefore we create a helper function which returns a
+ * reference to a static object that will be constructed the first time
+ * this function is called.
+ */
+ template<int dim, int spacedim>
+ MappingQ1<dim,spacedim> &
+ get_static_mapping_q1()
+ {
+ static MappingQ1<dim,spacedim> mapping;
+ return mapping;
+ }
}
template<int dim, int spacedim>
MappingCollection<dim,spacedim>
StaticMappingQ1<dim,spacedim>::mapping_collection
- = MappingCollection<dim,spacedim>(StaticMappingQ1<dim,spacedim>::return_static_mapping_q1());
+ = MappingCollection<dim,spacedim>(get_static_mapping_q1<dim,spacedim>());
}
const std::vector<ConstraintMatrix::size_type> &, \
MatrixType &) const
+ONLY_MATRIX_FUNCTIONS(FullMatrix<float>);
+ONLY_MATRIX_FUNCTIONS(FullMatrix<double>);
ONLY_MATRIX_FUNCTIONS(SparseMatrix<float>);
ONLY_MATRIX_FUNCTIONS(SparseMatrix<double>);
ONLY_MATRIX_FUNCTIONS(MatrixBlock<SparseMatrix<float> >);
#include <deal.II/lac/lapack_templates.h>
#include <deal.II/lac/lapack_support.h>
#include <deal.II/lac/full_matrix.h>
+#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/block_vector.h>
using namespace LAPACKSupport;
template <typename number>
-LAPACKFullMatrix<number>::LAPACKFullMatrix(const size_type n)
+LAPACKFullMatrix<number>::LAPACKFullMatrix (const size_type n)
:
TransposeTable<number> (n,n),
- state(matrix)
+ state (matrix)
{}
-
template <typename number>
-LAPACKFullMatrix<number>::LAPACKFullMatrix(
- const size_type m,
- const size_type n)
+LAPACKFullMatrix<number>::LAPACKFullMatrix (const size_type m,
+ const size_type n)
:
- TransposeTable<number> (m,n),
- state(matrix)
+ TransposeTable<number> (m, n),
+ state (matrix)
{}
-
template <typename number>
-LAPACKFullMatrix<number>::LAPACKFullMatrix(const LAPACKFullMatrix &M)
+LAPACKFullMatrix<number>::LAPACKFullMatrix (const LAPACKFullMatrix &M)
:
TransposeTable<number> (M),
- state(matrix)
+ state (matrix)
{}
-
template <typename number>
LAPACKFullMatrix<number> &
LAPACKFullMatrix<number>::operator = (const LAPACKFullMatrix<number> &M)
}
+template <typename number>
+void
+LAPACKFullMatrix<number>::reinit (const size_type n)
+{
+ this->TransposeTable<number>::reinit (n, n);
+ state = LAPACKSupport::matrix;
+}
+
+
+template <typename number>
+void
+LAPACKFullMatrix<number>::reinit (const size_type m,
+ const size_type n)
+{
+ this->TransposeTable<number>::reinit (m, n);
+ state = LAPACKSupport::matrix;
+}
+
template <typename number>
template <typename number2>
}
+template <typename number>
+template <typename number2>
+LAPACKFullMatrix<number> &
+LAPACKFullMatrix<number>::operator = (const SparseMatrix<number2> &M)
+{
+ Assert (this->n_rows() == M.n(), ExcDimensionMismatch(this->n_rows(), M.n()));
+ Assert (this->n_cols() == M.m(), ExcDimensionMismatch(this->n_cols(), M.m()));
+ for (size_type i=0; i<this->n_rows(); ++i)
+ for (size_type j=0; j<this->n_cols(); ++j)
+ (*this)(i,j) = M.el(i,j);
+
+ state = LAPACKSupport::matrix;
+ return *this;
+}
+
template <typename number>
LAPACKFullMatrix<number> &
Assert (d==0, ExcScalarAssignmentOnlyForZeroValue());
if (this->n_elements() != 0)
- std::fill (this->values.begin(), this->values.end(), number());
+ this->reset_values();
state = LAPACKSupport::matrix;
return *this;
}
-
template <typename number>
void
LAPACKFullMatrix<number>::vmult (
}
-
template <typename number>
void
LAPACKFullMatrix<number>::Tvmult (
}
-
template <typename number>
void
LAPACKFullMatrix<number>::mmult(LAPACKFullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::mmult(FullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_rows(), ExcDimensionMismatch(this->n_cols(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::Tmmult(FullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_rows(), ExcDimensionMismatch(this->n_rows(), B.n_rows()));
Assert (C.n_cols() == B.n_cols(), ExcDimensionMismatch(C.n_cols(), B.n_cols()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::mTmult(LAPACKFullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_cols() == B.n_cols(), ExcDimensionMismatch(this->n_cols(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_rows(), ExcDimensionMismatch(this->n_rows(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::TmTmult(LAPACKFullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
- Assert(C.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
+ Assert(C.state == matrix || C.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::TmTmult(FullMatrix<number> &C,
const LAPACKFullMatrix<number> &B,
const bool adding) const
{
- Assert(state == matrix, ExcState(state));
- Assert(B.state == matrix, ExcState(state));
+ Assert(state == matrix || state == inverse_matrix, ExcState(state));
+ Assert(B.state == matrix || B.state == inverse_matrix, ExcState(state));
Assert (this->n_rows() == B.n_cols(), ExcDimensionMismatch(this->n_rows(), B.n_cols()));
Assert (C.n_cols() == B.n_rows(), ExcDimensionMismatch(C.n_cols(), B.n_rows()));
Assert (C.n_rows() == this->n_cols(), ExcDimensionMismatch(this->n_cols(), C.n_rows()));
}
-
template <typename number>
void
LAPACKFullMatrix<number>::compute_lu_factorization()
}
-
template <typename number>
void
LAPACKFullMatrix<number>::compute_svd()
}
-
template <typename number>
void
LAPACKFullMatrix<number>::compute_inverse_svd(const double threshold)
}
-
template <typename number>
void
LAPACKFullMatrix<number>::invert()
}
-
template <typename number>
void
LAPACKFullMatrix<number>::apply_lu_factorization(Vector<number> &v,
Assert(state == lu, ExcState(state));
Assert(this->n_rows() == this->n_cols(),
LACExceptions::ExcNotQuadratic());
+ AssertDimension(this->n_rows(), v.size());
const char *trans = transposed ? &T : &N;
const int nn = this->n_cols();
}
-
template <typename number>
void
LAPACKFullMatrix<number>::apply_lu_factorization(LAPACKFullMatrix<number> &B,
Assert(state == lu, ExcState(state));
Assert(B.state == matrix, ExcState(state));
Assert(this->n_rows() == this->n_cols(), LACExceptions::ExcNotQuadratic());
+ AssertDimension(this->n_rows(), B.n_rows());
const char *trans = transposed ? &T : &N;
const int nn = this->n_cols();
}
-
template <typename number>
void
-LAPACKFullMatrix<number>::compute_eigenvalues(
- const bool right,
- const bool left)
+LAPACKFullMatrix<number>::compute_eigenvalues(const bool right,
+ const bool left)
{
Assert(state == matrix, ExcState(state));
const int nn = this->n_cols();
template <typename number>
void
-LAPACKFullMatrix<number>::compute_eigenvalues_symmetric(
- const number lower_bound,
- const number upper_bound,
- const number abs_accuracy,
- Vector<number> &eigenvalues,
- FullMatrix<number> &eigenvectors)
+LAPACKFullMatrix<number>::compute_eigenvalues_symmetric(const number lower_bound,
+ const number upper_bound,
+ const number abs_accuracy,
+ Vector<number> &eigenvalues,
+ FullMatrix<number> &eigenvectors)
{
Assert(state == matrix, ExcState(state));
const int nn = (this->n_cols() > 0 ? this->n_cols() : 1);
eigenvalues.reinit(n_eigenpairs);
eigenvectors.reinit(nn, n_eigenpairs, true);
+
for (size_type i=0; i < static_cast<size_type> (n_eigenpairs); ++i)
{
eigenvalues(i) = wr[i];
eigenvalues.reinit(n_eigenpairs);
eigenvectors.resize(n_eigenpairs);
+
for (size_type i=0; i < static_cast<size_type> (n_eigenpairs); ++i)
{
eigenvalues(i) = wr[i];
Tvmult(w, v, true);
}
+
template <typename number>
void
LAPACKFullMatrix<number>::print_formatted (
{
template LAPACKFullMatrix<S1> &
LAPACKFullMatrix<S1>::operator = (const FullMatrix<S2> &M);
+
+ template LAPACKFullMatrix<S1> &
+ LAPACKFullMatrix<S1>::operator = (const SparseMatrix<S2> &M);
}
}
-template<typename number, typename vnumber>
-const void *
-ProductSparseMatrix<number, vnumber>::get () const
-{
- return &*m1;
-}
-
-
template class ProductSparseMatrix<double, double>;
template class ProductSparseMatrix<double, float>;
template class ProductSparseMatrix<float, double>;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2004 - 2013 by the deal.II authors
+// Copyright (C) 2004 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
ExcDimensionMismatch (size(), n));
#if DEBUG
- // test ghost allocation in debug mode
- PetscInt begin, end;
+ {
+ // test ghost allocation in debug mode
+ PetscInt begin, end;
- ierr = VecGetOwnershipRange (vector, &begin, &end);
+ ierr = VecGetOwnershipRange (vector, &begin, &end);
- Assert(local_size==(size_type)(end-begin), ExcInternalError());
+ Assert(local_size==(size_type)(end-begin), ExcInternalError());
- Vec l;
- ierr = VecGhostGetLocalForm(vector, &l);
- AssertThrow (ierr == 0, ExcPETScError(ierr));
-
- PetscInt lsize;
- ierr = VecGetSize(l, &lsize);
- AssertThrow (ierr == 0, ExcPETScError(ierr));
+ Vec l;
+ ierr = VecGhostGetLocalForm(vector, &l);
+ AssertThrow (ierr == 0, ExcPETScError(ierr));
- ierr = VecGhostRestoreLocalForm(vector, &l);
- AssertThrow (ierr == 0, ExcPETScError(ierr));
+ PetscInt lsize;
+ ierr = VecGetSize(l, &lsize);
+ AssertThrow (ierr == 0, ExcPETScError(ierr));
- Assert( lsize==end-begin+(PetscInt)ghost_indices.n_elements() ,ExcInternalError());
+ ierr = VecGhostRestoreLocalForm(vector, &l);
+ AssertThrow (ierr == 0, ExcPETScError(ierr));
+ Assert (lsize==end-begin+(PetscInt)ghost_indices.n_elements(),
+ ExcInternalError());
+ }
#endif
+ // in PETSc versions up to 3.5, VecCreateGhost zeroed out the locally
+ // owned vector elements but forgot about the ghost elements. we need to
+ // do this ourselves
+ //
+ // see https://code.google.com/p/dealii/issues/detail?id=233
+#if DEAL_II_PETSC_VERSION_LT(3,6,0)
+ PETScWrappers::MPI::Vector zero;
+ zero.reinit (communicator, this->size(), local_size);
+ *this = zero;
+#endif
+
}
ierr = PCCreate(comm, &pc);
AssertThrow (ierr == 0, ExcPETScError(ierr));
+#if DEAL_II_PETSC_VERSION_LT(3, 5, 0)
ierr = PCSetOperators(pc , matrix, matrix, SAME_PRECONDITIONER);
+#else
+ ierr = PCSetOperators(pc , matrix, matrix);
+#endif
AssertThrow (ierr == 0, ExcPETScError(ierr));
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2004 - 2013 by the deal.II authors
+// Copyright (C) 2004 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// last argument is irrelevant here,
// since we use the solver only once
// anyway
+#if DEAL_II_PETSC_VERSION_LT(3, 5, 0)
ierr = KSPSetOperators (solver_data->ksp, A, preconditioner,
SAME_PRECONDITIONER);
+#else
+ ierr = KSPSetOperators (solver_data->ksp, A, preconditioner);
+#endif
AssertThrow (ierr == 0, ExcPETScError(ierr));
// let derived classes set the solver
* factorization here we start to see differences with the base
* class solve function
*/
+#if DEAL_II_PETSC_VERSION_GTE(3,2,0)
ierr = PCFactorSetMatSolverPackage (solver_data->pc, MATSOLVERMUMPS);
+#else
+ ierr = PCFactorSetMatSolverPackage (solver_data->pc, MAT_SOLVER_MUMPS);
+#endif
AssertThrow (ierr == 0, ExcPETScError (ierr));
/**
#else // PETSC_HAVE_MUMPS
Assert (false,
ExcMessage ("Your PETSc installation does not include a copy of "
- "MUMPS package necessary for this solver"));
+ "the MUMPS package necessary for this solver. You will need to configure "
+ "PETSc so that it includes MUMPS, recompile it, and then re-configure "
+ "and recompile deal.II as well."));
// Cast to void to silence compiler warnings
(void) A;
{
ForwardIterator it = begin;
bool has_larger_entries = false;
- std::size_t k=rowstart[row];
+ // skip diagonal
+ std::size_t k=rowstart[row]+store_diagonal_first_in_row;
for ( ; k<rowstart[row+1]; k++)
if (colnums[k] == invalid_entry)
break;
break;
}
if (has_larger_entries == false)
- for ( ; it != end; ++it, ++k)
+ for ( ; it != end; ++it)
{
+ if (store_diagonal_first_in_row && *it == row)
+ continue;
Assert (k <= rowstart[row+1],
ExcNotEnoughSpace(row, rowstart[row+1]-rowstart[row]));
- colnums[k] = *it;
+ colnums[k++] = *it;
}
else
// cannot just append the new range at the end, forward to the
// other function
- for (ForwardIterator it = begin; it != end; ++it)
- add (row, *it);
+ for (ForwardIterator p = begin; p != end; ++p)
+ add (row, *p);
}
}
else
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
int_rowstart.reserve(sparsity_pattern.n_rows()+1);
std::vector<idx_t> int_colnums;
int_colnums.reserve(sparsity_pattern.n_nonzero_elements());
- for (size_type row=0; row<sparsity_pattern.n_rows(); ++row)
+ for (SparsityPattern::size_type row=0; row<sparsity_pattern.n_rows(); ++row)
{
for (SparsityPattern::iterator col=sparsity_pattern.begin(row);
col < sparsity_pattern.end(row); ++col)
* invalid_size_type indicates that a node has not been numbered yet),
* pick a valid starting index among the as-yet unnumbered one.
*/
- size_type
+ SparsityPattern::size_type
find_unnumbered_starting_index (const SparsityPattern &sparsity,
- const std::vector<size_type> &new_indices)
+ const std::vector<SparsityPattern::size_type> &new_indices)
{
{
- size_type starting_point = numbers::invalid_size_type;
- size_type min_coordination = sparsity.n_rows();
- for (size_type row=0; row<sparsity.n_rows(); ++row)
+ SparsityPattern::size_type starting_point = numbers::invalid_size_type;
+ SparsityPattern::size_type min_coordination = sparsity.n_rows();
+ for (SparsityPattern::size_type row=0; row<sparsity.n_rows(); ++row)
// look over all as-yet unnumbered indices
if (new_indices[row] == numbers::invalid_size_type)
{
break;
// post-condition after loop: coordination, i.e. the number of
// entries in this row is now j-rowstart[row]
- if (static_cast<size_type>(j-sparsity.begin(row)) <
+ if (static_cast<SparsityPattern::size_type>(j-sparsity.begin(row)) <
min_coordination)
{
min_coordination = j-sparsity.begin(row);
// starting point, e.g. the first unnumbered one
if (starting_point == numbers::invalid_size_type)
{
- for (size_type i=0; i<new_indices.size(); ++i)
+ for (SparsityPattern::size_type i=0; i<new_indices.size(); ++i)
if (new_indices[i] == numbers::invalid_size_type)
{
starting_point = i;
void
- reorder_Cuthill_McKee (const SparsityPattern &sparsity,
- std::vector<size_type> &new_indices,
- const std::vector<size_type> &starting_indices)
+ reorder_Cuthill_McKee (const SparsityPattern &sparsity,
+ std::vector<SparsityPattern::size_type> &new_indices,
+ const std::vector<SparsityPattern::size_type> &starting_indices)
{
Assert (sparsity.n_rows() == sparsity.n_cols(),
ExcDimensionMismatch (sparsity.n_rows(), sparsity.n_cols()));
ExcDimensionMismatch (sparsity.n_rows(), new_indices.size()));
Assert (starting_indices.size() <= sparsity.n_rows(),
ExcMessage ("You can't specify more starting indices than there are rows"));
- for (size_type i=0; i<starting_indices.size(); ++i)
+ for (SparsityPattern::size_type i=0; i<starting_indices.size(); ++i)
Assert (starting_indices[i] < sparsity.n_rows(),
ExcMessage ("Invalid starting index"));
// store the indices of the dofs renumbered in the last round. Default to
// starting points
- std::vector<size_type> last_round_dofs (starting_indices);
+ std::vector<SparsityPattern::size_type> last_round_dofs (starting_indices);
// initialize the new_indices array with invalid values
std::fill (new_indices.begin(), new_indices.end(),
numbers::invalid_size_type);
// delete disallowed elements
- for (size_type i=0; i<last_round_dofs.size(); ++i)
+ for (SparsityPattern::size_type i=0; i<last_round_dofs.size(); ++i)
if ((last_round_dofs[i]==numbers::invalid_size_type) ||
(last_round_dofs[i]>=sparsity.n_rows()))
last_round_dofs[i] = numbers::invalid_size_type;
std::remove_if (last_round_dofs.begin(), last_round_dofs.end(),
- std::bind2nd(std::equal_to<size_type>(),
+ std::bind2nd(std::equal_to<SparsityPattern::size_type>(),
numbers::invalid_size_type));
// now if no valid points remain: find dof with lowest coordination number
new_indices));
// store next free dof index
- size_type next_free_number = 0;
+ SparsityPattern::size_type next_free_number = 0;
// enumerate the first round dofs
- for (size_type i=0; i!=last_round_dofs.size(); ++i)
+ for (SparsityPattern::size_type i=0; i!=last_round_dofs.size(); ++i)
new_indices[last_round_dofs[i]] = next_free_number++;
// now do as many steps as needed to
{
// store the indices of the dofs to be
// renumbered in the next round
- std::vector<size_type> next_round_dofs;
+ std::vector<SparsityPattern::size_type> next_round_dofs;
// find all neighbors of the
// dofs numbered in the last
// round
- for (size_type i=0; i<last_round_dofs.size(); ++i)
+ for (SparsityPattern::size_type i=0; i<last_round_dofs.size(); ++i)
for (SparsityPattern::iterator j=sparsity.begin(last_round_dofs[i]);
j<sparsity.end(last_round_dofs[i]); ++j)
if (j->is_valid_entry() == false)
std::sort (next_round_dofs.begin(), next_round_dofs.end());
// delete multiple entries
- std::vector<size_type>::iterator end_sorted;
+ std::vector<SparsityPattern::size_type>::iterator end_sorted;
end_sorted = std::unique (next_round_dofs.begin(), next_round_dofs.end());
next_round_dofs.erase (end_sorted, next_round_dofs.end());
// store for each coordination
// number the dofs with these
// coordination number
- std::multimap<size_type, int> dofs_by_coordination;
+ std::multimap<SparsityPattern::size_type, int> dofs_by_coordination;
// find coordination number for
// each of these dofs
- for (std::vector<size_type>::iterator s=next_round_dofs.begin();
+ for (std::vector<SparsityPattern::size_type>::iterator s=next_round_dofs.begin();
s!=next_round_dofs.end(); ++s)
{
- size_type coordination = 0;
+ SparsityPattern::size_type coordination = 0;
for (SparsityPattern::iterator j=sparsity.begin(*s);
j<sparsity.end(*s); ++j)
if (j->is_valid_entry() == false)
// insert this dof at its
// coordination number
- const std::pair<const size_type, int> new_entry (coordination, *s);
+ const std::pair<const SparsityPattern::size_type, int> new_entry (coordination, *s);
dofs_by_coordination.insert (new_entry);
}
// assign new DoF numbers to
// the elements of the present
// front:
- std::multimap<size_type, int>::iterator i;
+ std::multimap<SparsityPattern::size_type, int>::iterator i;
for (i = dofs_by_coordination.begin(); i!=dofs_by_coordination.end(); ++i)
new_indices[i->second] = next_free_number++;
#ifdef DEAL_II_WITH_MPI
template <class CSP_t>
void distribute_sparsity_pattern(CSP_t &csp,
- const std::vector<size_type> &rows_per_cpu,
+ const std::vector<typename CSP_t::size_type> &rows_per_cpu,
const MPI_Comm &mpi_comm,
const IndexSet &myrange)
{
- size_type myid = Utilities::MPI::this_mpi_process(mpi_comm);
- std::vector<size_type> start_index(rows_per_cpu.size()+1);
+ const unsigned int myid = Utilities::MPI::this_mpi_process(mpi_comm);
+ std::vector<typename CSP_t::size_type> start_index(rows_per_cpu.size()+1);
start_index[0]=0;
- for (size_type i=0; i<rows_per_cpu.size(); ++i)
+ for (typename CSP_t::size_type i=0; i<rows_per_cpu.size(); ++i)
start_index[i+1]=start_index[i]+rows_per_cpu[i];
- typedef std::map<size_type, std::vector<size_type> > map_vec_t;
+ typedef std::map<typename CSP_t::size_type, std::vector<typename CSP_t::size_type> > map_vec_t;
map_vec_t send_data;
{
unsigned int dest_cpu=0;
- size_type n_local_rel_rows = myrange.n_elements();
- for (size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
+ typename CSP_t::size_type n_local_rel_rows = myrange.n_elements();
+ for (typename CSP_t::size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
{
- size_type row=myrange.nth_index_in_set(row_idx);
+ typename CSP_t::size_type row=myrange.nth_index_in_set(row_idx);
//calculate destination CPU
while (row>=start_index[dest_cpu+1])
continue;
}
- size_type rlen = csp.row_length(row);
+ typename CSP_t::size_type rlen = csp.row_length(row);
//skip empty lines
if (!rlen)
continue;
//save entries
- std::vector<size_type> &dst = send_data[dest_cpu];
+ std::vector<typename CSP_t::size_type> &dst = send_data[dest_cpu];
dst.push_back(rlen); // number of entries
dst.push_back(row); // row index
- for (size_type c=0; c<rlen; ++c)
+ for (typename CSP_t::size_type c=0; c<rlen; ++c)
{
//columns
- size_type column = csp.column_number(row, c);
+ typename CSP_t::size_type column = csp.column_number(row, c);
dst.push_back(column);
}
}
{
std::vector<unsigned int> send_to;
send_to.reserve(send_data.size());
- for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
+ for (typename map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
send_to.push_back(it->first);
num_receive =
// send data
{
unsigned int idx=0;
- for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
+ for (typename map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
MPI_Isend(&(it->second[0]),
it->second.size(),
DEAL_II_DOF_INDEX_MPI_TYPE,
}
//TODO: In the following, we read individual bytes and then reinterpret them
-// as size_type objects. this is error prone. use properly typed reads that
+// as typename CSP_t::size_type objects. this is error prone. use properly typed reads that
// match the write above
{
//receive
- std::vector<size_type> recv_buf;
+ std::vector<typename CSP_t::size_type> recv_buf;
for (unsigned int index=0; index<num_receive; ++index)
{
MPI_Status status;
Assert (status.MPI_TAG==124, ExcInternalError());
MPI_Get_count(&status, MPI_BYTE, &len);
- Assert( len%sizeof(size_type)==0, ExcInternalError());
+ Assert( len%sizeof(typename CSP_t::size_type)==0, ExcInternalError());
- recv_buf.resize(len/sizeof(size_type));
+ recv_buf.resize(len/sizeof(typename CSP_t::size_type));
MPI_Recv(&recv_buf[0], len, MPI_BYTE, status.MPI_SOURCE,
status.MPI_TAG, mpi_comm, &status);
- std::vector<size_type>::const_iterator ptr = recv_buf.begin();
- std::vector<size_type>::const_iterator end = recv_buf.end();
+ typename std::vector<typename CSP_t::size_type>::const_iterator ptr = recv_buf.begin();
+ typename std::vector<typename CSP_t::size_type>::const_iterator end = recv_buf.end();
while (ptr+1<end)
{
- size_type num=*(ptr++);
- size_type row=*(ptr++);
+ typename CSP_t::size_type num=*(ptr++);
+ typename CSP_t::size_type row=*(ptr++);
for (unsigned int c=0; c<num; ++c)
{
csp.add(row, *ptr);
const MPI_Comm &mpi_comm,
const IndexSet &myrange)
{
- size_type myid = Utilities::MPI::this_mpi_process(mpi_comm);
+ const unsigned int myid = Utilities::MPI::this_mpi_process(mpi_comm);
- typedef std::map<size_type, std::vector<size_type> > map_vec_t;
+ typedef std::map<typename CSP_t::size_type, std::vector<typename CSP_t::size_type> > map_vec_t;
map_vec_t send_data;
{
unsigned int dest_cpu=0;
- size_type n_local_rel_rows = myrange.n_elements();
- for (size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
+ typename CSP_t::size_type n_local_rel_rows = myrange.n_elements();
+ for (typename CSP_t::size_type row_idx=0; row_idx<n_local_rel_rows; ++row_idx)
{
- size_type row=myrange.nth_index_in_set(row_idx);
+ typename CSP_t::size_type row=myrange.nth_index_in_set(row_idx);
// calculate destination CPU, note that we start the search
// at last destination cpu, because even if the owned ranges
if (dest_cpu==myid)
continue;
- size_type rlen = csp.row_length(row);
+ typename CSP_t::size_type rlen = csp.row_length(row);
//skip empty lines
if (!rlen)
continue;
//save entries
- std::vector<size_type> &dst = send_data[dest_cpu];
+ std::vector<typename CSP_t::size_type> &dst = send_data[dest_cpu];
dst.push_back(rlen); // number of entries
dst.push_back(row); // row index
- for (size_type c=0; c<rlen; ++c)
+ for (typename CSP_t::size_type c=0; c<rlen; ++c)
{
//columns
- size_type column = csp.column_number(row, c);
+ typename CSP_t::size_type column = csp.column_number(row, c);
dst.push_back(column);
}
}
{
std::vector<unsigned int> send_to;
send_to.reserve(send_data.size());
- for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
+ for (typename map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it)
send_to.push_back(it->first);
num_receive =
// send data
{
unsigned int idx=0;
- for (map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
+ for (typename map_vec_t::iterator it=send_data.begin(); it!=send_data.end(); ++it, ++idx)
MPI_Isend(&(it->second[0]),
it->second.size(),
DEAL_II_DOF_INDEX_MPI_TYPE,
}
//TODO: In the following, we read individual bytes and then reinterpret them
-// as size_type objects. this is error prone. use properly typed reads that
+// as typename CSP_t::size_type objects. this is error prone. use properly typed reads that
// match the write above
{
//receive
- std::vector<size_type> recv_buf;
+ std::vector<typename CSP_t::size_type> recv_buf;
for (unsigned int index=0; index<num_receive; ++index)
{
MPI_Status status;
Assert (status.MPI_TAG==124, ExcInternalError());
MPI_Get_count(&status, MPI_BYTE, &len);
- Assert( len%sizeof(size_type)==0, ExcInternalError());
+ Assert( len%sizeof(typename CSP_t::size_type)==0, ExcInternalError());
- recv_buf.resize(len/sizeof(size_type));
+ recv_buf.resize(len/sizeof(typename CSP_t::size_type));
MPI_Recv(&recv_buf[0], len, MPI_BYTE, status.MPI_SOURCE,
status.MPI_TAG, mpi_comm, &status);
- std::vector<size_type>::const_iterator ptr = recv_buf.begin();
- std::vector<size_type>::const_iterator end = recv_buf.end();
+ typename std::vector<typename CSP_t::size_type>::const_iterator ptr = recv_buf.begin();
+ typename std::vector<typename CSP_t::size_type>::const_iterator end = recv_buf.end();
while (ptr+1<end)
{
- size_type num=*(ptr++);
- size_type row=*(ptr++);
+ typename CSP_t::size_type num=*(ptr++);
+ typename CSP_t::size_type row=*(ptr++);
for (unsigned int c=0; c<num; ++c)
{
csp.add(row, *ptr);
#define SPARSITY_FUNCTIONS(SparsityType) \
template void SparsityTools::distribute_sparsity_pattern<SparsityType> (SparsityType & csp, \
- const std::vector<size_type> & rows_per_cpu,\
+ const std::vector<SparsityType::size_type> & rows_per_cpu,\
const MPI_Comm & mpi_comm,\
const IndexSet & myrange)
PreconditionJacobi::AdditionalData::
AdditionalData (const double omega,
- const double min_diagonal)
+ const double min_diagonal,
+ const unsigned int n_sweeps)
:
omega (omega),
- min_diagonal (min_diagonal)
+ min_diagonal (min_diagonal),
+ n_sweeps (n_sweeps)
{}
int ierr;
Teuchos::ParameterList parameter_list;
- parameter_list.set ("relaxation: sweeps", 1);
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
parameter_list.set ("relaxation: type", "Jacobi");
parameter_list.set ("relaxation: damping factor", additional_data.omega);
parameter_list.set ("relaxation: min diagonal value",
PreconditionSSOR::AdditionalData::
AdditionalData (const double omega,
const double min_diagonal,
- const unsigned int overlap)
+ const unsigned int overlap,
+ const unsigned int n_sweeps)
:
omega (omega),
min_diagonal (min_diagonal),
- overlap (overlap)
+ overlap (overlap),
+ n_sweeps (n_sweeps)
{}
int ierr;
Teuchos::ParameterList parameter_list;
- parameter_list.set ("relaxation: sweeps", 1);
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
parameter_list.set ("relaxation: type", "symmetric Gauss-Seidel");
parameter_list.set ("relaxation: damping factor", additional_data.omega);
parameter_list.set ("relaxation: min diagonal value",
PreconditionSOR::AdditionalData::
AdditionalData (const double omega,
const double min_diagonal,
- const unsigned int overlap)
+ const unsigned int overlap,
+ const unsigned int n_sweeps)
:
omega (omega),
min_diagonal (min_diagonal),
- overlap (overlap)
+ overlap (overlap),
+ n_sweeps (n_sweeps)
{}
int ierr;
Teuchos::ParameterList parameter_list;
- parameter_list.set ("relaxation: sweeps", 1);
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
+ parameter_list.set ("relaxation: type", "Gauss-Seidel");
+ parameter_list.set ("relaxation: damping factor", additional_data.omega);
+ parameter_list.set ("relaxation: min diagonal value",
+ additional_data.min_diagonal);
+ parameter_list.set ("schwarz: combine mode", "Add");
+
+ ierr = ifpack->SetParameters(parameter_list);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Initialize();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Compute();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+
+
+
+ /* ----------------------- PreconditionBlockJacobi ---------------------- */
+
+ PreconditionBlockJacobi::AdditionalData::
+ AdditionalData (const unsigned int block_size,
+ const std::string block_creation_type,
+ const double omega,
+ const double min_diagonal,
+ const unsigned int n_sweeps)
+ :
+ block_size(block_size),
+ block_creation_type(block_creation_type),
+ omega (omega),
+ min_diagonal (min_diagonal),
+ n_sweeps (n_sweeps)
+ {}
+
+
+
+ void
+ PreconditionBlockJacobi::initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data)
+ {
+ // release memory before reallocation
+ preconditioner.reset ();
+ preconditioner.reset (Ifpack().Create
+ ("block relaxation",
+ const_cast<Epetra_CrsMatrix *>(&matrix.trilinos_matrix()),
+ 0));
+
+ Ifpack_Preconditioner *ifpack = static_cast<Ifpack_Preconditioner *>
+ (preconditioner.get());
+ Assert (ifpack != 0, ExcMessage ("Trilinos could not create this "
+ "preconditioner"));
+
+ int ierr;
+
+ Teuchos::ParameterList parameter_list;
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
+ parameter_list.set ("relaxation: type", "Jacobi");
+ parameter_list.set ("relaxation: damping factor", additional_data.omega);
+ parameter_list.set ("relaxation: min diagonal value",
+ additional_data.min_diagonal);
+ parameter_list.set ("partitioner: type", additional_data.block_creation_type);
+ int n_local_parts = (matrix.trilinos_matrix().NumMyRows()+additional_data.
+ block_size-1)/additional_data.block_size;
+ parameter_list.set ("partitioner: local parts", n_local_parts);
+
+ ierr = ifpack->SetParameters(parameter_list);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Initialize();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Compute();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+
+
+
+ /* ----------------------- PreconditionBlockSSOR ------------------------ */
+
+ PreconditionBlockSSOR::AdditionalData::
+ AdditionalData (const unsigned int block_size,
+ const std::string block_creation_type,
+ const double omega,
+ const double min_diagonal,
+ const unsigned int overlap,
+ const unsigned int n_sweeps)
+ :
+ block_size(block_size),
+ block_creation_type(block_creation_type),
+ omega (omega),
+ min_diagonal (min_diagonal),
+ overlap (overlap),
+ n_sweeps (n_sweeps)
+ {}
+
+
+
+ void
+ PreconditionBlockSSOR::initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data)
+ {
+ preconditioner.reset ();
+ preconditioner.reset (Ifpack().Create
+ ("block relaxation",
+ const_cast<Epetra_CrsMatrix *>(&matrix.trilinos_matrix()),
+ additional_data.overlap));
+
+ Ifpack_Preconditioner *ifpack = static_cast<Ifpack_Preconditioner *>
+ (preconditioner.get());
+ Assert (ifpack != 0, ExcMessage ("Trilinos could not create this "
+ "preconditioner"));
+
+ int ierr;
+
+ Teuchos::ParameterList parameter_list;
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
+ parameter_list.set ("relaxation: type", "symmetric Gauss-Seidel");
+ parameter_list.set ("relaxation: damping factor", additional_data.omega);
+ parameter_list.set ("relaxation: min diagonal value",
+ additional_data.min_diagonal);
+ parameter_list.set ("schwarz: combine mode", "Add");
+ parameter_list.set ("partitioner: type", additional_data.block_creation_type);
+ int n_local_parts = (matrix.trilinos_matrix().NumMyRows()+additional_data.
+ block_size-1)/additional_data.block_size;
+ parameter_list.set ("partitioner: local parts", n_local_parts);
+
+ ierr = ifpack->SetParameters(parameter_list);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Initialize();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ ierr = ifpack->Compute();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ }
+
+
+
+ /* ------------------------ PreconditionBlockSOR ------------------------ */
+
+ PreconditionBlockSOR::AdditionalData::
+ AdditionalData (const unsigned int block_size,
+ const std::string block_creation_type,
+ const double omega,
+ const double min_diagonal,
+ const unsigned int overlap,
+ const unsigned int n_sweeps)
+ :
+ block_size(block_size),
+ block_creation_type(block_creation_type),
+ omega (omega),
+ min_diagonal (min_diagonal),
+ overlap (overlap),
+ n_sweeps (n_sweeps)
+ {}
+
+
+
+ void
+ PreconditionBlockSOR::initialize (const SparseMatrix &matrix,
+ const AdditionalData &additional_data)
+ {
+ preconditioner.reset ();
+ preconditioner.reset (Ifpack().Create
+ ("block relaxation",
+ const_cast<Epetra_CrsMatrix *>(&matrix.trilinos_matrix()),
+ additional_data.overlap));
+
+ Ifpack_Preconditioner *ifpack = static_cast<Ifpack_Preconditioner *>
+ (preconditioner.get());
+ Assert (ifpack != 0, ExcMessage ("Trilinos could not create this "
+ "preconditioner"));
+
+ int ierr;
+
+ Teuchos::ParameterList parameter_list;
+ parameter_list.set ("relaxation: sweeps", static_cast<int>(additional_data.n_sweeps));
parameter_list.set ("relaxation: type", "Gauss-Seidel");
parameter_list.set ("relaxation: damping factor", additional_data.omega);
parameter_list.set ("relaxation: min diagonal value",
additional_data.min_diagonal);
parameter_list.set ("schwarz: combine mode", "Add");
+ parameter_list.set ("partitioner: type", additional_data.block_creation_type);
+ int n_local_parts = (matrix.trilinos_matrix().NumMyRows()+additional_data.
+ block_size-1)/additional_data.block_size;
+ parameter_list.set ("partitioner: local parts", n_local_parts);
ierr = ifpack->SetParameters(parameter_list);
AssertThrow (ierr == 0, ExcTrilinosError(ierr));
{}
+ PreconditionAMG::~PreconditionAMG()
+ {
+ preconditioner.reset();
+ trilinos_matrix.reset();
+ }
+
void
PreconditionAMG:: initialize (const SparseMatrix &matrix,
const size_type constant_modes_dimension =
additional_data.constant_modes.size();
Epetra_MultiVector distributed_constant_modes (domain_map,
- constant_modes_dimension);
+ constant_modes_dimension > 0 ?
+ constant_modes_dimension : 1);
std::vector<double> dummy (constant_modes_dimension);
- if (constant_modes_dimension > 1)
+ if (constant_modes_dimension > 0)
{
const bool constant_modes_are_global =
additional_data.constant_modes[0].size() == n_rows;
{
linear_problem.reset();
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
linear_problem.reset
(new Epetra_LinearProblem(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
&x.trilinos_vector(),
const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
- execute_solve(preconditioner);
+ do_solve(preconditioner);
}
{
linear_problem.reset();
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
linear_problem.reset
(new Epetra_LinearProblem(&A,
&x.trilinos_vector(),
const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
- execute_solve(preconditioner);
+ do_solve(preconditioner);
}
{
linear_problem.reset();
- // In case we call the solver with
- // deal.II vectors, we create views
- // of the vectors in Epetra format.
+ // In case we call the solver with deal.II vectors, we create views of the
+ // vectors in Epetra format.
Assert (x.size() == A.n(),
ExcDimensionMismatch(x.size(), A.n()));
Assert (b.size() == A.m(),
Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
linear_problem.reset (new Epetra_LinearProblem
(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
&ep_x, &ep_b));
- execute_solve(preconditioner);
+ do_solve(preconditioner);
}
Epetra_Vector ep_x (View, A.OperatorDomainMap(), x.begin());
Epetra_Vector ep_b (View, A.OperatorRangeMap(), const_cast<double *>(b.begin()));
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
linear_problem.reset (new Epetra_LinearProblem(&A,&ep_x, &ep_b));
- execute_solve(preconditioner);
+ do_solve(preconditioner);
}
void
- SolverBase::execute_solve(const PreconditionBase &preconditioner)
+ SolverBase::solve (const SparseMatrix &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b,
+ const PreconditionBase &preconditioner)
+ {
+ linear_problem.reset();
+
+ // In case we call the solver with deal.II vectors, we create views of the
+ // vectors in Epetra format.
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
+ A.domain_partitioner().NumMyElements());
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
+ A.range_partitioner().NumMyElements());
+
+ Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
+ Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
+
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
+ linear_problem.reset (new Epetra_LinearProblem
+ (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
+ &ep_x, &ep_b));
+
+ do_solve(preconditioner);
+ }
+
+
+
+ void
+ SolverBase::solve (Epetra_Operator &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b,
+ const PreconditionBase &preconditioner)
+ {
+ linear_problem.reset();
+
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
+ A.OperatorDomainMap().NumMyElements());
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
+ A.OperatorRangeMap().NumMyElements());
+
+ Epetra_Vector ep_x (View, A.OperatorDomainMap(), x.begin());
+ Epetra_Vector ep_b (View, A.OperatorRangeMap(), const_cast<double *>(b.begin()));
+
+ // We need an Epetra_LinearProblem object to let the AztecOO solver know
+ // about the matrix and vectors.
+ linear_problem.reset (new Epetra_LinearProblem(&A,&ep_x, &ep_b));
+
+ do_solve(preconditioner);
+ }
+
+
+
+ void
+ SolverBase::do_solve(const PreconditionBase &preconditioner)
{
int ierr;
- // Next we can allocate the
- // AztecOO solver...
+ // Next we can allocate the AztecOO solver...
solver.SetProblem(*linear_problem);
- // ... and we can specify the
- // solver to be used.
+ // ... and we can specify the solver to be used.
switch (solver_name)
{
case cg:
Assert (false, ExcNotImplemented());
}
- // Introduce the preconditioner,
- // if the identity preconditioner is used,
+ // Introduce the preconditioner, if the identity preconditioner is used,
// the precondioner is set to none, ...
if (preconditioner.preconditioner.use_count()!=0)
{
ierr = solver.Iterate (solver_control.max_steps(),
solver_control.tolerance());
- // report errors in more detail
- // than just by checking whether
- // the return status is zero or
- // greater. the error strings are
- // taken from the implementation
- // of the AztecOO::Iterate
- // function
+ // report errors in more detail than just by checking whether the return
+ // status is zero or greater. the error strings are taken from the
+ // implementation of the AztecOO::Iterate function
switch (ierr)
{
case -1:
"loss of precision"));
case -4:
AssertThrow (false, ExcMessage("AztecOO::Iterate error code -4: "
- "GMRES hessenberg ill-conditioned"));
+ "GMRES Hessenberg ill-conditioned"));
default:
AssertThrow (ierr >= 0, ExcTrilinosError(ierr));
}
- // Finally, let the deal.II
- // SolverControl object know
- // what has happened. If the
- // solve succeeded, the status
- // of the solver control will
- // turn into
- // SolverControl::success.
+ // Finally, let the deal.II SolverControl object know what has
+ // happened. If the solve succeeded, the status of the solver control will
+ // turn into SolverControl::success.
solver_control.check (solver.NumIters(), solver.TrueResidual());
if (solver_control.last_check() != SolverControl::success)
/* ---------------------- SolverDirect ------------------------ */
SolverDirect::AdditionalData::
- AdditionalData (const bool output_solver_details)
+ AdditionalData (const bool output_solver_details,
+ const std::string &solver_type)
:
- output_solver_details (output_solver_details)
+ output_solver_details (output_solver_details),
+ solver_type(solver_type)
{}
const AdditionalData &data)
:
solver_control (cn),
- additional_data (data.output_solver_details)
+ additional_data (data.output_solver_details,data.solver_type)
{}
void
- SolverDirect::solve (const SparseMatrix &A,
- VectorBase &x,
- const VectorBase &b)
+ SolverDirect::do_solve()
{
- // First set whether we want to print
- // the solver information to screen
- // or not.
+ // Fetch return value of Amesos Solver functions
+ int ierr;
+
+ // First set whether we want to print the solver information to screen or
+ // not.
ConditionalOStream verbose_cout (std::cout,
additional_data.output_solver_details);
- linear_problem.reset();
solver.reset();
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
- linear_problem.reset
- (new Epetra_LinearProblem(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
- &x.trilinos_vector(),
- const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
+ // Next allocate the Amesos solver, this is done in two steps, first we
+ // create a solver Factory and and generate with that the concrete Amesos
+ // solver, if possible.
+ Amesos Factory;
+
+ AssertThrow(
+ Factory.Query(additional_data.solver_type.c_str()),
+ ExcMessage (std::string ("You tried to select the solver type <") +
+ additional_data.solver_type +
+ "> but this solver is not supported by Trilinos either "
+ "because it does not exist, or because Trilinos was not "
+ "configured for its use.")
+ );
- // Next we can allocate the
- // AztecOO solver...
- solver.reset (Amesos().Create("Amesos_Klu", *linear_problem));
+ solver.reset (
+ Factory.Create(additional_data.solver_type.c_str(), *linear_problem)
+ );
verbose_cout << "Starting symbolic factorization" << std::endl;
- solver->SymbolicFactorization();
+ ierr = solver->SymbolicFactorization();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
verbose_cout << "Starting numeric factorization" << std::endl;
- solver->NumericFactorization();
+ ierr = solver->NumericFactorization();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
verbose_cout << "Starting solve" << std::endl;
- solver->Solve();
-
- // Finally, let the deal.II
- // SolverControl object know
- // what has happened. If the
- // solve succeeded, the status
- // of the solver control will
- // turn into
- // SolverControl::success.
+ ierr = solver->Solve();
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+
+ // Finally, let the deal.II SolverControl object know what has
+ // happened. If the solve succeeded, the status of the solver control will
+ // turn into SolverControl::success.
solver_control.check (0, 0);
if (solver_control.last_check() != SolverControl::success)
}
+ void
+ SolverDirect::solve (const SparseMatrix &A,
+ VectorBase &x,
+ const VectorBase &b)
+ {
+ // We need an Epetra_LinearProblem object to let the Amesos solver know
+ // about the matrix and vectors.
+ linear_problem.reset
+ (new Epetra_LinearProblem(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
+ &x.trilinos_vector(),
+ const_cast<Epetra_MultiVector *>(&b.trilinos_vector())));
+
+ do_solve();
+ }
+
+
void
SolverDirect::solve (const SparseMatrix &A,
dealii::Vector<double> &x,
const dealii::Vector<double> &b)
{
- // First set whether we want to print
- // the solver information to screen
- // or not.
- ConditionalOStream verbose_cout (std::cout,
- additional_data.output_solver_details);
-
- linear_problem.reset();
- solver.reset();
-
- // In case we call the solver with
- // deal.II vectors, we create views
- // of the vectors in Epetra format.
+ // In case we call the solver with deal.II vectors, we create views of the
+ // vectors in Epetra format.
Assert (x.size() == A.n(),
ExcDimensionMismatch(x.size(), A.n()));
Assert (b.size() == A.m(),
Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
- // We need an
- // Epetra_LinearProblem object
- // to let the AztecOO solver
- // know about the matrix and
- // vectors.
+ // We need an Epetra_LinearProblem object to let the Amesos solver know
+ // about the matrix and vectors.
linear_problem.reset (new Epetra_LinearProblem
(const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
&ep_x, &ep_b));
- // Next we can allocate the
- // AztecOO solver...
- solver.reset (Amesos().Create("Amesos_Klu", *linear_problem));
+ do_solve();
+ }
- verbose_cout << "Starting symbolic factorization" << std::endl;
- solver->SymbolicFactorization();
- verbose_cout << "Starting numeric factorization" << std::endl;
- solver->NumericFactorization();
-
- verbose_cout << "Starting solve" << std::endl;
- solver->Solve();
-
- // Finally, let the deal.II
- // SolverControl object know
- // what has happened. If the
- // solve succeeded, the status
- // of the solver control will
- // turn into
- // SolverControl::success.
- solver_control.check (0, 0);
-
- if (solver_control.last_check() != SolverControl::success)
- AssertThrow(false, SolverControl::NoConvergence (solver_control.last_step(),
- solver_control.last_value()));
- }
+ void
+ SolverDirect::solve (const SparseMatrix &A,
+ dealii::parallel::distributed::Vector<double> &x,
+ const dealii::parallel::distributed::Vector<double> &b)
+ {
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(x.local_size()),
+ A.domain_partitioner().NumMyElements());
+ AssertDimension (static_cast<TrilinosWrappers::types::int_type>(b.local_size()),
+ A.range_partitioner().NumMyElements());
+ Epetra_Vector ep_x (View, A.domain_partitioner(), x.begin());
+ Epetra_Vector ep_b (View, A.range_partitioner(), const_cast<double *>(b.begin()));
+ // We need an Epetra_LinearProblem object to let the Amesos solver know
+ // about the matrix and vectors.
+ linear_problem.reset (new Epetra_LinearProblem
+ (const_cast<Epetra_CrsMatrix *>(&A.trilinos_matrix()),
+ &ep_x, &ep_b));
+ do_solve();
+ }
}
- inline
void
SparseMatrix::compress (::dealii::VectorOperation::values operation)
{
// MPI will still get a parallel
// interface.
SparsityPattern::SparsityPattern ()
- :
- compressed (true)
{
column_space_map.reset(new Epetra_Map (TrilinosWrappers::types::int_type(0),
TrilinosWrappers::types::int_type(0),
column_space_map (new Epetra_Map(TrilinosWrappers::types::int_type(0),
TrilinosWrappers::types::int_type(0),
Utilities::Trilinos::comm_self())),
- compressed (false),
graph (new Epetra_FECrsGraph(View,
*column_space_map,
*column_space_map,
SparsityPattern::SparsityPattern (const IndexSet ¶llel_partitioning,
const MPI_Comm &communicator,
const size_type n_entries_per_row)
- :
- compressed (false)
{
Epetra_Map map = parallel_partitioning.make_trilinos_map (communicator,
false);
SparsityPattern::SparsityPattern (const IndexSet ¶llel_partitioning,
const MPI_Comm &communicator,
const std::vector<size_type> &n_entries_per_row)
- :
- compressed (false)
{
Epetra_Map map = parallel_partitioning.make_trilinos_map (communicator,
false);
const IndexSet &col_parallel_partitioning,
const MPI_Comm &communicator,
const size_type n_entries_per_row)
- :
- compressed (false)
{
Epetra_Map row_map =
row_parallel_partitioning.make_trilinos_map (communicator, false);
const IndexSet &col_parallel_partitioning,
const MPI_Comm &communicator,
const std::vector<size_type> &n_entries_per_row)
- :
- compressed (false)
{
Epetra_Map row_map =
row_parallel_partitioning.make_trilinos_map (communicator, false);
const IndexSet &writable_rows,
const MPI_Comm &communicator,
const size_type n_max_entries_per_row)
- :
- compressed (false)
{
reinit (row_parallel_partitioning, col_parallel_partitioning,
writable_rows, communicator, n_max_entries_per_row);
"the maps of different processors."));
graph.reset ();
column_space_map.reset (new Epetra_Map (input_col_map));
- compressed = false;
-
- // for more than one processor, need to
- // specify only row map first and let the
- // matrix entries decide about the column
- // map (which says which columns are
- // present in the matrix, not to be
- // confused with the col_map that tells
- // how the domain dofs of the matrix will
- // be distributed). for only one
- // processor, we can directly assign the
- // columns as well.
+
+ // for more than one processor, need to specify only row map first and let
+ // the matrix entries decide about the column map (which says which
+ // columns are present in the matrix, not to be confused with the col_map
+ // that tells how the domain dofs of the matrix will be distributed). for
+ // only one processor, we can directly assign the columns as well. If we
+ // use a recent Trilinos version, we can also require building a non-local
+ // graph which gives us thread-safe initialization.
if (input_row_map.Comm().NumProc() > 1)
graph.reset (new Epetra_FECrsGraph(Copy, input_row_map,
- n_entries_per_row, false));
+ n_entries_per_row, false
+#if DEAL_II_TRILINOS_VERSION_GTE(11,9,0)
+ , true
+#endif
+ ));
else
graph.reset (new Epetra_FECrsGraph(Copy, input_row_map, input_col_map,
n_entries_per_row, false));
static_cast<size_type>(n_global_elements(input_row_map)));
column_space_map.reset (new Epetra_Map (input_col_map));
- compressed = false;
if (input_row_map.Comm().NumProc() > 1)
graph.reset(new Epetra_FECrsGraph(Copy, input_row_map,
n_entries_per_row[min_my_gid(input_row_map)],
- false));
+ false
+#if DEAL_II_TRILINOS_VERSION_GTE(11,9,0)
+ , true
+#endif
+ ));
else
graph.reset(new Epetra_FECrsGraph(Copy, input_row_map, input_col_map,
n_entries_per_row[max_my_gid(input_row_map)],
static_cast<size_type>(n_global_elements(input_col_map)));
column_space_map.reset (new Epetra_Map (input_col_map));
- compressed = false;
Assert (input_row_map.LinearMap() == true,
ExcMessage ("This function is not efficient if the map is not contiguous."));
graph->FillComplete();
nonlocal_graph.reset();
-
- compressed = true;
}
nonlocal_graph->RowMap().NumMyElements() > 0)
{
// insert dummy element
- TrilinosWrappers::types::int_type row = nonlocal_graph->RowMap().MyGID(0);
+ TrilinosWrappers::types::int_type row = nonlocal_graph->RowMap().MyGID(
+ static_cast<TrilinosWrappers::types::int_type> (0));
nonlocal_graph->InsertGlobalIndices(row, 1, &row);
}
Assert(nonlocal_graph->IndicesAreGlobal() == true,
ierr = graph->OptimizeStorage ();
AssertThrow (ierr == 0, ExcTrilinosError(ierr));
-
- compressed = true;
}
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2008 - 2013 by the deal.II authors
+// Copyright (C) 2008 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
*this += v;
else
{
+ Assert (!has_ghost_elements(), ExcGhostsPresent());
AssertThrow (size() == v.size(),
ExcDimensionMismatch (size(), v.size()));
- Epetra_Import data_exchange (vector->Map(), v.vector->Map());
+#if DEAL_II_TRILINOS_VERSION_GTE(11,9,0)
+ Epetra_Import data_exchange (vector->Map(), v.vector->Map());
+ int ierr = vector->Import(*v.vector, data_exchange, Add);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+ last_action = Add;
+#else
+ // In versions older than 11.9 the Import function is broken for adding
+ // Hence, we provide a workaround in this case
+
+ Epetra_MultiVector dummy(vector->Map(), 1, false);
+ Epetra_Import data_exchange (dummy.Map(), v.vector->Map());
- int ierr = vector->Import(*v.vector, data_exchange, Add);
+ int ierr = dummy.Import(*v.vector, data_exchange, Insert);
AssertThrow (ierr == 0, ExcTrilinosError(ierr));
- last_action = Insert;
+ ierr = vector->Update (1.0, dummy, 1.0);
+ AssertThrow (ierr == 0, ExcTrilinosError(ierr));
+#endif
}
}
template void MatrixFree<deal_II_dimension,float>::
print_memory_consumption<ConditionalOStream> (ConditionalOStream &) const;
-
template struct internal::MatrixFreeFunctions::MappingInfo<deal_II_dimension,double>;
template struct internal::MatrixFreeFunctions::MappingInfo<deal_II_dimension,float>;
+
+ template void internal::MatrixFreeFunctions::ShapeInfo<double>::reinit
+ <deal_II_dimension>(const Quadrature<1> &, const FiniteElement
+ <deal_II_dimension,deal_II_dimension> &, const unsigned int);
+ template void internal::MatrixFreeFunctions::ShapeInfo<float>::reinit
+ <deal_II_dimension>(const Quadrature<1> &, const FiniteElement
+ <deal_II_dimension,deal_II_dimension> &, const unsigned int);
+
}
if (level_boundary)
{
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += fe.dofs_per_face;
continue;
}
// here.
if (flux_coupling != DoFTools::none)
{
- unsigned int increment = nfe.dofs_per_cell - nfe.dofs_per_face;
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += increment;
+ const unsigned int dof_increment = nfe.dofs_per_cell - nfe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += dof_increment;
}
// Do this only once per
// the coarse one.
neighbor_indices.resize(nfe.dofs_per_cell);
neighbor->get_mg_dof_indices(neighbor_indices);
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += nfe.dofs_per_face;
- for (unsigned int i=0; i<nfe.dofs_per_cell; ++i)
- row_lengths[neighbor_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += nfe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<nfe.dofs_per_cell; ++local_dof)
+ row_lengths[neighbor_indices[local_dof]] += fe.dofs_per_face;
}
}
user_flags_triangulation.load_user_flags(old_flags);
if (level_boundary)
{
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ row_lengths[cell_indices[local_dof]] += fe.dofs_per_face;
continue;
}
// here.
for (unsigned int base=0; base<nfe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<nfe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- if (couple_face[fe_index](fe.system_to_block_index(i).first,
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ if (couple_face[fe_index](fe.system_to_block_index(local_dof).first,
nfe.first_block_of_base(base) + mult) != DoFTools::none)
{
- unsigned int increment = nfe.base_element(base).dofs_per_cell
- - nfe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
+ const unsigned int dof_increment = nfe.base_element(base).dofs_per_cell
+ - nfe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[local_dof]] += dof_increment;
}
// Do this only once per
neighbor->get_mg_dof_indices(neighbor_indices);
for (unsigned int base=0; base<nfe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<nfe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<fe.dofs_per_cell; ++i)
- if (couple_cell[fe_index](fe.system_to_component_index(i).first,
+ for (unsigned int local_dof=0; local_dof<fe.dofs_per_cell; ++local_dof)
+ if (couple_cell[fe_index](fe.system_to_component_index(local_dof).first,
nfe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[cell_indices[i]]
+ row_lengths[cell_indices[local_dof]]
+= nfe.base_element(base).dofs_per_face;
for (unsigned int base=0; base<fe.n_base_elements(); ++base)
for (unsigned int mult=0; mult<fe.element_multiplicity(base); ++mult)
- for (unsigned int i=0; i<nfe.dofs_per_cell; ++i)
- if (couple_cell[fe_index](nfe.system_to_component_index(i).first,
+ for (unsigned int local_dof=0; local_dof<nfe.dofs_per_cell; ++local_dof)
+ if (couple_cell[fe_index](nfe.system_to_component_index(local_dof).first,
fe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[neighbor_indices[i]]
+ row_lengths[neighbor_indices[local_dof]]
+= fe.base_element(base).dofs_per_face;
}
}
// first fill dof_data
for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
{
- const FEValuesBase<DH::dimension,DH::space_dimension> &fe_patch_values
+ const FEValuesBase<DH::dimension,DH::space_dimension> &this_fe_patch_values
= data.get_present_fe_values (dataset);
const unsigned int n_components =
- fe_patch_values.get_fe().n_components();
+ this_fe_patch_values.get_fe().n_components();
const DataPostprocessor<DH::space_dimension> *postprocessor=this->dof_data[dataset]->postprocessor;
// at each point there is only one component of value,
// gradient etc.
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
std::vector<Point<DH::space_dimension> > dummy_normals;
// at each point there is a vector valued function and its
// derivative...
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients_system);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians_system);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
std::vector<Point<DH::space_dimension> > dummy_normals;
// reasons.
if (n_components == 1)
{
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
for (unsigned int q=0; q<n_q_points; ++q)
patch.data(offset,q) = data.patch_values[q];
else
{
data.resize_system_vectors(n_components);
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
for (unsigned int component=0; component<n_components;
++component)
DataVectorType actual_type = type;
if (type == type_automatic)
{
+ // in the rare case that someone has a DGP(0) attached, we can not decide what she wants here:
+ Assert((dofs == 0) || (triangulation->n_active_cells() != dofs->n_dofs()),
+ ExcMessage("Unable to determine the type of vector automatically because the number of DoFs "
+ "is equal to the number of cells. Please specify DataVectorType."));
+
if (vec.size() == triangulation->n_active_cells())
actual_type = type_cell_data;
else
// first fill dof_data
for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
{
- const FEValuesBase<dimension> &fe_patch_values
+ const FEValuesBase<dimension> &this_fe_patch_values
= data.get_present_fe_values (dataset);
const unsigned int n_components
- = fe_patch_values.get_fe().n_components();
+ = this_fe_patch_values.get_fe().n_components();
const DataPostprocessor<dim> *postprocessor=this->dof_data[dataset]->postprocessor;
if (postprocessor != 0)
{
// thus does not depend on the number of components of the data
// vector
if (update_flags & update_normal_vectors)
- data.patch_normals=fe_patch_values.get_normal_vectors();
+ data.patch_normals=this_fe_patch_values.get_normal_vectors();
if (n_components == 1)
{
// at each point there is only one component of value,
// gradient etc.
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
postprocessor->
compute_derived_quantities_scalar(data.patch_values,
// derivative...
data.resize_system_vectors(n_components);
if (update_flags & update_values)
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
if (update_flags & update_gradients)
- this->dof_data[dataset]->get_function_gradients (fe_patch_values,
+ this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
data.patch_gradients_system);
if (update_flags & update_hessians)
- this->dof_data[dataset]->get_function_hessians (fe_patch_values,
+ this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
data.patch_hessians_system);
if (update_flags & update_quadrature_points)
- data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
+ data.patch_evaluation_points = this_fe_patch_values.get_quadrature_points();
postprocessor->
compute_derived_quantities_vector(data.patch_values_system,
// reasons.
if (n_components == 1)
{
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values);
for (unsigned int q=0; q<n_q_points; ++q)
patch.data(offset,q) = data.patch_values[q];
else
{
data.resize_system_vectors(n_components);
- this->dof_data[dataset]->get_function_values (fe_patch_values,
+ this->dof_data[dataset]->get_function_values (this_fe_patch_values,
data.patch_values_system);
for (unsigned int component=0; component<n_components;
++component)
// reinit fe values object...
x_fe_midpoint_value.reinit (neighbor);
- const FEValues<dim> &fe_midpoint_value
+ const FEValues<dim> &neighbor_fe_midpoint_value
= x_fe_midpoint_value.get_present_fe_values();
// ...and get the value of the
// solution...
const typename DerivativeDescription::ProjectedDerivative
neighbor_midpoint_value
- = DerivativeDescription::get_projected_derivative (fe_midpoint_value,
+ = DerivativeDescription::get_projected_derivative (neighbor_fe_midpoint_value,
solution, component);
// ...and the place where it lives
const Point<dim>
- neighbor_center = fe_midpoint_value.quadrature_point(0);
+ neighbor_center = neighbor_fe_midpoint_value.quadrature_point(0);
// vector for the
}
- template <int dim, template <int, int> class DH, class InputVector, int order, int spacedim>
+ template <class DH, class InputVector, int order>
void
- approximate_derivative_tensor (const Mapping<dim,spacedim> &mapping,
- const DH<dim,spacedim> &dof,
+ approximate_derivative_tensor (const Mapping<DH::dimension,DH::space_dimension> &mapping,
+ const DH &dof,
const InputVector &solution,
- const typename DH<dim,spacedim>::active_cell_iterator &cell,
- Tensor<order,dim> &derivative,
+ const typename DH::active_cell_iterator &cell,
+ Tensor<order,DH::dimension> &derivative,
const unsigned int component)
{
- internal::approximate_cell<typename internal::DerivativeSelector<order,dim>::DerivDescr,dim,DH,InputVector>
+ internal::approximate_cell<typename internal::DerivativeSelector<order,DH::dimension>::DerivDescr>
(mapping,
dof,
solution,
- template <int dim, template <int, int> class DH, class InputVector, int order, int spacedim>
+ template <class DH, class InputVector, int order>
void
- approximate_derivative_tensor (const DH<dim,spacedim> &dof,
+ approximate_derivative_tensor (const DH &dof,
const InputVector &solution,
- const typename DH<dim,spacedim>::active_cell_iterator &cell,
- Tensor<order,dim> &derivative,
+ const typename DH::active_cell_iterator &cell,
+ Tensor<order,DH::dimension> &derivative,
const unsigned int component)
{
// just call the respective function with Q1 mapping
- approximate_derivative_tensor<dim,DH,InputVector,order,spacedim>
- (StaticMappingQ1<dim>::mapping,
+ approximate_derivative_tensor<DH,InputVector,order>
+ (StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
dof,
solution,
cell,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const Mapping<deal_II_dimension> & mapping,
const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const Mapping<deal_II_dimension> & mapping,
const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const Mapping<deal_II_dimension> & mapping,
const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
const DH<deal_II_dimension>::active_cell_iterator &cell,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
const DH<deal_II_dimension>::active_cell_iterator &cell,
template
void
-approximate_derivative_tensor<deal_II_dimension>
+approximate_derivative_tensor
(const DH<deal_II_dimension> &dof_handler,
const VEC &solution,
const DH<deal_II_dimension>::active_cell_iterator &cell,
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
Assert (matrix.n() == solution.size(),
ExcDimensionMismatch(matrix.n(), solution.size()));
- // if no boundary values are to be applied
- // simply return
- if (boundary_values.size() == 0)
- return;
-
- const std::pair<types::global_dof_index, types::global_dof_index> local_range
- = matrix.local_range();
- Assert (local_range == right_hand_side.local_range(),
- ExcInternalError());
- Assert (local_range == solution.local_range(),
- ExcInternalError());
-
- // determine the first nonzero diagonal
- // entry from within the part of the
- // matrix that we can see. if we can't
- // find such an entry, take one
- PetscScalar average_nonzero_diagonal_entry = 1;
- for (types::global_dof_index i=local_range.first; i<local_range.second; ++i)
- if (matrix.diag_element(i) != 0)
- {
- average_nonzero_diagonal_entry = std::fabs(matrix.diag_element(i));
- break;
- }
-
- // figure out which rows of the matrix we
- // have to eliminate on this processor
- std::vector<types::global_dof_index> constrained_rows;
- for (std::map<types::global_dof_index,double>::const_iterator
- dof = boundary_values.begin();
- dof != boundary_values.end();
- ++dof)
- if ((dof->first >= local_range.first) &&
- (dof->first < local_range.second))
- constrained_rows.push_back (dof->first);
+ // if no boundary values are to be applied, then
+ // jump straight to the compress() calls that we still have
+ // to perform because they are collective operations
+ if (boundary_values.size() > 0)
+ {
+ const std::pair<types::global_dof_index, types::global_dof_index> local_range
+ = matrix.local_range();
+ Assert (local_range == right_hand_side.local_range(),
+ ExcInternalError());
+ Assert (local_range == solution.local_range(),
+ ExcInternalError());
+
+ // determine the first nonzero diagonal
+ // entry from within the part of the
+ // matrix that we can see. if we can't
+ // find such an entry, take one
+ PetscScalar average_nonzero_diagonal_entry = 1;
+ for (types::global_dof_index i=local_range.first; i<local_range.second; ++i)
+ if (matrix.diag_element(i) != 0)
+ {
+ average_nonzero_diagonal_entry = std::fabs(matrix.diag_element(i));
+ break;
+ }
- // then eliminate these rows and set
- // their diagonal entry to what we have
- // determined above. note that for petsc
- // matrices interleaving read with write
- // operations is very expensive. thus, we
- // here always replace the diagonal
- // element, rather than first checking
- // whether it is nonzero and in that case
- // preserving it. this is different from
- // the case of deal.II sparse matrices
- // treated in the other functions.
- matrix.clear_rows (constrained_rows, average_nonzero_diagonal_entry);
-
- std::vector<types::global_dof_index> indices;
- std::vector<PetscScalar> solution_values;
- for (std::map<types::global_dof_index,double>::const_iterator
- dof = boundary_values.begin();
- dof != boundary_values.end();
- ++dof)
- if ((dof->first >= local_range.first) &&
- (dof->first < local_range.second))
- {
- indices.push_back (dof->first);
- solution_values.push_back (dof->second);
- }
- solution.set (indices, solution_values);
+ // figure out which rows of the matrix we
+ // have to eliminate on this processor
+ std::vector<types::global_dof_index> constrained_rows;
+ for (std::map<types::global_dof_index,double>::const_iterator
+ dof = boundary_values.begin();
+ dof != boundary_values.end();
+ ++dof)
+ if ((dof->first >= local_range.first) &&
+ (dof->first < local_range.second))
+ constrained_rows.push_back (dof->first);
- // now also set appropriate values for
- // the rhs
- for (unsigned int i=0; i<solution_values.size(); ++i)
- solution_values[i] *= average_nonzero_diagonal_entry;
+ // then eliminate these rows and set
+ // their diagonal entry to what we have
+ // determined above. note that for petsc
+ // matrices interleaving read with write
+ // operations is very expensive. thus, we
+ // here always replace the diagonal
+ // element, rather than first checking
+ // whether it is nonzero and in that case
+ // preserving it. this is different from
+ // the case of deal.II sparse matrices
+ // treated in the other functions.
+ matrix.clear_rows (constrained_rows, average_nonzero_diagonal_entry);
+
+ std::vector<types::global_dof_index> indices;
+ std::vector<PetscScalar> solution_values;
+ for (std::map<types::global_dof_index,double>::const_iterator
+ dof = boundary_values.begin();
+ dof != boundary_values.end();
+ ++dof)
+ if ((dof->first >= local_range.first) &&
+ (dof->first < local_range.second))
+ {
+ indices.push_back (dof->first);
+ solution_values.push_back (dof->second);
+ }
+ solution.set (indices, solution_values);
- right_hand_side.set (indices, solution_values);
+ // now also set appropriate values for
+ // the rhs
+ for (unsigned int i=0; i<solution_values.size(); ++i)
+ solution_values[i] *= average_nonzero_diagonal_entry;
+ right_hand_side.set (indices, solution_values);
+ }
+ else
+ {
+ // clear_rows() is a collective operation so we still have to call
+ // it:
+ std::vector<types::global_dof_index> constrained_rows;
+ matrix.clear_rows (constrained_rows, 1.);
+ }
+
// clean up
matrix.compress ();
solution.compress (VectorOperation::insert);
Assert (matrix.n() == solution.size(),
ExcDimensionMismatch(matrix.m(), solution.size()));
- // if no boundary values are to be applied
- // simply return
- if (boundary_values.size() == 0)
- return;
-
- const std::pair<types::global_dof_index, types::global_dof_index> local_range
- = matrix.local_range();
- Assert (local_range == right_hand_side.local_range(),
- ExcInternalError());
- Assert (local_range == solution.local_range(),
- ExcInternalError());
-
- // we have to read and write from this
- // matrix (in this order). this will only
- // work if we compress the matrix first,
- // done here
- matrix.compress ();
-
- // determine the first nonzero diagonal
- // entry from within the part of the
- // matrix that we can see. if we can't
- // find such an entry, take one
- TrilinosScalar average_nonzero_diagonal_entry = 1;
- for (types::global_dof_index i=local_range.first; i<local_range.second; ++i)
- if (matrix.diag_element(i) != 0)
- {
- average_nonzero_diagonal_entry = std::fabs(matrix.diag_element(i));
- break;
- }
-
- // figure out which rows of the matrix we
- // have to eliminate on this processor
- std::vector<types::global_dof_index> constrained_rows;
- for (std::map<types::global_dof_index,double>::const_iterator
- dof = boundary_values.begin();
- dof != boundary_values.end();
- ++dof)
- if ((dof->first >= local_range.first) &&
- (dof->first < local_range.second))
- constrained_rows.push_back (dof->first);
-
- // then eliminate these rows and
- // set their diagonal entry to
- // what we have determined
- // above. if the value already is
- // nonzero, it will be preserved,
- // in accordance with the basic
- // matrix classes in deal.II.
- matrix.clear_rows (constrained_rows, average_nonzero_diagonal_entry);
-
- std::vector<types::global_dof_index> indices;
- std::vector<TrilinosScalar> solution_values;
- for (std::map<types::global_dof_index,double>::const_iterator
- dof = boundary_values.begin();
- dof != boundary_values.end();
- ++dof)
- if ((dof->first >= local_range.first) &&
- (dof->first < local_range.second))
- {
- indices.push_back (dof->first);
- solution_values.push_back (dof->second);
- }
- solution.set (indices, solution_values);
-
- // now also set appropriate
- // values for the rhs
- for (unsigned int i=0; i<solution_values.size(); ++i)
- solution_values[i] *= matrix.diag_element(indices[i]);
-
- right_hand_side.set (indices, solution_values);
-
+ // if no boundary values are to be applied, then
+ // jump straight to the compress() calls that we still have
+ // to perform because they are collective operations
+ if (boundary_values.size() > 0)
+ {
+ const std::pair<types::global_dof_index, types::global_dof_index> local_range
+ = matrix.local_range();
+ Assert (local_range == right_hand_side.local_range(),
+ ExcInternalError());
+ Assert (local_range == solution.local_range(),
+ ExcInternalError());
+
+ // we have to read and write from this
+ // matrix (in this order). this will only
+ // work if we compress the matrix first,
+ // done here
+ matrix.compress ();
+
+ // determine the first nonzero diagonal
+ // entry from within the part of the
+ // matrix that we can see. if we can't
+ // find such an entry, take one
+ TrilinosScalar average_nonzero_diagonal_entry = 1;
+ for (types::global_dof_index i=local_range.first; i<local_range.second; ++i)
+ if (matrix.diag_element(i) != 0)
+ {
+ average_nonzero_diagonal_entry = std::fabs(matrix.diag_element(i));
+ break;
+ }
+
+ // figure out which rows of the matrix we
+ // have to eliminate on this processor
+ std::vector<types::global_dof_index> constrained_rows;
+ for (std::map<types::global_dof_index,double>::const_iterator
+ dof = boundary_values.begin();
+ dof != boundary_values.end();
+ ++dof)
+ if ((dof->first >= local_range.first) &&
+ (dof->first < local_range.second))
+ constrained_rows.push_back (dof->first);
+
+ // then eliminate these rows and
+ // set their diagonal entry to
+ // what we have determined
+ // above. if the value already is
+ // nonzero, it will be preserved,
+ // in accordance with the basic
+ // matrix classes in deal.II.
+ matrix.clear_rows (constrained_rows, average_nonzero_diagonal_entry);
+
+ std::vector<types::global_dof_index> indices;
+ std::vector<TrilinosScalar> solution_values;
+ for (std::map<types::global_dof_index,double>::const_iterator
+ dof = boundary_values.begin();
+ dof != boundary_values.end();
+ ++dof)
+ if ((dof->first >= local_range.first) &&
+ (dof->first < local_range.second))
+ {
+ indices.push_back (dof->first);
+ solution_values.push_back (dof->second);
+ }
+ solution.set (indices, solution_values);
+
+ // now also set appropriate
+ // values for the rhs
+ for (unsigned int i=0; i<solution_values.size(); ++i)
+ solution_values[i] *= matrix.diag_element(indices[i]);
+
+ right_hand_side.set (indices, solution_values);
+ }
+ else
+ {
+ // clear_rows() is a collective operation so we still have to call
+ // it:
+ std::vector<types::global_dof_index> constrained_rows;
+ matrix.clear_rows (constrained_rows, 1.);
+ }
+
// clean up
matrix.compress ();
solution.compress (VectorOperation::insert);
// write column headings
- std::map <std::string, std::vector <std::vector <double> > >::iterator
- data_store_begin = data_store.begin ();
to_gnuplot << "# <Key> ";
if (indep_names.size() > 0)
}
}
- for (; data_store_begin != data_store.end (); data_store_begin++)
+ for (std::map <std::string, std::vector <std::vector <double> > >::iterator
+ data_store_begin = data_store.begin (); data_store_begin != data_store.end (); ++data_store_begin)
{
typename std::map <std::string, ComponentMask>::iterator mask = component_mask.find(data_store_begin->first);
unsigned int n_stored = mask->second.n_selected_components();
// write data stored for the point
for (unsigned int key = 0; key < dataset_key.size (); key++)
{
- std::map <std::string, std::vector <std::vector <double> > >::iterator
- data_store_begin = data_store.begin ();
to_gnuplot << dataset_key[key];
for (unsigned int component = 0; component < n_indep; component++)
to_gnuplot << " " << independent_values[component][key];
}
- for (; data_store_begin != data_store.end (); data_store_begin++)
+ for (std::map <std::string, std::vector <std::vector <double> > >::iterator
+ data_store_begin = data_store.begin ();
+ data_store_begin != data_store.end (); ++data_store_begin)
{
typename std::map <std::string, ComponentMask>::iterator mask = component_mask.find(data_store_begin->first);
unsigned int n_stored = mask->second.n_selected_components();
std::vector<Vector<typename VECTOR::value_type> > (in_size))
.swap(dof_values_on_cell);
- typename VECTOR::value_type zero_val = typename VECTOR::value_type();
-
Table<2,FullMatrix<double> > interpolation_hp;
std::vector<std::vector<bool> > restriction_is_additive;
// ---------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 1998 - 2013 by the deal.II authors
+// Copyright (C) 1998 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
//TODO[SP]: replace <deal_II_dimension> by <deal_II_dimension, deal_II_space_dimension>
// where applicable and move to codimension cases above also when applicable
for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS)
- {
- namespace VectorTools \{
+{
+ namespace VectorTools \{
#if deal_II_dimension == deal_II_space_dimension
#if deal_II_dimension != 1
- template
- void
- compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
- template
- void
- compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
+ template
+ void
+ compute_nonzero_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ FunctionMap<deal_II_dimension>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
- template
- void
- compute_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
- template
- void
- compute_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<types::boundary_id> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<deal_II_dimension> &mapping);
+ template
+ void
+ compute_nonzero_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ FunctionMap<deal_II_dimension>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_nonzero_tangential_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ FunctionMap<deal_II_dimension>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+ template
+ void
+ compute_nonzero_tangential_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ FunctionMap<deal_II_dimension>::type &function_map,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
+
+ template
+ void
+ compute_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<types::boundary_id> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<deal_II_dimension> &mapping);
#endif
#endif
- \}
- }
+ \}
+}
\ No newline at end of file
COMMAND rm -f ${_test_directory}/failing_diff
COMMAND touch ${_test_directory}/diff
COMMAND
- ${TEST_DIFF} ${_test_directory}/output ${_comparison_file} > ${_test_directory}/diff
+ ${TEST_DIFF} ${_comparison_file} ${_test_directory}/output > ${_test_directory}/diff
|| (mv ${_test_directory}/diff
${_test_directory}/failing_diff
&& echo "${_test_full}: RUN successful."