Commit 65fd4d24 authored by breuera's avatar breuera

initial commit

parent b70075b5
# Doxyfile 1.7.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = "swe_solvers"
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY =
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.
CREATE_SUBDIRS = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful is your file systems
# doesn't support long names like on DOS, Mac, or CD-ROM.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
JAVADOC_AUTOBRIEF = NO
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
# comment as the brief description. If set to NO, the comments
# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.
TAB_SIZE = 8
# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.
ALIASES =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = NO
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for
# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources only. Doxygen will then generate output that is more tailored for
# Fortran.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for
# VHDL.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given extension.
# Doxygen has a built-in mapping, but you can override or extend it using this
# tag. The format is ext=language, where ext is a file extension, and language
# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
EXTENSION_MAPPING =
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate getter
# and setter methods for a property. Setting this option to YES (the default)
# will make doxygen to replace the get and set methods by a property in the
# documentation. This will only work if the methods are indeed getting or
# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.
SUBGROUPING = YES
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
TYPEDEF_HIDES_STRUCT = NO
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
# When the cache is full, less often used symbols will be written to disk.
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
# causing a significant performance penality.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will rougly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols
SYMBOL_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
EXTRACT_PRIVATE = YES
# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.
EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
# anonymous namespace are hidden.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = NO
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
# will list include files with double quotes in the documentation
# rather than with sharp brackets.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
# will sort the (brief and detailed) documentation of class members so that
# constructors and destructors are listed first. If set to NO (the default)
# the constructors will appear in the respective orders defined by
# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.
SORT_BY_SCOPE_NAME = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or define consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and defines in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
# If the sources in your project are distributed over multiple directories
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
# in the documentation. The default is NO.
SHOW_DIRECTORIES = NO
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. The create the layout file
# that represents doxygen's defaults, run doxygen with the -l option.
# You can optionally specify a file name after the option, if omitted
# DoxygenLayout.xml will be used as the name of the layout file.
LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.
WARNINGS = YES
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.
WARN_IF_UNDOCUMENTED = YES
# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be abled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.
WARN_NO_PARAMDOC = NO
# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
# also the default input encoding. Doxygen uses libiconv (or the iconv built
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
FILE_PATTERNS =
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.
EXAMPLE_PATTERNS =
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
# is applied to all files.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.
REFERENCES_LINK_SOURCE = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If the tag is left blank doxygen
# will generate a default style sheet. Note that doxygen will try to copy
# the style sheet file to the HTML output directory, so don't put your own
# stylesheet in the HTML output directory as well, or it will be erased!
HTML_STYLESHEET =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
# Doxygen will adjust the colors in the stylesheet and background images
# according to this color. Hue is specified as an angle on a colorwheel,
# see http://en.wikipedia.org/wiki/Hue for more information.
# For instance the value 0 represents red, 60 is yellow, 120 is green,
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
# The allowed range is 0 to 359.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
# the colors in the HTML output. For a value of 0 the output will use
# grayscales only. A value of 255 will produce the most vivid colors.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
# the luminance component of the colors in the HTML output. Values below
# 100 gradually make the output lighter, whereas values above 100 make
# the output darker. The value divided by 100 is the actual gamma applied,
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
# and 100 does not change the gamma.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
HTML_TIMESTAMP = YES
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
# NO a bullet list will be used.
HTML_ALIGN_MEMBERS = YES
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
HTML_DYNAMIC_SECTIONS = NO
# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
# integrated development environment, introduced with OSX 10.5 (Leopard).
# To create a documentation set, doxygen will generate a Makefile in the
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
GENERATE_DOCSET = NO
# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
# feed. A documentation feed provides an umbrella under which multiple
# documentation sets from a single provider (such as a company or product suite)
# can be grouped.
DOCSET_FEEDNAME = "Doxygen generated docs"
# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
# should uniquely identify the documentation set bundle. This should be a
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.
DOCSET_BUNDLE_ID = org.doxygen.Project
# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.
GENERATE_HTMLHELP = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.
CHM_FILE =
# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.
HHC_LOCATION =
# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).
GENERATE_CHI = NO
# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.
CHM_INDEX_ENCODING =
# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
# that can be used as input for Qt's qhelpgenerator to generate a
# Qt Compressed Help (.qch) of the generated HTML documentation.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders
QHP_VIRTUAL_FOLDER = doc
# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
# add. For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
# Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
# Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS =
# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
# will be generated, which together with the HTML files, form an Eclipse help
# plugin. To install this plugin and make it available under the help contents
# menu in Eclipse, the contents of the directory containing the HTML and XML
# files needs to be copied into the plugins directory of eclipse. The name of
# the directory within the plugins directory should be the same as
# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
# the help appears.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have
# this name.
ECLIPSE_DOC_ID = org.doxygen.Project
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
# top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it.
DISABLE_INDEX = NO
# This tag can be used to set the number of enum values (range [1..20])
# that doxygen will group on one line in the generated HTML documentation.
ENUM_VALUES_PER_LINE = 4
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
# Windows users are probably better off using the HTML help feature.
GENERATE_TREEVIEW = NO
# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
# and Class Hierarchy pages using a tree view instead of an ordered list.
USE_INLINE_TREES = NO
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
TREEVIEW_WIDTH = 250
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
# links to external symbols imported via tag files in a separate window.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of Latex formulas included
# as images in the HTML documentation. The default is 10. Note that
# when you change the font size after a successful doxygen run you need
# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are
# not supported properly for IE 6.0, but are supported on all modern browsers.
# Note that when changing this option you need to delete any form_*.png files
# in the HTML output before the changes have effect.
FORMULA_TRANSPARENT = YES
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# and DHTML and should work on any modern browser. Note that when using
# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
# (GENERATE_DOCSET) there is already a search function so this one should
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client
# using Javascript. Doxygen will generate the search PHP script and index
# file to put on the web server. The advantage of the server
# based approach is that it scales better to large projects and allows
# full text search. The disadvances is that it is more difficult to setup
# and does not have live searching capabilities.
SERVER_BASED_SEARCH = NO
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
# Note that when enabling USE_PDFLATEX this option is only used for
# generating bitmaps for formulas in the HTML output, but not in the
# Makefile that is written to the output directory.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
# If LATEX_SOURCE_CODE is set to YES then doxygen will include
# source code with syntax highlighting in the LaTeX output.
# Note that which sources are shown also depends on other settings
# such as SOURCE_BROWSER.
LATEX_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.
XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
# on a line, have an all uppercase name, and do not end with a semicolon. Such
# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
# The TAGFILES option can be used to specify one or more tagfiles.
# Optionally an initial location of the external documentation
# can be added for each tagfile. The format of a tag file without
# this location is as follows:
#
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths or
# URLs. If a location is present for each tag, the installdox tool
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen
# is run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will
# be listed.
EXTERNAL_GROUPS = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option is superseded by the HAVE_DOT option below. This is only a
# fallback. It is recommended to install and use dot, since it yields more
# powerful graphs.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see
# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
# base this on the number of processors available in the system. You can set it
# explicitly to a value larger than 0 to get control over the balance
# between CPU load and processing speed.
DOT_NUM_THREADS = 0
# By default doxygen will write a font called FreeSans.ttf to the output
# directory and reference it in all dot files that doxygen generates. This
# font does not include all possible unicode characters however, so when you need
# these (or just want a differently looking font) you can specify the font name
# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
# which can be done by putting it in a standard location or by setting the
# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
# containing the font.
DOT_FONTNAME = FreeSans.ttf
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the output directory to look for the
# FreeSans.ttf font (which doxygen will put there itself). If you specify a
# different font using DOT_FONTNAME you can set the path where dot
# can find it using this tag.
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# the CLASS_DIAGRAMS tag to NO.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
UML_LOOK = NO
# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.
TEMPLATE_RELATIONS = NO
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.
INCLUDE_GRAPH = YES
# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH and HAVE_DOT options are set to YES then
# doxygen will generate a call dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
CALL_GRAPH = NO
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).
DOTFILE_DIRS =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
# visualized by representing a node as a red box. Note that doxygen if the
# number of direct children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.
DOT_MULTI_TARGETS = YES
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.
DOT_CLEANUP = YES
#!/bin/bash
GEOCLAWSRCPATH=../src/solver/geoclaw
ifort -w -g -c $GEOCLAWSRCPATH/riemannsolvers.f $GEOCLAWSRCPATH/c_bind_riemannsolvers.f90
\ No newline at end of file
/**
* AugRie.hpp
*
****
**** Approximate Augmented Riemann Solver for the Shallow Water Equations
****
*
* Created on: Sep 12, 2011
* Last Update: Feb 18, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
* Some optimizations: Martin Schreiber
* Homepage: http://www5.in.tum.de/wiki/index.php/Martin_Schreiber
* E-Mail: schreibm AT in.tum.de
*
****
*
* (Main) Literature:
*
* @phdthesis{george2006finite,
* Author = {George, D.L.},
* Title = {Finite volume methods and adaptive refinement for tsunami propagation and inundation},
* Year = {2006}}
*
* @article{george2008augmented,
* Author = {George, D.L.},
* Journal = {Journal of Computational Physics},
* Number = {6},
* Pages = {3089--3113},
* Publisher = {Elsevier},
* Title = {Augmented Riemann solvers for the shallow water equations over variable topography with steady states and inundation},
* Volume = {227},
* Year = {2008}}
*
* @book{leveque2002finite,
* Author = {LeVeque, R. J.},
* Date-Added = {2011-09-13 14:09:31 +0000},
* Date-Modified = {2011-10-31 09:46:40 +0000},
* Publisher = {Cambridge University Press},
* Title = {Finite Volume Methods for Hyperbolic Problems},
* Volume = {31},
* Year = {2002}}
*
* @webpage{levequeclawpack,
* Author = {LeVeque, R. J.},
* Lastchecked = {January, 05, 2011},
* Title = {Clawpack Sofware},
* Url = {https://github.com/clawpack/clawpack-4.x/blob/master/geoclaw/2d/lib}}
*
****
*
* Acknowledgments:
* Special thanks go to R.J. LeVeque and D.L. George for publishing their code
* and the corresponding documentation (-> Literature).
*/
/*
* TODO: store nLow/nHigh variables in array[2]
*/
#ifndef AUGRIE_HPP_
#define AUGRIE_HPP_
#include "WavePropagation.hpp"
#include <cassert>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
/** switch features of the solver on/off
*
* The solver is not strictly positivity preserving with correctrarefactions.
*
* Solver seems to fail in the "Single wave on a simple beach"-benchmark
* if correctrarefactions or complexsteadystatewave is used.
*
* TODO: Further investigation is recommended.
*/
//#define correctrarefactions
//#define complexsteadystatewave
namespace solver {
template <typename T> class AugRie;
}
/**
* Approximate Augmented Riemann Solver for the Shallow Water Equations.
*
* T should be double or float.
*/
template <typename T> class solver::AugRie: public WavePropagation<T> {
private: //explicit for unit tests
//use nondependent names (template base class)
using solver::WavePropagation<T>::zeroTol;
using solver::WavePropagation<T>::g;
using solver::WavePropagation<T>::dryTol;
using solver::WavePropagation<T>::hLeft;
using solver::WavePropagation<T>::hRight;
using solver::WavePropagation<T>::huLeft;
using solver::WavePropagation<T>::huRight;
using solver::WavePropagation<T>::bLeft;
using solver::WavePropagation<T>::bRight;
using solver::WavePropagation<T>::uLeft;
using solver::WavePropagation<T>::uRight;
using solver::WavePropagation<T>::wetDryState;
using solver::WavePropagation<T>::DryDry;
using solver::WavePropagation<T>::WetWet;
using solver::WavePropagation<T>::WetDryInundation;
using solver::WavePropagation<T>::WetDryWall;
using solver::WavePropagation<T>::WetDryWallInundation;
using solver::WavePropagation<T>::DryWetInundation;
using solver::WavePropagation<T>::DryWetWall;
using solver::WavePropagation<T>::DryWetWallInundation;
using solver::WavePropagation<T>::storeParameters;
//! Newton-tolerance (exit Newton-Raphson-method, if we are close enough to the root)
const T newtonTol;
//! maximum number of Newton-Raphson-Iterations
const int maxNumberOfNewtonIterations;
//! height of our homogeneous Riemann-problem at middle state (computed by determineMiddleState)
T hMiddle;
//! shock or inner rarefaction speeds of our homogeneous Riemann-problem (computed by computeMiddleState)
T middleStateSpeeds[2];
/**
* the Riemann-struture of the homogeneous Riemann-problem.
*/
enum RiemannStructure {
DrySingleRarefaction, /**< 1st wave family: contact discontinuity; 2nd wave family: rarefaction. */
SingleRarefactionDry, /**< 1st wave family: rarefaction; 2nd wave family: contact discontinuity. */
ShockShock, /**< 1st wave family: shock; 2nd wave family: shock. */
ShockRarefaction, /**< 1st wave family: shock; 2nd wave family: rarefaction. */
RarefactionShock, /**< 1st wave family: rarefaction; 2nd wave family: shock. */
RarefactionRarefaction /**< 1st wave family: rarefaction; 2nd wave family: rarefaction. */
};
//! Riemann-structure of our homogeneous Riemann-problem (determined by determineRiemannStructure)
RiemannStructure riemannStructure;
public:
/**
* Constructor of the Augmented Riemann solver with optional parameters.
*
* @param i_dryTolerance numerical definition of "dry".
* @param i_gravity gravity constant.
* @param i_newtonTolerance numerical definition of "convergence" (used in the AugRie solver only).
* @param i_maxNumberOfNewtonIterations maximum steps for the Newton-Raphson method (used in the AugRie solver only).
* @param i_zeroTolerance numerical definition of zero.
*/
AugRie( T i_dryTolerance = (T) 0.01,
T i_gravity = (T) 9.81,
T i_newtonTolerance = (T) 0.000001,
int i_maxNumberOfNewtonIterations = 10,
T i_zeroTolerance = (T) 0.00001 ):
WavePropagation<T>( i_dryTolerance, i_gravity, i_zeroTolerance ),
newtonTol(i_newtonTolerance),
maxNumberOfNewtonIterations(i_maxNumberOfNewtonIterations) {
#ifndef NDEBUG
#ifndef SUPPRESS_SOLVER_DEBUG_OUTPUT
//print some information about the used solver
std::cout << " *** solver::AugRie created" << std::endl
<< " zeroTolerance=" << zeroTol << std::endl
<< " gravity=" << g << std::endl
<< " dryTolerance=" << dryTol << std::endl
<< " newtonTolerance=" << newtonTol << std::endl
<< " maxNumberNumberOfNewtonIterations=" << maxNumberOfNewtonIterations << std::endl
<< "\n optional features:"
#ifdef correctrarefactions
<< " correctrarefactions"
#endif
#ifdef complexsteadystatewave
<< " complexsteadystatewave"
#endif
<< "\n ***\n\n";
#endif
#endif
}
//declare variables which are used over and over again
#if 0
T sqrt_g_h[2];
T sqrt_h[2];
#define sqrt_g_hLeft (sqrt_g_h[0])
#define sqrt_g_hRight (sqrt_g_h[1])
#define sqrt_hLeft (sqrt_h[0])
#define sqrt_hRight (sqrt_h[1])
#else
T sqrt_g_hLeft;
T sqrt_g_hRight;
T sqrt_hLeft;
T sqrt_hRight;
#endif
T sqrt_g;
/**
* Compute net updates for the left/right cell of the edge.
*
* maxWaveSpeed will be set to the maximum (linearized) wave speed => CFL
*/
void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
// store parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight );
//set speeds to zero (will be determined later)
uLeft = uRight = 0.;
//reset net updates and the maximum wave speed
o_hUpdateLeft = o_hUpdateRight = o_huUpdateLeft = o_huUpdateRight = (T)0.;
o_maxWaveSpeed = (T)0.;
//determine the wet/dry state and compute local variables correspondingly
determineWetDryState();
if (wetDryState == DryDry) //nothing to do in a dry region
return;
//precompute some terms which are fixed during
//the computation after some specific point
sqrt_g = std::sqrt(g);
sqrt_hLeft = std::sqrt(hLeft);
sqrt_hRight = std::sqrt(hRight);
sqrt_g_hLeft = sqrt_g*sqrt_hLeft;
sqrt_g_hRight = sqrt_g*sqrt_hRight;
//where to store the three waves
T fWaves[3][2];
//and their speeds
T waveSpeeds[3];
//compute the augmented decomposition
// (thats the place where the computational work is done..)
computeWaveDecomposition( fWaves,
waveSpeeds );
//compute the updates from the three propagating waves
//A^-\delta Q = \sum{s[i]<0} \beta[i] * r[i] = A^-\delta Q = \sum{s[i]<0} Z^i
//A^+\delta Q = \sum{s[i]>0} \beta[i] * r[i] = A^-\delta Q = \sum{s[i]<0} Z^i
for (int waveNumber = 0; waveNumber < 3; waveNumber++) {
if (waveSpeeds[waveNumber] < -zeroTol) { //left going
o_hUpdateLeft += fWaves[waveNumber][0];
o_huUpdateLeft += fWaves[waveNumber][1];
}
else if (waveSpeeds[waveNumber] > zeroTol) { //right going
o_hUpdateRight += fWaves[waveNumber][0];
o_huUpdateRight += fWaves[waveNumber][1];
}
else { //TODO: this case should not happen mathematically, but it does. Where is the bug? Machine accuracy only?
o_hUpdateLeft += (T).5*fWaves[waveNumber][0];
o_huUpdateLeft += (T).5*fWaves[waveNumber][1];
o_hUpdateRight += (T).5*fWaves[waveNumber][0];
o_huUpdateRight += (T).5*fWaves[waveNumber][1];
}
//no wave speeds => zero strength fWaves
// assert( std::fabs(fWaves[waveNumber][0]) < zeroTol );
// assert( std::fabs(fWaves[waveNumber][1]) < zeroTol );
}
#ifndef NDEBUG
if(wetDryState == DryWetWall)
assert( std::fabs(o_hUpdateLeft) < zeroTol && std::fabs(o_huUpdateLeft) < zeroTol );
else if(wetDryState == WetDryWall)
assert( std::fabs(o_hUpdateRight) < zeroTol && std::fabs(o_huUpdateRight) < zeroTol );
#endif
//compute maximum wave speed (-> CFL-condition)
waveSpeeds[0] = std::fabs(waveSpeeds[0]);
waveSpeeds[1] = std::fabs(waveSpeeds[1]);
waveSpeeds[2] = std::fabs(waveSpeeds[2]);
o_maxWaveSpeed = std::max(waveSpeeds[0], waveSpeeds[1]);
o_maxWaveSpeed = std::max(o_maxWaveSpeed, waveSpeeds[2]);
}
private:
/**
* Determine the wet/dry state and set member variables accordingly.
*/
void determineWetDryState() {
//compute speeds or set them to zero (dry cells)
if (hLeft > dryTol) {
uLeft = huLeft / hLeft;
}
else {
bLeft += hLeft;
hLeft = huLeft = uLeft = 0;
}
if (hRight > dryTol) {
uRight = huRight / hRight;
}
else {
bRight += hRight;
hRight = huRight = uRight = 0;
}
//test for simple wet/wet case since this is most probably the
//most frequently executed branch
if (hLeft >= dryTol && hRight >= dryTol) {
wetDryState = WetWet;
}
//check for the dry/dry-case
else if (hLeft < dryTol && hRight < dryTol)
wetDryState = DryDry;
//we have a shoreline: one cell dry, one cell wet
//check for simple inundation problems
// (=> dry cell lies lower than the wet cell)
else if (hLeft < dryTol && hRight + bRight > bLeft)
wetDryState = DryWetInundation;
else if (hRight < dryTol && hLeft + bLeft > bRight)
wetDryState = WetDryInundation;
//dry cell lies higher than the wet cell
else if (hLeft < dryTol) {
//lets check if the momentum is able to overcome the difference in height
// => solve homogeneous Riemann-problem to determine the middle state height
// which would arise if there is a wall (wall-boundary-condition)
// \cite[ch. 6.8.2]{george2006finite})
// \cite[ch. 5.2]{george2008augmented}
computeMiddleState( hRight, hRight,
-uRight, uRight,
-huRight, huRight,
maxNumberOfNewtonIterations );
if (hMiddle + bRight > bLeft) {
//momentum is large enough, continue with the original values
// bLeft = hMiddle + bRight;
wetDryState = DryWetWallInundation;
}
else {
//momentum is not large enough, use wall-boundary-values
hLeft = hRight;
uLeft = -uRight;
huLeft = -huRight;
bLeft = bRight = (T)0.;
wetDryState = DryWetWall;
}
}
else if (hRight < dryTol) {
//lets check if the momentum is able to overcome the difference in height
// => solve homogeneous Riemann-problem to determine the middle state height
// which would arise if there is a wall (wall-boundary-condition)
// \cite[ch. 6.8.2]{george2006finite})
// \cite[ch. 5.2]{george2008augmented}
computeMiddleState( hLeft, hLeft,
uLeft, -uLeft,
huLeft, -huLeft,
maxNumberOfNewtonIterations );
if (hMiddle + bLeft > bRight) {
//momentum is large enough, continue with the original values
// bRight = hMiddle + bLeft;
wetDryState = WetDryWallInundation;
}
else {
hRight = hLeft;
uRight = -uLeft;
huRight = -huLeft;
bRight = bLeft = (T)0.;
wetDryState = WetDryWall;
}
}
//done with all cases
else assert(false);
//limit the effect of the source term if there is a "wall"
//\cite[end of ch. 5.2?]{george2008augmented}
//\cite[rpn2ez_fast_geo.f][levequeclawpack]
if ( wetDryState == DryWetWallInundation )
bLeft = hRight + bRight;
else if( wetDryState == WetDryWallInundation )
bRight = hLeft + bLeft;
}
/**
* Compute the augmented wave decomposition.
*
* @param o_fWaves will be set to: Decomposition into f-Waves.
* @param o_waveSpeeds will be set to: speeds of the linearized waves (eigenvalues).
*/
inline void computeWaveDecomposition( T o_fWaves[3][2],
T o_waveSpeeds[3] ) {
//compute eigenvalues of the jacobian matrices in states Q_{i-1} and Q_{i} (char. speeds)
T characteristicSpeeds[2];
characteristicSpeeds[0] = uLeft - sqrt_g_hLeft;
characteristicSpeeds[1] = uRight + sqrt_g_hRight;
//compute "Roe speeds"
T hRoe = (T).5 * (hRight + hLeft);
T uRoe = uLeft * sqrt_hLeft + uRight * sqrt_hRight;
uRoe /= sqrt_hLeft + sqrt_hRight;
T roeSpeeds[2];
//optimization for dumb compilers
T sqrt_g_hRoe = std::sqrt(g*hRoe);
roeSpeeds[0] = uRoe - sqrt_g_hRoe;
roeSpeeds[1] = uRoe + sqrt_g_hRoe;
//compute the middle state of the homogeneous Riemann-Problem
if(wetDryState != WetDryWall && wetDryState != DryWetWall) { //case WDW and DWW was computed in determineWetDryState already
computeMiddleState( hLeft, hRight,
uLeft, uRight,
huLeft, huRight
);
}
//compute extended eindfeldt speeds (einfeldt speeds + middle state speeds)
// \cite[ch. 5.2]{george2008augmented}, \cite[ch. 6.8]{george2006finite}
T extEinfeldtSpeeds[2]= {(T)0, (T)0};
if( wetDryState == WetWet ||
wetDryState == WetDryWall ||
wetDryState == DryWetWall ) {
extEinfeldtSpeeds[0] = std::min(characteristicSpeeds[0], roeSpeeds[0]);
extEinfeldtSpeeds[0] = std::min(extEinfeldtSpeeds[0], middleStateSpeeds[1]);
extEinfeldtSpeeds[1] = std::max(characteristicSpeeds[1], roeSpeeds[1]);
extEinfeldtSpeeds[1] = std::max(extEinfeldtSpeeds[1], middleStateSpeeds[0]);
}
else if (hLeft < dryTol) { //ignore undefined speeds
extEinfeldtSpeeds[0] = std::min(roeSpeeds[0], middleStateSpeeds[1]);
extEinfeldtSpeeds[1] = std::max(characteristicSpeeds[1], roeSpeeds[1]);
assert(middleStateSpeeds[0] < extEinfeldtSpeeds[1]);
}
else if (hRight < dryTol) { //ignore undefined speeds
extEinfeldtSpeeds[0] = std::min(characteristicSpeeds[0], roeSpeeds[0]);
extEinfeldtSpeeds[1] = std::max(roeSpeeds[1], middleStateSpeeds[0]);
assert(middleStateSpeeds[1] > extEinfeldtSpeeds[0]);
}
else {
assert(false);
}
//HLL middle state
// \cite[theorem 3.1]{george2006finite}, \cite[ch. 4.1]{george2008augmented}
T hLLMiddleHeight = huLeft - huRight + extEinfeldtSpeeds[1] * hRight - extEinfeldtSpeeds[0] * hLeft;
hLLMiddleHeight /= extEinfeldtSpeeds[1] - extEinfeldtSpeeds[0];
hLLMiddleHeight = std::max(hLLMiddleHeight, (T)0.);
//define eigenvalues
T eigenValues[3];
eigenValues[0] = extEinfeldtSpeeds[0];
//eigenValues[1] --> corrector wave
eigenValues[2] = extEinfeldtSpeeds[1];
//define eigenvectors
T eigenVectors[3][3];
//set first and third eigenvector
eigenVectors[0][0] = (T)1;
eigenVectors[0][2] = (T)1;
eigenVectors[1][0] = eigenValues[0];
eigenVectors[1][2] = eigenValues[2];
eigenVectors[2][0] = eigenValues[0]*eigenValues[0];
eigenVectors[2][2] = eigenValues[2]*eigenValues[2];
//compute rarefaction corrector wave
// \cite[ch. 6.7.2]{george2006finite}, \cite[ch. 5.1]{george2008augmented}
bool strongRarefaction = false;
#ifdef correctrarefactions
if ( (riemannStructure == ShockRarefaction ||
riemannStructure == RarefactionShock ||
riemannStructure == RarefactionRarefaction) &&
hMiddle > dryTol ) { //limit to ensure non-negative depth
//TODO: GeoClaw, riemann_aug_JCP; No explicit boundaries for "strong rarefaction" in literature?
T rareBarrier[2] = {.5, .9};
//lower rare barrier in the case of a transsonic rarefaction
if ( (riemannStructure == RarefactionShock || riemannStructure == RarefactionRarefaction) &&
eigenValues[0]*middleStateSpeeds[0] < (T).0 ) { //transsonic rarefaction, first wave family
rareBarrier[0] = (T).2;
}
else if ( (riemannStructure == ShockRarefaction || riemannStructure == RarefactionRarefaction) &&
eigenValues[2]*middleStateSpeeds[1] < (T)0. ) { //transsonic rarefaction, second wave family
rareBarrier[0] = (T).2;
}
T sqrt_g_hMiddle = std::sqrt(g*hMiddle);
//determine the max. rarefaction size (distance between head and tail)
T rareFactionSize[2];
rareFactionSize[0] = (T)3. * (sqrt_g_hLeft - sqrt_g_hMiddle);
rareFactionSize[1] = (T)3. * (sqrt_g_hRight - sqrt_g_hMiddle);
T maxRareFactionSize = std::max(rareFactionSize[0], rareFactionSize[1]);
//set the eigenvalue of the corrector wave in the case of a "strong rarefaction"
if ( maxRareFactionSize > rareBarrier[0] * (eigenValues[2] - eigenValues[0]) &&
maxRareFactionSize < rareBarrier[1] * (eigenValues[2] - eigenValues[0])
) {
strongRarefaction = true;
if (rareFactionSize[0] > rareFactionSize[1])
eigenValues[1] = middleStateSpeeds[0];
else
eigenValues[1] = middleStateSpeeds[1];
}
//TODO: implemented in clawpack, why?
// if ( hMiddle < std::min(hLeft, hRight)/5.) { //middle state in an HLL solve
// strongRarefaction = false;
// }
}
#endif
//set 2nd eigenvector
if(strongRarefaction == false) {
eigenValues[1] = (T).5*(eigenValues[0]+eigenValues[2]);
eigenVectors[0][1] = 0.;
eigenVectors[1][1] = 0.;
eigenVectors[2][1] = 1.;
}
else {
eigenVectors[0][1] = (T)1.;
eigenVectors[1][1] = eigenValues[1];
eigenVectors[2][1] = eigenValues[1]*eigenValues[1];
}
//compute the jump in state
T rightHandSide[3];
rightHandSide[0] = hRight - hLeft;
rightHandSide[1] = huRight - huLeft;
rightHandSide[2] = huRight * uRight + (T).5 * g * hRight * hRight
-( huLeft * uLeft + (T).5 * g * hLeft * hLeft );
//compute steady state wave
// \cite[ch. 4.2.1 \& app. A]{george2008augmented}, \cite[ch. 6.2 \& ch. 4.4]{george2006finite}
T steadyStateWave[2];
T hBar = (hLeft + hRight)*(T).5;
#ifdef complexsteadystatewave
T lLambdaBar = (uLeft + uRight)*(uLeft + uRight)*.25 - g*hBar;
T lLambdaTilde = std::max((T)0., uLeft*uRight) - g*hBar;
//near sonic as defined in geoclaw (TODO: literature?)
if( ( std::fabs(lLambdaBar) < zeroTol ) ||
( lLambdaBar*lLambdaTilde < zeroTol ) ||
( lLambdaBar*eigenValues[0]*eigenValues[1] < zeroTol ) ||
( std::min( std::fabs( eigenValues[0]), std::fabs(eigenValues[2]) ) < zeroTol ) ||
( eigenValues[0] < (T)0. && middleStateSpeeds[0] > (T)0. ) ||
( eigenValues[2] > (T)0. && middleStateSpeeds[1] < (T)0. ) ||
( (uLeft + sqrt(g*hLeft)) * (uRight+sqrt(g*hRight)) < (T)0. ) ||
( (uLeft - sqrt(g*hLeft)) * (uRight-sqrt(g*hRight)) < (T)0. ) ) {
#endif
steadyStateWave[0] = -(bRight - bLeft);
steadyStateWave[1] = -g * hBar * (bRight - bLeft);
#ifdef complexsteadystatewave
}
else {
steadyStateWave[0] = g * (hBar / lLambdaBar) * (bRight - bLeft);
T hTilde = hBar * lLambdaTilde / lLambdaBar;
//set bounds for problems far from steady state
hTilde = std::max(std::min(hLeft, hRight), hTilde);
hTilde = std::min(std::max(hLeft, hRight), hTilde);
steadyStateWave[1] = -g*hTilde*(bRight - bLeft);
}
#endif
//preserve depth-positivity
// \cite[ch. 6.5.2]{george2006finite}, \cite[ch. 4.2.3]{george2008augmented}
if(eigenValues[0] < -zeroTol && eigenValues[2] > zeroTol) { //subsonic
steadyStateWave[0] = std::max(steadyStateWave[0], hLLMiddleHeight*(eigenValues[2]-eigenValues[0])/eigenValues[0]);
steadyStateWave[0] = std::min(steadyStateWave[0], hLLMiddleHeight*(eigenValues[2]-eigenValues[0])/eigenValues[2]);
}
else if(eigenValues[0] > zeroTol) { //supersonic right TODO: motivation?
steadyStateWave[0] = std::max(steadyStateWave[0], -hLeft);
steadyStateWave[0] = std::min(steadyStateWave[0], hLLMiddleHeight*(eigenValues[2]-eigenValues[0])/eigenValues[0]);
}
else if(eigenValues[2] < -zeroTol) { //supersonic left TODO: motivation?
steadyStateWave[0] = std::max(steadyStateWave[0], hLLMiddleHeight*(eigenValues[2]-eigenValues[0])/eigenValues[2]);
steadyStateWave[0] = std::min(steadyStateWave[0], hRight);
}
//Limit the effect of the source term
// \cite[ch. 6.4.2]{george2006finite}
steadyStateWave[1] = std::min(steadyStateWave[1], g*std::max(-hLeft*(bRight-bLeft) , -hRight*(bRight-bLeft)));
steadyStateWave[1] = std::max(steadyStateWave[1], g*std::min(-hLeft*(bRight-bLeft) , -hRight*(bRight-bLeft)));
//no source term in the case of a wall
if( wetDryState == WetDryWall || wetDryState == DryWetWall ) {
assert(std::fabs(steadyStateWave[0])<zeroTol);
assert(std::fabs(steadyStateWave[1])<zeroTol);
}
rightHandSide[0] -= steadyStateWave[0];
//rightHandSide[1]: no source term
rightHandSide[2] -= steadyStateWave[1];
//everything is ready, solve the equations!
T beta[3];
solveLinearEquation(eigenVectors, rightHandSide, beta);
//compute f-waves and wave-speeds
if (wetDryState == WetDryWall) { //zero ghost updates (wall boundary)
//care about the left going wave (0) only
o_fWaves[0][0] = beta[0] * eigenVectors[1][0];
o_fWaves[0][1] = beta[0] * eigenVectors[2][0];
//set the rest to zero
o_fWaves[1][0] = o_fWaves[1][1] = (T)0.;
o_fWaves[2][0] = o_fWaves[2][1] = (T)0.;
o_waveSpeeds[0] = eigenValues[0];
o_waveSpeeds[1] = o_waveSpeeds[2] = (T)0.;
assert(eigenValues[0] < zeroTol);
}
else if (wetDryState == DryWetWall) { //zero ghost updates (wall boundary)
//care about the right going wave (2) only
o_fWaves[2][0] = beta[2] * eigenVectors[1][2];
o_fWaves[2][1] = beta[2] * eigenVectors[2][2];
//set the rest to zero
o_fWaves[0][0] = o_fWaves[0][1] = (T)0.;
o_fWaves[1][0] = o_fWaves[1][1] = (T)0.;
o_waveSpeeds[2] = eigenValues[2];
o_waveSpeeds[0] = o_waveSpeeds[1] = 0.;
assert(eigenValues[2] > -zeroTol);
}
else {
//compute f-waves (default)
for (int waveNumber = 0; waveNumber < 3; waveNumber++) {
o_fWaves[waveNumber][0] = beta[waveNumber] * eigenVectors[1][waveNumber]; //select 2nd and
o_fWaves[waveNumber][1] = beta[waveNumber] * eigenVectors[2][waveNumber]; //3rd component of the augmented decomposition
}
o_waveSpeeds[0] = eigenValues[0];
o_waveSpeeds[1] = eigenValues[1];
o_waveSpeeds[2] = eigenValues[2];
}
}
/**
* Computes the middle state of the homogeneous Riemann-problem.
* -> (\cite[ch. 13]{leveque2002finite})
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_maxNumberOfNewtonIterations maximum number of Newton iterations.
*/
inline void computeMiddleState( const T &i_hLeft, const T &i_hRight,
const T &i_uLeft, const T &i_uRight,
const T &i_huLeft, const T &i_huRight,
const int &i_maxNumberOfNewtonIterations = 1 ) {
//set everything to zero
hMiddle = (T)0.;
middleStateSpeeds[0] = (T)0.;
middleStateSpeeds[1] = (T)0.;
//compute local square roots
//(not necessarily the same ones as in computeNetUpdates!)
T l_sqrt_g_hRight = std::sqrt(g*i_hRight);
T l_sqrt_g_hLeft = std::sqrt(g*i_hLeft);
//single rarefaction in the case of a wet/dry interface
if (i_hLeft < dryTol) {
middleStateSpeeds[1] = middleStateSpeeds[0] = i_uRight - (T)2*l_sqrt_g_hRight;
riemannStructure = DrySingleRarefaction;
return;
}
else if (i_hRight < dryTol) {
middleStateSpeeds[0] = middleStateSpeeds[1] = i_uLeft + (T)2*l_sqrt_g_hLeft;
riemannStructure = SingleRarefactionDry;
return;
}
//determine the wave structure of the Riemann-problem
riemannStructure = determineRiemannStructure( i_hLeft, i_hRight,
i_uLeft, i_uRight );
//will be computed later
T sqrt_g_hMiddle = 0.;
if (riemannStructure == ShockShock) {
/*compute All-Shock Riemann Solution
* \cite[ch. 13.7]{leveque2002finite}
*
*compute middle state h_m
* => Solve non-linear scalar equation by Newton's method
* u_l - (h_m - h_l) \sqrt{\frac{g}{2} \left( \frac{1}{h_m} + \frac{1}{h_l} \right) }
* = u_r + (h_m - h_r) \sqrt{\frac{g}{2} \left( \frac{1}{h_m} + \frac{1}{h_r} \right) }
*
* Therefore determine the root of phi_{ss}:
*\begin{equation}
* \begin{matrix}
* \phi_{ss}(h) =&& u_r - u_l +
* (h-h_l) \sqrt{
* \frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_l} \right)
* } \\
* && +(h-h_r) \sqrt{
* \frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_r} \right)
* }
* \end{matrix}
*\end{equation}
*
*\begin{equation}
* \begin{matrix}
* \phi_{ss}'(h) = &&\sqrt{\frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_l} \right) }
* +\sqrt{\frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_r} \right) }\\
* && -\frac{g}{4}
* \frac{h-h_l}
* {
* h^2\sqrt{\frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_l} \right) }
* }-
* \frac{g}{4}
* \frac{h-h_r}
* {
* h^2\sqrt{\frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_r} \right) }
* }
* \end{matrix}
*\end{equation}
*/
// hMiddle = (hLeft + hRight)*(T)0.618; //first estimate
hMiddle = std::min(i_hLeft, i_hRight);
T l_sqrtTermH[2] = {0,0};
for (int i = 0; i < i_maxNumberOfNewtonIterations; i++) {
// sqrtTermHLow = std::sqrt((T).5 * g * ((T)1/hMiddle + (T)1/hLeft));
l_sqrtTermH[0] = std::sqrt((T).5 * g * ((hMiddle+i_hLeft)/(hMiddle*i_hLeft)));
// sqrtTermHHigh = std::sqrt((T).5 * g * ((T)1/hMiddle + (T)1/hRight));
l_sqrtTermH[1] = std::sqrt((T).5 * g * ((hMiddle+i_hRight)/(hMiddle*i_hRight)));
T phi = i_uRight - i_uLeft + (hMiddle - i_hLeft) * l_sqrtTermH[0] + (hMiddle - i_hRight) * l_sqrtTermH[1];
if (std::fabs(phi) < newtonTol)
break;
T derivativePhi = l_sqrtTermH[0] + l_sqrtTermH[1]
- (T).25*g*(hMiddle - i_hLeft) / (l_sqrtTermH[0]*hMiddle*hMiddle)
- (T).25*g*(hMiddle - i_hRight) / (l_sqrtTermH[1]*hMiddle*hMiddle);
hMiddle = hMiddle - phi/derivativePhi; //Newton step
assert(hMiddle >= dryTol);
// if(i == i_maxNumberOfNewtonIterations-1) {
// std::cerr << "Newton-Method did not converge" << std::endl;
// std::cerr << "std::fabs(phi): " << std::fabs(phi) << std::endl;
// std::cerr << "hMiddle: " << hMiddle << std::endl;
// assert(false);
// }
}
sqrt_g_hMiddle = std::sqrt(g*hMiddle);
//compute middle speed u_m
//\begin{equation}
// \label{eq:hmshock1stfamsimp}
// u_m = u_l - (h_m - h_l) \sqrt{\frac{g}{2} \left( \frac{1}{h_m} + \frac{1}{h_l} \right) }
//\end{equation}
//
//\begin{equation}
// \label{eq:hmshock2ndfamsimp}
// u_m = u_r + (h_m - h_r) \sqrt{\frac{g}{2} \left( \frac{1}{h_m} + \frac{1}{h_r} \right) }
//\end{equation}
// T uMiddleEstimates[2];
// uMiddleEstimates[0] = uLeft - (hMiddle - hLeft) * l_sqrtTermH[0];
// uMiddleEstimates[1] = i_uRight + (hMiddle - hRight) * l_sqrtTermH[1];
// uMiddle = (T).5 * (uMiddleEstimates[0] + uMiddleEstimates[1]);
//middle state speeds as they are implemented in clawpack, TODO: why?
// middleStateSpeeds[0] = uMiddleEstimates[0] - sqrt_g_hMiddle;
// middleStateSpeeds[1] = uMiddleEstimates[1] + sqrt_g_hMiddle;
}
if (riemannStructure == RarefactionRarefaction) {
//Compute All-Rarefaction Riemann Solution
// \cite[ch. 13.8.6]{leveque2002finite}
//compute middle state height h_m
hMiddle = std::max((T)0., i_uLeft - i_uRight + (T)2.*(l_sqrt_g_hLeft + l_sqrt_g_hRight)); //std::max -> Text after formula (13.56), page 279
hMiddle = (T)1/((T)16*g)* hMiddle * hMiddle;
sqrt_g_hMiddle = std::sqrt(g*hMiddle);
//middle state speeds as they are implemented in clawpack, why?
// middleStateSpeeds[0] = uLeft + (T)2.*l_sqrt_g_hLow - (T)3.*sqrt_g_hMiddle;
// middleStateSpeeds[1] = i_uRight - (T)2.*l_sqrt_g_hHigh + (T)3.*sqrt_g_hMiddle;
}
if (riemannStructure == ShockRarefaction || riemannStructure == RarefactionShock) {
//compute dam-break Riemann-solution
//TODO: reference
T hMin, hMax;
if (riemannStructure == ShockRarefaction) {
hMin = i_hLeft;
hMax = i_hRight;
}
else {
hMin = i_hRight;
hMax = i_hLeft;
}
//hMiddle = (hLeft + hRight)*(T)0.618; //first estimate
hMiddle = hMin;
sqrt_g_hMiddle = std::sqrt(g*hMiddle);
T sqrt_g_hMax = std::sqrt(g*hMax);
for (int i = 0; i < i_maxNumberOfNewtonIterations; i++) {
/*
*compute middle state h_m
* => Solve non-linear scalar equation by Newton's method
*
* Therefore determine the root of phi_{sr}/phi_{rs}:
*\begin{equation}
* \begin{matrix}
* h_{min} = \min(h_l, h_r)\\
* h_{max} = \max(h_l, h_r)
* \end{matrix}
*\end{equation}
*\begin{equation}
* \begin{matrix}
* \phi_{sr}(h) = \phi_{rs}(h) =&& u_r - u_l + (h - h_{min}) \sqrt{
* \frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_{min}} \right)
* } \\
* && + 2 (\sqrt{gh} - \sqrt{gh_{max}})
* \end{matrix}
*\end{equation}
*\begin{equation}
* \phi'_{sr}(h) = \phi'_{rs}(h) = \sqrt{\frac{g}{2} \left( \frac{1}{h} + \frac{1}{h_{min}} \right) }
* -\frac{g}{4} \frac{h-h_{min}}
* { h^2
* \sqrt{
* \frac{g}{2} \left(\frac{1}{h} + \frac{1}{h_{min}} \right)
* }
* }
* + \sqrt{\frac{g}{h}}
*\end{equation}
*/
T sqrtTermHMin = std::sqrt( (T).5*g* ((hMiddle+hMin)/(hMiddle*hMin)) );
T phi = i_uRight - i_uLeft + (hMiddle - hMin) * sqrtTermHMin + (T)2*(sqrt_g_hMiddle - sqrt_g_hMax);
if (std::fabs(phi) < newtonTol)
break;
T derivativePhi = sqrtTermHMin - (T).25*g * (hMiddle - hMin) / (hMiddle * hMiddle * sqrtTermHMin) + sqrt_g/sqrt_g_hMiddle;
hMiddle = hMiddle - phi/derivativePhi; //Newton step
if (hMiddle < hMin) {
std::cout << phi << std::endl;
std::cout << derivativePhi << std::endl;
std::cerr << "hMiddle(" << hMiddle << ") < hMin(" << hMin << ")" << std::endl;
assert(false);
}
// if(i == i_maxNumberOfNewtonIterations-1) {
// std::cerr << "Newton-Method did not converge" << std::endl;
// std::cerr << "std::fabs(phi): " << std::fabs(phi) << std::endl;
// std::cerr << "hMiddle: " << hMiddle << std::endl;
// assert(false);
// }
sqrt_g_hMiddle = std::sqrt(g*hMiddle);
}
// //middle state speeds as they are implemented in clawpack, TODO: why?
// if (riemannStructure == ShockRarefaction) {
// uMiddle = i_uRight - (T)2.*( l_sqrt_g_hHigh - sqrt_g_hMiddle );
// middleStateSpeeds[0] = i_uRight - (T)2.*l_sqrt_g_hHigh + sqrt_g_hMiddle;
// middleStateSpeeds[1] = i_uRight - (T)2.*l_sqrt_g_hHigh + (T)3.*sqrt_g_hMiddle;
// }
// else {
// uMiddle = uLeft + (T)2.*( l_sqrt_g_hLow - sqrt_g_hMiddle );
// middleStateSpeeds[0] = uLeft + (T)2.*l_sqrt_g_hLow - (T)3.*sqrt_g_hMiddle;
// middleStateSpeeds[1] = uLeft + (T)2.*l_sqrt_g_hLow - sqrt_g_hMiddle;
// }
}
middleStateSpeeds[0] = i_uLeft + (T)2.*l_sqrt_g_hLeft - (T)3.*sqrt_g_hMiddle;
middleStateSpeeds[1] = i_uRight - (T)2.*l_sqrt_g_hRight + (T)3.*sqrt_g_hMiddle;
assert(hMiddle >= 0);
}
/**
* Determine the Riemann-structure of a given problem.
* -> \cite[theorem 4.2]{george2006finite}, \cite[appendix B]{george2008augmented}
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
*
* @return Riemann-structure of a given problem.
*/
inline RiemannStructure determineRiemannStructure( const T &i_hLeft, const T &i_hRight,
const T &i_uLeft, const T &i_uRight ) const {
T hMin = std::min(i_hLeft, i_hRight);
T hMax = std::max(i_hLeft, i_hRight);
T uDif = i_uRight - i_uLeft;
if( 0 <= (T)2.0*(std::sqrt(g*hMin) - std::sqrt(g*hMax)) + uDif)
return RarefactionRarefaction;
if( (hMax - hMin) * std::sqrt(g*(T)0.5*( 1/hMax + 1/hMin )) + uDif <= 0 )
return ShockShock;
if( i_hLeft < i_hRight )
return ShockRarefaction;
return RarefactionShock;
}
/**
* Solve the linear equation:
* A * x = b with A \in \mathbb{R}^{3\times3}, x,b \in \mathbb{R}^3
*
* @param i_matrix the matrix
* @param i_b right hand side
* @param o_x solution
*/
static inline void solveLinearEquation( const T i_matrix[3][3],
const T i_b[3],
T o_x[3] ) {
//#if 1
// compute inverse of 3x3 matrix
const T m[3][3] =
{ { (i_matrix[1][1]*i_matrix[2][2] - i_matrix[1][2]*i_matrix[2][1]), -(i_matrix[0][1]*i_matrix[2][2] - i_matrix[0][2]*i_matrix[2][1]), (i_matrix[0][1]*i_matrix[1][2] - i_matrix[0][2]*i_matrix[1][1]) },
{ -(i_matrix[1][0]*i_matrix[2][2] - i_matrix[1][2]*i_matrix[2][0]), (i_matrix[0][0]*i_matrix[2][2] - i_matrix[0][2]*i_matrix[2][0]), -(i_matrix[0][0]*i_matrix[1][2] - i_matrix[0][2]*i_matrix[1][0]) },
{ (i_matrix[1][0]*i_matrix[2][1] - i_matrix[1][1]*i_matrix[2][0]), -(i_matrix[0][0]*i_matrix[2][1] - i_matrix[0][1]*i_matrix[2][0]), (i_matrix[0][0]*i_matrix[1][1] - i_matrix[0][1]*i_matrix[1][0]) }
};
T d = (i_matrix[0][0]*m[0][0] + i_matrix[0][1]*m[1][0] + i_matrix[0][2]*m[2][0]);
#ifndef NDEBUG
if (std::fabs(d) < 0.000000001) {
std::cerr << "Division close to zero!" << std::endl;
std::cout << "Matrix: " << std::endl;
std::cout << i_matrix[0][0] << ", " << i_matrix[0][1] << ", " << i_matrix[0][2] << std::endl;
std::cout << i_matrix[1][0] << ", " << i_matrix[1][1] << ", " << i_matrix[1][2] << std::endl;
std::cout << i_matrix[2][0] << ", " << i_matrix[2][1] << ", " << i_matrix[2][2] << std::endl;
std::cout << "b: " << std::endl;
std::cout << i_b[0] << ", " << i_b[1] << ", " << i_b[2] << std::endl;
std::cout << "d: " << d << std::endl;
assert(false);
}
#endif
// m stores not really the inverse matrix, but the inverse multiplied by d
T s = (T)1/d;
// compute m*i_b
o_x[0] = (m[0][0]*i_b[0] + m[0][1]*i_b[1] + m[0][2]*i_b[2])*s;
o_x[1] = (m[1][0]*i_b[0] + m[1][1]*i_b[1] + m[1][2]*i_b[2])*s;
o_x[2] = (m[2][0]*i_b[0] + m[2][1]*i_b[1] + m[2][2]*i_b[2])*s;
// return;
//#else
// T origDet = computeDeterminant(i_matrix);
//
// if (std::fabs(origDet) > zeroTol) {
// T modifiedMatrix[3][3];
//
// for (int column = 0; column < 3; column++)
// {
// memcpy(modifiedMatrix, i_matrix, sizeof(T)*3*3);
//
// //set a column of the matrix to i_b
// modifiedMatrix[0][column] = i_b[0];
// modifiedMatrix[1][column] = i_b[1];
// modifiedMatrix[2][column] = i_b[2];
//
// o_x[column] = computeDeterminant(modifiedMatrix) / origDet;
// }
// }
// else {
// std::cerr << "Warning: Linear dependent eigenvectors! (using Jacobi Solver)" << std::endl;
// std::cerr << "Determinant: " << origDet << std::endl;
// std::cerr << i_matrix[0][0] << "\t" << i_matrix[0][1] << "\t" << i_matrix[0][2] << std::endl;
// std::cerr << i_matrix[1][0] << "\t" << i_matrix[1][1] << "\t" << i_matrix[1][2] << std::endl;
// std::cerr << i_matrix[2][0] << "\t" << i_matrix[2][1] << "\t" << i_matrix[2][2] << std::endl;
//#if 0
// T xTemp[3];
// xTemp[0] = xTemp[1] = xTemp[2] = 0.;
// for (int m = 0; m < 20; m++) {
// for (int row = 0; row < 3; row++) {
// o_x[row] = 0.;
// for (int col = 0; col < 3; col++) {
// if (col != row)
// o_x[row] += i_matrix[row][col]*xTemp[col];
// }
// o_x[row] = (i_b[row] - o_x[row])/i_matrix[row][row];
// }
//
// if (fabs(o_x[0]-xTemp[0]) + fabs(o_x[1]-xTemp[1]) + fabs(o_x[2]-xTemp[2]) < zeroTol*10.)
// break;
// else {
// std::cout << "Error: " << fabs(o_x[0]-xTemp[0]) + fabs(o_x[1]-xTemp[1]) + fabs(o_x[2]-xTemp[2]) << std::endl;
// xTemp[0] = o_x[0];
// xTemp[1] = o_x[1];
// xTemp[2] = o_x[2];
// }
// }
// std::cout << "Solution:" << std::endl;
// std::cout << "\t" << o_x[0] << std::endl;
// std::cout << "x=\t" << o_x[1] << std::endl;
// std::cout << "\t" << o_x[2] << std::endl;
// std::cout << "*********" << std::endl;
// std::cout << "\t" << i_b[0] << std::endl;
// std::cout << "b=\t" << i_b[1] << std::endl;
// std::cout << "\t" << i_b[2] << std::endl;
// std::cout << "***A*x****" << std::endl;
// for (int row = 0; row < 3; row++) {
// std::cout << "\t" <<
// i_matrix[row][0] * o_x[0] +
// i_matrix[row][1] * o_x[1] +
// i_matrix[row][2] * o_x[2] << std::endl;
// }
//#endif
// assert(false);
// }
//#endif
}
//#if 0
// /**
// * Compute the determinant of a 3x3 matrix
// * using formula: |A|=a11 * (a22a33-a32a23) + a12 * (a23a31-a33a21) + a13 * (a21a32-a31a22)
// * |A|=a00 * (a11a22-a21a12) + a01 * (a12a20-a22a10) + a02 * (a10a21-a20a11)
// */
// T computeDeterminant(T matrix[3][3]) const
// {
//
// T determinant = matrix[0][0] * ( matrix[1][1] * matrix[2][2] - matrix[2][1] * matrix[1][2] )
// + matrix[0][1] * ( matrix[1][2] * matrix[2][0] - matrix[2][2] * matrix[1][0] )
// + matrix[0][2] * ( matrix[1][0] * matrix[2][1] - matrix[2][0] * matrix[1][1] );
//
// return determinant;
// }
//#endif
#undef sqrt_g_hLeft
#undef sqrt_g_hRight
#undef sqrt_hLeft
#undef sqrt_hRight
};
#undef complexsteadystatewave
#undef correctrarefactions
#endif /* AUGRIE_HPP_ */
/**
* AugRieGeoClaw.hpp
*
****
**** Augmented Riemann solver which uses the underlying Fortran routines of GeoClaw directly.
****
*
* Created on: Mar 13, 2012
* Last Update: Mar 14, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*
* (Main) Literature:
*
* @webpage{levequeclawpack,
* Author = {LeVeque, R. J.},
* Lastchecked = {Mar, 14, 2011},
* Title = {Clawpack Sofware},
* Url = {https://github.com/clawpack/geoclaw}
*
*
****
*
* Acknowledgments:
* Special thanks go to R.J. LeVeque and D.L. George for publishing their code.
*/
#ifndef AUGRIEGEOCLAW_HPP_
#define AUGRIEGEOCLAW_HPP_
#include <cassert>
#include <cmath>
#include "WavePropagation.hpp"
/**
* Extern declaration of the c_bing_geoclaw_riemann_aug_JCP routine.
*
* Remark: Not constant variables might change during execution.
*
* @param i_maxNumberOfRiemannIterations maximum number Riemann iterations (solver might iterate over the Riemann problem one day, currently fixed to 1)
* @param i_numberOfFWaves number of fWaves (might change to 2 for standard f-Wave solver for example, currently fixed to 3)
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge in normal direction.
* @param i_huRight momentum on the right side of the edge in normal direction.
* @param i_hvLeft momentum on the left side of the edge in parallel direction.
* @param i_hvRight momentum on the right side of the edge in parallel direction.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
* @param i_dryTol dry tolerance (definition of wet/dry cells).
* @param i_g gravity constant (typically 9.81).
* @param o_netUpdatesLeft will be set to: Net-update for the height(0)/normal momentum(1)/parallel momentum(2) of the cell on the left side of the edge.
* @param o_netUpdatesRight will be set to: Net-update for the height(0)/normal momentum(1)/parallel momentum(2) of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
extern "C" void c_bind_geoclaw_riemann_aug_JCP( const int &i_maxNumberOfRiemannIterations, const int &i_numberOfFWaves,
double &i_hLeft, double &i_hRight,
double &i_huLeft, double &i_huRight,
double &i_hvLeft, double &i_hvRight,
double &i_bLeft, double &i_bRight,
const double &i_dryTol, const double &i_g,
double o_netUpdatesLeft[3], double o_netUpdatesRight[3],
double &o_maxWaveSpeed);
namespace solver {
template <typename T> class AugRieGeoClaw;
}
/**
* Augmented Riemann solver which uses the underlying Fortran routines of GeoClaw directly.
*
* T should be double or float. (currently fixed to double precision)
*/
template <typename T> class solver::AugRieGeoClaw: public WavePropagation<T> {
//private:
//use nondependent names (template base class)
using solver::WavePropagation<T>::zeroTol;
using solver::WavePropagation<T>::g;
using solver::WavePropagation<T>::dryTol;
using solver::WavePropagation<T>::hLeft;
using solver::WavePropagation<T>::hRight;
using solver::WavePropagation<T>::huLeft;
using solver::WavePropagation<T>::huRight;
using solver::WavePropagation<T>::bLeft;
using solver::WavePropagation<T>::bRight;
using solver::WavePropagation<T>::uLeft;
using solver::WavePropagation<T>::uRight;
using solver::WavePropagation<T>::storeParameters;
//! momentum on the left side of the edge (could change during execution) in parallel direction.
T hvLeft;
//! momentum on the right side of the edge (could change during execution) in parallel direction.
T hvRight;
//! number of iterations over the Riemann problem (not used)
const int maxNumberOfRiemannIterations;
/**
* Implemented within the GeoClaw-Fortran routines. Not used here.
*/
void determineWetDryState() {assert(false);}
/**
* Store parameters to member variables.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge in normal direction.
* @param i_huRight momentum on the right side of the edge in normal direction.
* @param i_hvLeft momentum on the left side of the edge in parallel direction.
* @param i_hvRight momentum on the right side of the edge in parallel direction.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*/
inline void storeParameters( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_hvLeft, const T &i_hvRight,
const T &i_bLeft, const T &i_bRight ) {
//store common parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight );
hvLeft = i_hvLeft;
hvRight = i_hvRight;
}
public:
/**
* Constructor of the GeoClaw Augmented Riemann solver with optional parameters.
*
* @param i_dryTolerance numerical definition of "dry".
* @param i_gravity gravity constant.
* @param i_zeroTolerance numerical definition of zero (currently not used).
* @param i_maxNumberOfRiemannIterations maximum number Riemann iterations (solver might iterate over the Riemann problem one day, currently fixed to 1)
*/
AugRieGeoClaw( T i_dryTolerance = (T) 0.01,
T i_gravity = (T) 9.81,
T i_zeroTolerance = (T) 0.000000001,
int i_maxNumberOfRiemannIterations = 1 ):
WavePropagation<T>( i_dryTolerance, i_gravity, i_zeroTolerance ),
maxNumberOfRiemannIterations(i_maxNumberOfRiemannIterations){};
/**
* Not implemented.
*/
void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
//not implemented
assert(false);
}
/**
* Compute net updates for the cell on the left/right side of the edge.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge in normal direction.
* @param i_huRight momentum on the right side of the edge in normal direction.
* @param i_hvLeft momentum on the left side of the edge in parallel direction.
* @param i_hvRight momentum on the right side of the edge in parallel direction.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge in normal direction.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge in normal direction.
* @param o_hvUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge in parallel direction.
* @param o_hvUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge in parallel direction.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_hvLeft, const T &i_hvRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_hvUpdateLeft,
T &o_hvUpdateRight,
T &o_maxWaveSpeed ) {
// store parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_hvLeft, i_hvRight,
i_bLeft, i_bRight );
double netUpdatesLeft[3], netUpdatesRight[3];
c_bind_geoclaw_riemann_aug_JCP( maxNumberOfRiemannIterations, 3,
hLeft, hRight,
huLeft, huRight,
hvLeft, hvRight,
bLeft, bRight,
dryTol, g,
netUpdatesLeft, netUpdatesRight,
o_maxWaveSpeed );
//copy net-updates
o_hUpdateLeft = netUpdatesLeft[0];
o_hUpdateRight = netUpdatesRight[0];
o_huUpdateLeft = netUpdatesLeft[1];
o_huUpdateRight = netUpdatesRight[1];
o_hvUpdateLeft = netUpdatesLeft[2];
o_hvUpdateRight = netUpdatesRight[2];
}
};
#endif /* AUGRIEGEOCLAW_HPP_ */
/**
* FWave.hpp
*
****
**** F-Wave Riemann Solver for the Shallow Water Equation
****
*
* Created on: Aug 25, 2011
* Last Update: Feb 18, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*
* (Main) Literature:
*
* @article{bale2002wave,
* title={A wave propagation method for conservation laws and balance laws with spatially varying flux functions},
* author={Bale, D.S. and LeVeque, R.J. and Mitran, S. and Rossmanith, J.A.},
* journal={SIAM Journal on Scientific Computing},
* volume={24},
* number={3},
* pages={955--978},
* year={2002},
* publisher={Citeseer}}
*
* @book{leveque2002finite,
* Author = {LeVeque, R. J.},
* Date-Added = {2011-09-13 14:09:31 +0000},
* Date-Modified = {2011-10-31 09:46:40 +0000},
* Publisher = {Cambridge University Press},
* Title = {Finite Volume Methods for Hyperbolic Problems},
* Volume = {31},
* Year = {2002}}
*
* @webpage{levequeclawpack,
* Author = {LeVeque, R. J.},
* Lastchecked = {January, 05, 2011},
* Title = {Clawpack Sofware},
* Url = {https://github.com/clawpack/clawpack-4.x/blob/master/geoclaw/2d/lib}}
*
****
*
* Acknowledgments:
* Special thanks go to R.J. LeVeque and D.L. George for publishing their code
* and the corresponding documentation (-> Literature).
*/
#ifndef FWAVE_HPP_
#define FWAVE_HPP_
#include <cassert>
#include <cmath>
#include "WavePropagation.hpp"
namespace solver {
template <typename T> class FWave;
}
/**
* FWave Riemann Solver for the Shallow Water Equations.
*
* T should be double or float.
*/
template <typename T> class solver::FWave: public WavePropagation<T> {
private: //explicit for unit tests
//use nondependent names (template base class)
using solver::WavePropagation<T>::zeroTol;
using solver::WavePropagation<T>::g;
using solver::WavePropagation<T>::dryTol;
using solver::WavePropagation<T>::hLeft;
using solver::WavePropagation<T>::hRight;
using solver::WavePropagation<T>::huLeft;
using solver::WavePropagation<T>::huRight;
using solver::WavePropagation<T>::bLeft;
using solver::WavePropagation<T>::bRight;
using solver::WavePropagation<T>::uLeft;
using solver::WavePropagation<T>::uRight;
using solver::WavePropagation<T>::wetDryState;
using solver::WavePropagation<T>::DryDry;
using solver::WavePropagation<T>::WetWet;
using solver::WavePropagation<T>::WetDryWall;
using solver::WavePropagation<T>::DryWetWall;
using solver::WavePropagation<T>::storeParameters;
public:
/**
* Constructor of the f-wave solver with optional parameters.
*
* @param i_dryTolerance numerical definition of "dry".
* @param i_gravity gravity constant.
* @param i_zeroTolerance numerical definition of zero.
*/
FWave( T i_dryTolerance = (T) 0.01,
T i_gravity = (T) 9.81,
T i_zeroTolerance = (T) 0.000000001 ):
WavePropagation<T>( i_dryTolerance, i_gravity, i_zeroTolerance ) {
#ifndef NDEBUG
#ifndef SUPPRESS_SOLVER_DEBUG_OUTPUT
//print some information about the used solver
std::cout << " *** solver::FWave created" << std::endl
<< " zeroTolerance=" << zeroTol << std::endl
<< " gravity=" << g << std::endl
<< " dryTolerance=" << dryTol << std::endl
<< " ***\n\n";
#endif
#endif
}
/**
* Compute net updates for the cell on the left/right side of the edge.
* This is the default method of a standalone f-Wave solver.
*
* Please note:
* In the case of a Dry/Wet- or Wet/Dry-boundary, wall boundary conditions will be set.
* The f-Wave solver is not positivity preserving.
* -> You as the programmer have to take care about "negative water heights"!
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
//set speeds to zero (will be determined later)
uLeft = uRight = 0;
//reset the maximum wave speed
o_maxWaveSpeed = 0;
//! wave speeds of the f-waves
T waveSpeeds[2];
//store parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight );
//determine the wet/dry state and compute local variables correspondingly
determineWetDryState();
//zero updates and return in the case of dry cells
if(wetDryState == DryDry) {
o_hUpdateLeft = o_hUpdateRight = o_huUpdateLeft = o_huUpdateRight = (T)0.;
return;
}
//compute the wave speeds
computeWaveSpeeds(waveSpeeds);
//use the wave speeds to compute the net-updates
computeNetUpdates_WithWaveSpeeds( waveSpeeds,
o_hUpdateLeft, o_hUpdateRight,
o_huUpdateLeft, o_huUpdateRight,
o_maxWaveSpeed );
//zero ghost updates (wall boundary)
if(wetDryState == WetDryWall) {
o_hUpdateRight = 0;
o_huUpdateRight = 0;
}
else if(wetDryState == DryWetWall) {
o_hUpdateLeft = 0;
o_huUpdateLeft = 0;
}
}
/**
* Compute net updates for the cell on the left/right side of the edge.
* This is an expert method, because a lot of (numerical-)knowledge about the problem is assumed/has to be provided.
* It is the f-Wave entry point for the hybrid solver, which combines the "simple" F-Wave approach with the more complex Augmented Riemann Solver.
*
* wetDryState is assumed to be WetWet.
*
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
* @param waveSpeeds speeds of the linearized waves (eigenvalues).
* A hybrid solver will typically provide its own values.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
void computeNetUpdatesHybrid ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
const T &i_uLeft, const T &i_uRight,
const T i_waveSpeeds[2],
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
//store parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight,
i_uLeft, i_uRight );
computeNetUpdates_WithWaveSpeeds( i_waveSpeeds,
o_hUpdateLeft, o_hUpdateRight,
o_huUpdateLeft, o_huUpdateRight,
o_maxWaveSpeed );
}
private:
/**
* Compute net updates for the cell on the left/right side of the edge.
* Its assumed that the member variables are set already.
*
* @param i_waveSpeeds speeds of the linearized waves (eigenvalues).
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
void computeNetUpdates_WithWaveSpeeds ( const T i_waveSpeeds[2],
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
//reset net updates
o_hUpdateLeft = o_hUpdateRight = o_huUpdateLeft = o_huUpdateRight = (T)0.;
//! where to store the two f-waves
T fWaves[2][2];
//compute the decomposition into f-waves
computeWaveDecomposition( i_waveSpeeds, fWaves );
//compute the net-updates
//1st wave family
if(i_waveSpeeds[0] < -zeroTol) { //left going
o_hUpdateLeft += fWaves[0][0];
o_huUpdateLeft += fWaves[0][1];
}
else if(i_waveSpeeds[0] > zeroTol) { //right going
o_hUpdateRight += fWaves[0][0];
o_huUpdateRight += fWaves[0][1];
}
else { //split waves
o_hUpdateLeft += (T).5*fWaves[0][0];
o_huUpdateLeft += (T).5*fWaves[0][1];
o_hUpdateRight += (T).5*fWaves[0][0];
o_huUpdateRight += (T).5*fWaves[0][1];
}
//2nd wave family
if(i_waveSpeeds[1] < -zeroTol) { //left going
o_hUpdateLeft += fWaves[1][0];
o_huUpdateLeft += fWaves[1][1];
}
else if(i_waveSpeeds[1] > zeroTol) { //right going
o_hUpdateRight += fWaves[1][0];
o_huUpdateRight += fWaves[1][1];
}
else { //split waves
o_hUpdateLeft += (T).5*fWaves[1][0];
o_huUpdateLeft += (T).5*fWaves[1][1];
o_hUpdateRight += (T).5*fWaves[1][0];
o_huUpdateRight += (T).5*fWaves[1][1];
}
//compute maximum wave speed (-> CFL-condition)
o_maxWaveSpeed = std::max( std::fabs(i_waveSpeeds[0]) , std::fabs(i_waveSpeeds[1]) );
}
/**
* Determine the wet/dry state and set member variables accordingly.
*/
void determineWetDryState() {
//determine the wet/dry state
if(hLeft < dryTol && hRight < dryTol) { //both cells are dry
wetDryState = DryDry;
}
else if(hLeft < dryTol) { // left cell dry, right cell wet
uRight = huRight/hRight;
//Set wall boundary conditions.
//This is not correct in the case of inundation problems.
hLeft = hRight;
bLeft = bRight;
huLeft = -huRight;
uLeft = -uRight;
wetDryState = DryWetWall;
}
else if(hRight < dryTol) { //left cell wet, right cell dry
uLeft = huLeft/hLeft;
//Set wall boundary conditions.
//This is not correct in the case of inundation problems.
hRight = hLeft;
bRight = bLeft;
huRight = -huLeft;
uLeft = -uRight;
wetDryState = WetDryWall;
}
else { //both cells wet
uLeft = huLeft/hLeft;
uRight = huRight/hRight;
wetDryState = WetWet;
}
}
/**
* Compute the decomposition into f-Waves.
*
* @param i_waveSpeeds speeds of the linearized waves (eigenvalues).
* @param o_fWaves will be set to: Decomposition into f-Waves.
*/
void computeWaveDecomposition( const T i_waveSpeeds[2],
T o_fWaves[2][2]
) const {
//TODO: Update documentation.
//Eigenvalues***********************************************************************************************
//Computed somewhere before.
//An option would be to use the char. speeds:
//
//lambda^1 = u_{i-1} - sqrt(g*h_{i-1})
//lambda^2 = u_i + sqrt(g*h_i)
//Matrix of right eigenvectors******************************************************************************
// 1 1
// R =
// u_{i-1} - sqrt(g * h_{i-1}) u_i + sqrt(g * h_i)
//**********************************************************************************************************
// u_i + sqrt(g * h_i) -1
// R^{-1} = 1 / (u_i - sqrt(g * h_i) - u_{i-1} + sqrt(g * h_{i-1}) *
// -( u_{i-1} - sqrt(g * h_{i-1}) ) 1
//**********************************************************************************************************
// hu
// f(q) =
// hu^2 + 1/2 g * h^2
//
//**********************************************************************************************************
// 0
// \delta x \Psi =
// -g * 1/2 * (h_i + h_{i-1}) * (b_i - b_{i+1})
//**********************************************************************************************************
// beta = R^{-1} * (f(Q_i) - f(Q_{i-1}) - \delta x \Psi)
//**********************************************************************************************************
//assert: wave speed of the 1st wave family should be less than the speed of the 2nd wave family.
assert( i_waveSpeeds[0] < i_waveSpeeds[1] );
T lambdaDif = i_waveSpeeds[1] - i_waveSpeeds[0];
//assert: no division by zero
assert(std::abs(lambdaDif) > zeroTol);
//compute the inverse matrix R^{-1}
T Rinv[2][2];
T oneDivLambdaDif = (T)1. / lambdaDif;
Rinv[0][0] = oneDivLambdaDif * i_waveSpeeds[1];
Rinv[0][1] = -oneDivLambdaDif;
Rinv[1][0] = oneDivLambdaDif * -i_waveSpeeds[0];
Rinv[1][1] = oneDivLambdaDif;
//right hand side
T fDif[2];
//calculate modified (bathymetry!) flux difference
// f(Q_i) - f(Q_{i-1})
fDif[0] = huRight - huLeft;
fDif[1] = huRight * uRight + (T).5 * g * hRight * hRight
-(huLeft * uLeft + (T).5 * g * hLeft * hLeft);
// \delta x \Psi[2]
T psi = -g * (T).5 * (hRight + hLeft)*(bRight - bLeft);
fDif[1] -= psi;
//solve linear equations
T beta[2];
beta[0] = Rinv[0][0] * fDif[0] + Rinv[0][1] * fDif[1];
beta[1] = Rinv[1][0] * fDif[0] + Rinv[1][1] * fDif[1];
//return f-waves
o_fWaves[0][0] = beta[0];
o_fWaves[0][1] = beta[0] * i_waveSpeeds[0];
o_fWaves[1][0] = beta[1];
o_fWaves[1][1] = beta[1] * i_waveSpeeds[1];
}
/**
* Compute the edge local eigenvalues.
*
* @param o_waveSpeeds will be set to: speeds of the linearized waves (eigenvalues).
*/
void computeWaveSpeeds( T o_waveSpeeds[2]) const {
//compute eigenvalues of the jacobian matrices in states Q_{i-1} and Q_{i}
T characteristicSpeeds[2];
characteristicSpeeds[0] = uLeft - std::sqrt(g*hLeft);
characteristicSpeeds[1] = uRight + std::sqrt(g*hRight);
//compute "Roe speeds"
T hRoe = (T).5 * (hRight + hLeft);
T uRoe = uLeft * std::sqrt(hLeft) + uRight * std::sqrt(hRight);
uRoe /= std::sqrt(hLeft) + std::sqrt(hRight);
T roeSpeeds[2];
roeSpeeds[0] = uRoe - std::sqrt(g*hRoe);
roeSpeeds[1] = uRoe + std::sqrt(g*hRoe);
//computer eindfeldt speeds
T einfeldtSpeeds[2];
einfeldtSpeeds[0] = std::min(characteristicSpeeds[0], roeSpeeds[0]);
einfeldtSpeeds[1] = std::max(characteristicSpeeds[1], roeSpeeds[1]);
//set wave speeds
o_waveSpeeds[0] = einfeldtSpeeds[0];
o_waveSpeeds[1] = einfeldtSpeeds[1];
}
};
#endif /* FWAVE_HPP_ */
/**
* FWaveCuda.h
*
****
**** This is a pure C implementation of the standard C++ f-Wave solver (FWave.hpp).
****
*
* Created on: Jan 12, 2012
* Last Update: Jan 12, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*
* (Main) Literature:
*
* @article{bale2002wave,
* title={A wave propagation method for conservation laws and balance laws with spatially varying flux functions},
* author={Bale, D.S. and LeVeque, R.J. and Mitran, S. and Rossmanith, J.A.},
* journal={SIAM Journal on Scientific Computing},
* volume={24},
* number={3},
* pages={955--978},
* year={2002},
* publisher={Citeseer}}
*
* @book{leveque2002finite,
* Author = {LeVeque, R. J.},
* Date-Added = {2011-09-13 14:09:31 +0000},
* Date-Modified = {2011-10-31 09:46:40 +0000},
* Publisher = {Cambridge University Press},
* Title = {Finite Volume Methods for Hyperbolic Problems},
* Volume = {31},
* Year = {2002}}
*
* @webpage{levequeclawpack,
* Author = {LeVeque, R. J.},
* Lastchecked = {January, 05, 2011},
* Title = {Clawpack Sofware},
* Url = {https://github.com/clawpack/clawpack-4.x/blob/master/geoclaw/2d/lib}}
*
****
*
* Acknowledgments:
* Special thanks go to R.J. LeVeque and D.L. George for publishing their code
* and the corresponding documentation (-> Literature).
*/
#include <cmath>
#include <cstdio>
typedef float T;
//! numerical definition of zero.
const T zeroTol = (T) 0.0000001;
//! numerical definition of a dry cell
const T dryTol = (T) 100.;
__device__
void fWaveComputeNetUpdates( const T i_gravity,
T i_hLeft, T i_hRight,
T i_huLeft, T i_huRight,
T i_bLeft, T i_bRight,
T o_netUpdates[5]);
__device__
inline void fWaveComputeWaveSpeeds( const T i_gravity,
const T i_hLeft, const T i_hRight,
const T i_huLeft, const T i_huRight,
const T i_uLeft, const T i_uRight,
const T i_bLeft, const T i_bRight,
T o_waveSpeeds[2] );
__device__
inline void fWaveComputeWaveDecomposition( const T i_gravity,
const T i_hLeft, const T i_hRight,
const T i_huLeft, const T i_huRight,
const T i_uLeft, const T i_uRight,
const T i_bLeft, const T i_bRight,
const T i_waveSpeeds[2],
T o_fWaves[2][2] );
/**
* Compute net updates for the cell on the left/right side of the edge
*
* The order of o_netUpdates is given by:
* 0: hUpdateLeft - Net-update for the height of the cell on the left side of the edge.
* 1: hUpdateRight - Net-update for the height of the cell on the right side of the edge.
* 2: huUpdateLeft - Net-update for the momentum of the cell on the left side of the edge
* 3: huUpdateRight - Net-update for the momentum of the cell on the right side of the edge.
* 4: maxWaveSpeed - Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*
* TODO: A wet/wet state is assumend / no boundaries are implemented within the solver to
* allow an execution with with a few jumps only.
*
* @param i_gravity gravity constant.
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_netUpdates will be set to the net updates.
*/
__device__
void fWaveComputeNetUpdates( const T i_gravity,
T i_hLeft, T i_hRight,
T i_huLeft, T i_huRight,
T i_bLeft, T i_bRight,
T o_netUpdates[5] ) {
//reset net updates
o_netUpdates[0] = (T)0.; //hUpdateLeft
o_netUpdates[1] = (T)0.; //hUpdateRight
o_netUpdates[2] = (T)0.; //huUpdateLeft
o_netUpdates[3] = (T)0.; //huUpdateRight
//reset the maximum wave speed
o_netUpdates[4] = (T)0.; //maxWaveSpeed
// determine the wet dry state and corr. values, if necessary.
if( !(i_hLeft > dryTol && i_hRight > dryTol) ) {
if( i_hLeft < dryTol && i_hRight < dryTol )
return;
else if ( i_hLeft < dryTol ) {
i_hLeft = i_hRight;
i_huLeft = -i_huRight;
i_bLeft = i_bRight;
}
else { //( i_hRight < dryTol )
i_hRight = i_hLeft;
i_huRight = -i_huLeft;
i_bRight = i_bLeft;
}
}
//! velocity on the left side of the edge
T uLeft = i_huLeft / i_hLeft;
//! velocity on the right side of the edge
T uRight = i_huRight / i_hRight;
//! wave speeds of the f-waves
T waveSpeeds[2];
//compute the wave speeds
fWaveComputeWaveSpeeds( i_gravity,
i_hLeft, i_hRight,
i_huLeft, i_huRight,
uLeft, uRight,
i_bLeft, i_bRight,
waveSpeeds );
//! where to store the two f-waves
T fWaves[2][2];
//compute the decomposition into f-waves
fWaveComputeWaveDecomposition( i_gravity,
i_hLeft, i_hRight,
i_huLeft, i_huRight,
uLeft, uRight,
i_bLeft, i_bRight,
waveSpeeds,
fWaves );
//compute the net-updates
//1st wave family
if(waveSpeeds[0] < -zeroTol) { //left going
o_netUpdates[0] += fWaves[0][0]; //hUpdateLeft
o_netUpdates[2] += fWaves[0][1]; //huUpdateLeft
}
else if(waveSpeeds[0] > zeroTol) { //right going
o_netUpdates[1] += fWaves[0][0]; //hUpdateRight
o_netUpdates[3] += fWaves[0][1]; //huUpdateRight
}
else { //split waves
o_netUpdates[0] += (T).5*fWaves[0][0]; //hUpdateLeft
o_netUpdates[2] += (T).5*fWaves[0][1]; //huUpdateLeft
o_netUpdates[1] += (T).5*fWaves[0][0]; //hUpdateRight
o_netUpdates[3] += (T).5*fWaves[0][1]; //huUpdateRight
}
//2nd wave family
if(waveSpeeds[1] < -zeroTol) { //left going
o_netUpdates[0] += fWaves[1][0]; //hUpdateLeft
o_netUpdates[2] += fWaves[1][1]; //huUpdateLeft
}
else if(waveSpeeds[1] > zeroTol) { //right going
o_netUpdates[1] += fWaves[1][0]; //hUpdateRight
o_netUpdates[3] += fWaves[1][1]; //huUpdateRight
}
else { //split waves
o_netUpdates[0] += (T).5*fWaves[1][0]; //hUpdateLeft
o_netUpdates[2] += (T).5*fWaves[1][1]; //huUpdateLeft
o_netUpdates[1] += (T).5*fWaves[1][0]; //hUpdateRight
o_netUpdates[3] += (T).5*fWaves[1][1]; //huUpdateRight
}
//compute maximum wave speed (-> CFL-condition)
o_netUpdates[4] = fmax( fabs(waveSpeeds[0]) , fabs(waveSpeeds[1]) );
}
/**
* Compute the edge local eigenvalues.
*
* @param i_gravity gravity constant.
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_waveSpeeds will be set to: speeds of the linearized waves (eigenvalues).
*/
__device__
inline void fWaveComputeWaveSpeeds( const T i_gravity,
const T i_hLeft, const T i_hRight,
const T i_huLeft, const T i_huRight,
const T i_uLeft, const T i_uRight,
const T i_bLeft, const T i_bRight,
T o_waveSpeeds[2] ) {
//compute eigenvalues of the jacobian matrices in states Q_{i-1} and Q_{i}
T characteristicSpeeds[2];
characteristicSpeeds[0] = i_uLeft - sqrt(i_gravity*i_hLeft);
characteristicSpeeds[1] = i_uRight + sqrt(i_gravity*i_hRight);
//compute "Roe speeds"
T hRoe = (T).5 * (i_hRight + i_hLeft);
T uRoe = i_uLeft * sqrt(i_hLeft) + i_uRight * sqrt(i_hRight);
uRoe /= sqrt(i_hLeft) + sqrt(i_hRight);
T roeSpeeds[2];
roeSpeeds[0] = uRoe - sqrt(i_gravity*hRoe);
roeSpeeds[1] = uRoe + sqrt(i_gravity*hRoe);
//computer eindfeldt speeds
T einfeldtSpeeds[2];
einfeldtSpeeds[0] = fmin(characteristicSpeeds[0], roeSpeeds[0]);
einfeldtSpeeds[1] = fmax(characteristicSpeeds[1], roeSpeeds[1]);
//set wave speeds
o_waveSpeeds[0] = einfeldtSpeeds[0];
o_waveSpeeds[1] = einfeldtSpeeds[1];
}
/**
* Compute the decomposition into f-Waves.
*
* @param i_gravity gravity constant.
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
* @param i_waveSpeeds speeds of the linearized waves (eigenvalues).
* @param o_fWaves will be set to: Decomposition into f-Waves.
*/
__device__
inline void fWaveComputeWaveDecomposition( const T i_gravity,
const T i_hLeft, const T i_hRight,
const T i_huLeft, const T i_huRight,
const T i_uLeft, const T i_uRight,
const T i_bLeft, const T i_bRight,
const T i_waveSpeeds[2],
T o_fWaves[2][2] ) {
T lambdaDif = i_waveSpeeds[1] - i_waveSpeeds[0];
//compute the inverse matrix R^{-1}
T Rinv[2][2];
T oneDivLambdaDif = (T)1. / lambdaDif;
Rinv[0][0] = oneDivLambdaDif * i_waveSpeeds[1];
Rinv[0][1] = -oneDivLambdaDif;
Rinv[1][0] = oneDivLambdaDif * -i_waveSpeeds[0];
Rinv[1][1] = oneDivLambdaDif;
//right hand side
T fDif[2];
//calculate modified (bathymetry!) flux difference
// f(Q_i) - f(Q_{i-1})
fDif[0] = i_huRight - i_huLeft;
fDif[1] = i_huRight * i_uRight + (T).5 * i_gravity * i_hRight * i_hRight
-(i_huLeft * i_uLeft + (T).5 * i_gravity * i_hLeft * i_hLeft);
// \delta x \Psi[2]
T psi = -i_gravity * (T).5 * (i_hRight + i_hLeft)*(i_bRight - i_bLeft);
fDif[1] -= psi;
//solve linear equations
T beta[2];
beta[0] = Rinv[0][0] * fDif[0] + Rinv[0][1] * fDif[1];
beta[1] = Rinv[1][0] * fDif[0] + Rinv[1][1] * fDif[1];
//return f-waves
o_fWaves[0][0] = beta[0];
o_fWaves[0][1] = beta[0] * i_waveSpeeds[0];
o_fWaves[1][0] = beta[1];
o_fWaves[1][1] = beta[1] * i_waveSpeeds[1];
/*
* in the case of a "zero strength" wave set the wave speeds to zero
* => non present waves don't affect the CFL-condition.
* TODO: Seems not to affect the time step size
*/
// if( fmax(fabs(beta[0]), fabs(beta[1])) < zeroTol ) {
// io_waveSpeeds[0] = (T) 0.;
// io_waveSpeeds[1] = (T) 0.;
// }
}
/**
* Hybrid.hpp
*
****
**** Hybrid Riemann Solver for the Shallow Water Equation
****
*
* Created on: Jan 04, 2012
* Last Update: Feb 20, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*
* (Main) Literature:
*
* @webpage{levequeclawpack,
* Author = {LeVeque, R. J.},
* Lastchecked = {January, 05, 2011},
* Title = {Clawpack Sofware},
* Url = {https://github.com/dlgeorge/clawpack-4.x/blob/master/geoclaw/2d/lib/rpn2ez_fast_geo.f}}
*
* TODO: Where to find literature about hybrid-solvers?
*
****
*
* Acknowledgments:
* Special thanks go to R.J. LeVeque and D.L. George for publishing their code
* and the corresponding documentation (-> Literature).
*/
#ifndef HYBRID_HPP_
#define HYBRID_HPP_
#include "FWave.hpp"
#include "AugRie.hpp"
#ifndef NDEBUG
#include <iostream>
#endif
namespace solver {
template <typename T> class Hybrid;
}
/**
* Hybrid Wave Propagation Solver.
* Combines the "simple" f-Wave approach with the more complex Augmented Riemann Solver.
*
* T should be double or float.
*/
template <typename T> class solver::Hybrid {
private:
//! gravity constant.
const T g;
//! numerical definition of "dry".
const T dryTol;
//! f-Wave solver for "simple" problems.
solver::FWave<T> fWaveSolver;
//! Augmented Riemann-solver for more complex problems.
solver::AugRie<T> augRieSolver;
#ifndef NDEBUG
//! how often was the f-Wave solver used.
long counterFWave;
//! how often was the AugRie solver used.
long counterAugRie;
#endif
public:
/**
* Constructor of the hybrid solver with optional parameters.
*
* @param i_dryTolerance numerical definition of "dry".
* @param i_gravity gravity constant.
* @param i_newtonTolerance numerical definition of "convergence" (used in the AugRie solver only).
* @param i_maxNumberOfNewtonIterations maximum steps for the Newton-Raphson method (used in the AugRie solver only).
* @param i_zeroTolerance numerical definition of zero.
*/
Hybrid( T i_dryTolerance = (T) 0.01,
T i_gravity = (T) 9.81,
T i_newtonTolerance = (T) 0.000001,
int i_maxNumberOfNewtonIterations = 10,
T zeroTolerance = (T) 0.000000001 ):
g(i_gravity),
dryTol(i_dryTolerance),
fWaveSolver( i_dryTolerance,
i_gravity,
zeroTolerance ),
augRieSolver( i_dryTolerance,
i_gravity,
i_newtonTolerance,
i_maxNumberOfNewtonIterations,
zeroTolerance ) {
#ifndef NDEBUG
//set the counters to zero.
counterFWave = counterAugRie = 0;
#ifndef SUPPRESS_SOLVER_DEBUG_OUTPUT
//print some information about the used solver.
std::cout << " *** solver::Hybrid created" << std::endl
<< " zeroTolerance=" << zeroTolerance << std::endl
<< " gravity=" << i_gravity << std::endl
<< " dryTolerance=" << i_dryTolerance << std::endl
<< " newtonTolerance=" << i_newtonTolerance << std::endl
<< " maxNumberNumberOfNewtonIterations=" << i_maxNumberOfNewtonIterations << std::endl
<< " ***\n\n";
#endif
#endif
};
/**
* Compute net updates for the cell on the left/right side of the edge.
* The "correct" solver is used automatically.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
if( useAugmentedRiemannSolver( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight,
o_hUpdateLeft, o_hUpdateRight,
o_huUpdateLeft, o_huUpdateRight,
o_maxWaveSpeed ) == true ) {
augRieSolver.computeNetUpdates( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight,
o_hUpdateLeft, o_hUpdateRight,
o_huUpdateLeft, o_huUpdateRight,
o_maxWaveSpeed );
#ifndef NDEBUG
counterAugRie++;
#endif
}
#ifndef NDEBUG
else {
counterFWave++;
}
#endif
}
/**
* Should the Augmented Riemann Solver be used?
* Side effect: If its sufficient to use the f-Wave solver the net-updates
* will be computed already (hybrid f-Wave version).
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*
* @return A boolean whether the Augmented Riemann Solver should be used or not.
*/
bool useAugmentedRiemannSolver( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) {
//use the augmented solver by default
bool useAugRieSolver = true;
if(i_hLeft > dryTol && i_hRight > dryTol) { //both cells wet?
//compute the velocities
T uLeft = i_huLeft / i_hLeft;
T uRight = i_huRight / i_hRight;
//definition of a "simple" Riemann-problem (GeoClaw)
//TODO: Literature?
if( std::fabs(i_hLeft - i_hRight) < (T)0.001*std::min(i_hLeft, i_hRight) && //"small" jump in height
std::max(uLeft*uLeft, uRight*uRight)/std::max(g*i_hLeft, g*i_hRight) < (T)0.01 ) { //"small" jump in velocity
useAugRieSolver = false;
//compute simplified wave speeds (Geoclaw)
//TODO: Literature?
T waveSpeeds[2];
waveSpeeds[0] = (uLeft + uRight)*(T).5 - std::sqrt(g*(i_hLeft + i_hRight)*(T).5);
waveSpeeds[1] = (uLeft + uRight)*(T).5 + std::sqrt(g*(i_hLeft + i_hRight)*(T).5);
//compute the f-waves
fWaveSolver.computeNetUpdatesHybrid( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight,
uLeft, uRight,
waveSpeeds,
o_hUpdateLeft, o_hUpdateRight,
o_huUpdateLeft, o_huUpdateRight,
o_maxWaveSpeed );
}
}
//DryDry case: Don't use any solver and set everything to zero
else if(i_hLeft < dryTol && i_hRight < dryTol) {
o_hUpdateLeft = o_hUpdateRight = o_huUpdateLeft = o_huUpdateRight = o_maxWaveSpeed = 0;
useAugRieSolver = false;
}
return useAugRieSolver;
}
#ifndef NDEBUG
/**
* Prints the current statistics of the hybrid solver.
*/
void printStats() {
std::cout << " *** solver::Hybrid printing statistics" << std::endl
<< " times the f-Wave solver was used: " << counterFWave << std::endl
<< " times the AugRie solver was used: " << counterAugRie << std::endl
<< " ***\n\n";
}
/**
* Get the current statistics of the hybrid solver.
*
* @param o_counterFWave will be set to: times the f-Wave solver was used.
* @param o_counterAugRie will be set to: times the Augmented Riemann solver was used.
*/
void getStats( long &o_counterFWave, long &o_counterAugRie ) {
o_counterFWave = counterFWave;
o_counterAugRie = counterAugRie;
}
#endif
};
#endif /* HYBRID_HPP_ */
/**
* WavePropagation.hpp
*
****
**** Abstract wave propagation solver for the Shallow Water Equations.
****
*
* Created on: Jan 03, 2012
* Last Update: Jan 05, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*/
#ifndef WAVEPROPAGATIONSOLVER_HPP_
#define WAVEPROPAGATIONSOLVER_HPP_
namespace solver {
template <typename T> class WavePropagation;
}
/**
* Abstract wave propagation solver for the Shallow Water Equations.
*
* T should be double or float.
*/
template <typename T> class solver::WavePropagation {
protected:
//global variables
//! numerical definition of "dry".
const T dryTol;
//! gravity constant
const T g;
//! numerical definition of zero.
const T zeroTol;
#if 0
//parameters for computeNetUpdates
T h[2];
T hu[2];
T b[2];
T u[2];
#define hLeft (h[0])
#define hRight (h[1])
#define huLeft (hu[0])
#define huRight (hu[1])
#define bLeft (b[0])
#define bRight (b[1])
#define uLeft (u[0])
#define uRight (u[1])
#else
//edge-local variables
//! height on the left side of the edge (could change during execution).
T hLeft;
//! height on the right side of the edge (could change during execution).
T hRight;
//! momentum on the left side of the edge (could change during execution).
T huLeft;
//! momentum on the right side of the edge (could change during execution).
T huRight;
//! bathymetry on the left side of the edge (could change during execution).
T bLeft;
//! bathymetry on the right side of the edge (could change during execution).
T bRight;
//! velocity on the left side of the edge (computed by determineWetDryState).
T uLeft;
//! velocity on the right side of the edge (computed by determineWetDryState).
T uRight;
#endif
/**
* The wet/dry state of the Riemann-problem.
*/
enum WetDryState {
DryDry, /**< Both cells are dry. */
WetWet, /**< Both cells are wet. */
WetDryInundation, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies higher than the 2nd one. */
WetDryWall, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies lower than the 2nd one.
* Momentum is not large enough to overcome the difference. */
WetDryWallInundation, /**< 1st cell: wet, 2nd cell: dry. 1st cell lies lower than the 2nd one.
* Momentum is large enough to overcome the difference. */
DryWetInundation, /**< 1st cell: dry, 2nd cell: wet. 1st cell lies lower than the 2nd one. */
DryWetWall, /**< 1st cell: dry, 2nd cell: wet. 1st cell lies higher than the 2nd one.
* Momentum is not large enough to overcome the difference. */
DryWetWallInundation /**< 1st cell: dry, 2nd cell: wet. 1st cell lies higher than the 2nd one.
* Momentum is large enough to overcome the difference. */
};
//! wet/dry state of our Riemann-problem (determined by determineWetDryState)
WetDryState wetDryState;
//! Determine the wet/dry-state and set local values if we have to.
virtual void determineWetDryState() = 0;
/**
* Constructor of a wave propagation solver.
*
* @param gravity gravity constant.
* @param dryTolerance numerical definition of "dry".
* @param zeroTolerance numerical definition of zero.
*/
WavePropagation( T i_dryTolerance,
T i_gravity,
T i_zeroTolerance ):
dryTol(i_dryTolerance),
g(i_gravity),
zeroTol(i_zeroTolerance) {};
/**
* Store parameters to member variables.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*/
inline void storeParameters( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight ) {
//store parameters to member variables
hLeft = i_hLeft;
hRight = i_hRight;
huLeft = i_huLeft;
huRight = i_huRight;
bLeft = i_bLeft;
bRight = i_bRight;
}
/**
* Store parameters to member variables.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
* @param i_uLeft velocity on the left side of the edge.
* @param i_uRight velocity on the right side of the edge.
*/
inline void storeParameters( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
const T &i_uLeft, const T &i_uRight) {
//store parameters to member variables
storeParameters( i_hLeft, i_hRight,
i_huLeft, i_huRight,
i_bLeft, i_bRight );
uLeft = i_uLeft;
uRight = i_uRight;
}
public:
/**
* Compute net updates for the cell on the left/right side of the edge.
* This is the default method every standalone wave propagation solver should provide.
*
* @param i_hLeft height on the left side of the edge.
* @param i_hRight height on the right side of the edge.
* @param i_huLeft momentum on the left side of the edge.
* @param i_huRight momentum on the right side of the edge.
* @param i_bLeft bathymetry on the left side of the edge.
* @param i_bRight bathymetry on the right side of the edge.
*
* @param o_hUpdateLeft will be set to: Net-update for the height of the cell on the left side of the edge.
* @param o_hUpdateRight will be set to: Net-update for the height of the cell on the right side of the edge.
* @param o_huUpdateLeft will be set to: Net-update for the momentum of the cell on the left side of the edge.
* @param o_huUpdateRight will be set to: Net-update for the momentum of the cell on the right side of the edge.
* @param o_maxWaveSpeed will be set to: Maximum (linearized) wave speed -> Should be used in the CFL-condition.
*/
virtual void computeNetUpdates ( const T &i_hLeft, const T &i_hRight,
const T &i_huLeft, const T &i_huRight,
const T &i_bLeft, const T &i_bRight,
T &o_hUpdateLeft,
T &o_hUpdateRight,
T &o_huUpdateLeft,
T &o_huUpdateRight,
T &o_maxWaveSpeed ) = 0;
virtual ~WavePropagation() {};
#undef hLeft
#undef hRight
#undef huLeft
#undef huRight
#undef bLeft
#undef bRight
#undef uLeft
#undef uRight
};
#endif /* WAVEPROPAGATIONSOLVER_HPP_ */
/**
* ComponentsTest.cpp
*
****
**** Collection of elementary unit tests for the Augmented Riemann solver.
****
*
* Created on: Nov 30, 2011
* Last Update: June 12, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*/
#include "ComponentsTest.h"
//Access private members
#define private public
#include "../solver/AugRie.hpp"
#undef private
#include "cute.h"
#include <cmath>
#include <string>
#include <netcdfcpp.h>
/**
* Contructor.
*
* Sets all variables to reasonable default values and reads the pre-computed values of the function phi.
*/
ComponentsTest::ComponentsTest():
gravity(9.81),
dryTol(0.001),
zeroTol(0.00001),
maxWaterHeight(8500),
maxWaveSpeed(14166.66),
maxWaveSpeedVariation(833.33),
numberOfRandomTests(500000),
testPhiSize(1000000),
testPhiWallSamples(500000),
testPhiRandomSamples(500000),
maxNumberOfNewtonIterationsDefault(10),
maxNumberOfNewtonIterationsExpensive(50000),
newtonTol(0.0001),
testFileName("unit_tests/files/testphi_1000000.nc"),
mySolver(dryTol, gravity, newtonTol, maxNumberOfNewtonIterationsDefault, zeroTol) {
// read pre-computed values of phi
testPhi = new double* [5];
for(int i = 0; i < 5; i++) {
testPhi[i] = new double[testPhiSize];
}
readTestPhi();
}
/**
* Destructor.
*
*/
ComponentsTest::~ComponentsTest() {
// for(int i = 0; i < 5; i++) {
// delete[] testPhi[i];
// }
// delete[] testPhi;
testPhi = NULL;
}
/**
* Operator with no arguments, which is called in the main function.
*/
void ComponentsTest::operator() (){
checkDetermineRiemannStructure();
checkComputeMiddleState();
checkDetermineWetDryStateSimple();
checkInundationLimits();
checkComputeNetUpdatesForWalls();
checkComputeNetUpdatesForPositivity();
};
/**
* Create a random number between l_min and l_max.
*
* @param i_min minimum value.
* @param i_max maximum value.
* @return random number.
*/
double ComponentsTest::createRandomNumber( const double i_min, const double i_max) {
double randomNumber = ((double)rand()/(double)RAND_MAX); //between 0 and 1
return i_min + (i_max-i_min) * randomNumber;
}
/**
* Read a test file with pre-computed solutions for
* the non-linear algebraic funtion phi.
*/
void ComponentsTest::readTestPhi() {
NcFile dataFile(testFileName.c_str(), NcFile::ReadOnly);
if (!dataFile.is_valid()) {
std::cout << "Couldn't open file: " << testFileName << std::endl;
assert(false);
}
ASSERT( dataFile.get_dim(0)->size() == testPhiSize );
NcVar* data;
//Retrieve the variables
data = dataFile.get_var("hLow");
data->get(testPhi[0], testPhiSize, 0);
data = dataFile.get_var("hHigh");
data->get(testPhi[1], testPhiSize, 0);
data = dataFile.get_var("huLow");
data->get(testPhi[2], testPhiSize, 0);
data = dataFile.get_var("huHigh");
data->get(testPhi[3], testPhiSize, 0);
data = dataFile.get_var("hStar");
data->get(testPhi[4], testPhiSize, 0);
}
/**
* Generates a string which contains the variables defined in the solver.
*
* @return string containing solver variables.
*/
std::string ComponentsTest::printSolverVariables() {
std::stringstream errMsg;
errMsg << std::endl
<< " dryTol: " << mySolver.dryTol << std::endl
<< " g: " << mySolver.g << std::endl
<< " zeroTol: " << mySolver.zeroTol << std::endl
<< " maxNumberOfNewtonIterations: " << mySolver.maxNumberOfNewtonIterations << std::endl
<< " newtonTol: " << mySolver.newtonTol << std::endl
<< " middleStateSpeeds[0]: " << mySolver.middleStateSpeeds[0] << std::endl
<< " middleStateSpeeds[1]: " << mySolver.middleStateSpeeds[1] << std::endl
<< " hLeft: " << mySolver.hLeft << ", hRight: " << mySolver.hRight << std::endl
<< " uLeft: " << mySolver.uLeft << ", uRight: " << mySolver.uRight << std::endl
<< " huLeft: " << mySolver.huLeft << ", huRight: " << mySolver.huRight << std::endl
<< " bLeft: " << mySolver.bLeft << ", bLeft: " << mySolver.bRight << std::endl
<< " hMiddle: " << mySolver.hMiddle << std::endl
<< " wetDryState: " << mySolver.wetDryState << std::endl
<< " riemannStructure: " << mySolver.riemannStructure << std::endl
<< "\n *** WetDryState" << std::endl
<< " DryDry: " << mySolver.DryDry
<< ", WetWet: " << mySolver.WetWet
<< ", WetDryInundation: " << mySolver.WetDryInundation
<< ", WetDryWall: " << mySolver.WetDryWall
<< ", WetDryWallInundation: " << mySolver.WetDryWallInundation
<< ", DryWetInundation: " << mySolver.DryWetInundation
<< ", DryWetWall: " << mySolver.DryWetWall
<< ", DryWetWallInundation: " << mySolver.DryWetWallInundation << std::endl
<< "\n *** riemannStructure" << std::endl
<< " DrySingleRarefaction: " << mySolver.DrySingleRarefaction
<< ", SingleRarefactionDry: " << mySolver.SingleRarefactionDry
<< ", ShockShock: " << mySolver.ShockShock
<< ", ShockRarefaction: " << mySolver.ShockRarefaction
<< ", RarefactionShock: " << mySolver.RarefactionShock
<< ", RarefactionRarefaction: " << mySolver.RarefactionRarefaction << std::endl;
errMsg.flush();
return errMsg.str();
}
/**
* Generates a string, which contains the variables of the solver and the given Riemann solution in the net-update formulation.
*
* @param i_hUpdateLeft net-update for the height of the cell on the left side of the edge.
* @param i_hUpdateRight net-update for the height of the cell on the right side of the edge.
* @param i_huUpdateLeft net-update for the momentum of the cell on the left side of the edge.
* @param i_huUpdateRight net-update for the momentum of the cell on the right side of the edge.
* @param i_maxWaveSpeed maximum wave speed.
* @return string conataining solver variables and Riemann solution.
*/
std::string ComponentsTest::printSolverVariablesWithResults( const double i_hUpdateLeft,
const double i_hUpdateRight,
const double i_huUpdateLeft,
const double i_huUpdateRight,
const double i_maxWaveSpeed ) {
std::stringstream errMsg;
errMsg << printSolverVariables()
<< "\n *** return values of computeNetUpdates" << std::endl
<< " hUpdateLeft: " << i_hUpdateLeft << std::endl
<< " hUpdateRight: " << i_hUpdateRight << std::endl
<< " huUpdateLeft: " << i_huUpdateLeft << std::endl
<< " huUpdateRight: " << i_huUpdateRight << std::endl
<< " maxWaveSpeed: " << i_maxWaveSpeed << std::endl;
errMsg.flush();
return errMsg.str();
}
/**
* Tests the function determineRiemannStructure(...) of the Augmented Riemann solver.
*/
void ComponentsTest::checkDetermineRiemannStructure() {
solver::AugRie<double>::RiemannStructure myRiemannStructure;
for(int i = 0; i < numberOfRandomTests; i++) {
//test for shock/shock problems
hLeft = hRight = createRandomNumber(zeroTol, maxWaterHeight);
uLeft = createRandomNumber(14166.6, 0);
uRight = createRandomNumber(0, -maxWaveSpeed);
myRiemannStructure = mySolver.determineRiemannStructure(hLeft, hRight, uLeft, uRight);
ASSERT(myRiemannStructure == solver::AugRie<double>::ShockShock);
//test for rare/rare problems
uLeft = createRandomNumber(-14166.6, 0);
uRight = createRandomNumber(0, +maxWaveSpeed);
myRiemannStructure = mySolver.determineRiemannStructure(hLeft, hRight, uLeft, uRight);
ASSERT(myRiemannStructure == solver::AugRie<double>::RarefactionRarefaction);
//test for shock/rare problems
hLeft = createRandomNumber(zeroTol, 8000);
uLeft = uRight = 0.;
myRiemannStructure = mySolver.determineRiemannStructure(hLeft, hRight, uLeft, uRight);
if(hLeft < hRight) {
ASSERT(myRiemannStructure == solver::AugRie<double>::ShockRarefaction);
}
else if(hLeft > hRight) {
ASSERT(myRiemannStructure == solver::AugRie<double>::RarefactionShock);
}
}
}
/**
* Test the function determineMiddleState(...) of the Augmented Riemann solver with pre-computed solutions.
*/
void ComponentsTest::checkComputeMiddleState() {
//allow lots of Newton Iterations
solver::AugRie<double> mySolver(dryTol, gravity, newtonTol, maxNumberOfNewtonIterationsExpensive, zeroTol);
//do the tests
for(int i = 0; i < testPhiSize; i++) {
double hLeft = testPhi[0][i];
double hRight = testPhi[1][i];
double huLeft = testPhi[2][i];
double huRight = testPhi[3][i];
double uLeft = huLeft / hLeft;
double uRight = huRight / hRight;
mySolver.computeMiddleState( hLeft, hRight,
uLeft, uRight,
huLeft, huRight,
maxNumberOfNewtonIterationsExpensive
);
if(testPhi[4][i] < 25.)
ASSERT_EQUAL_DELTA(mySolver.hMiddle, testPhi[4][i], .1);
else if(testPhi[4][i] < 100.)
ASSERT_EQUAL_DELTA(mySolver.hMiddle, testPhi[4][i], 1.);
else
ASSERT_EQUAL_DELTA(mySolver.hMiddle, testPhi[4][i], 2.);
}
}
/**
* Test the function determinWetDryState(...) of the Augmented Riemann solver in a simple way
*/
void ComponentsTest::checkDetermineWetDryStateSimple() {
for(int i = 0; i < numberOfRandomTests; i++) {
mySolver.bLeft = 0.;
mySolver.bRight = 0.;
mySolver.uLeft = createRandomNumber(1., maxWaveSpeed);
mySolver.uRight = createRandomNumber(-maxWaveSpeed, -1);
//test case dry/dry
mySolver.hLeft = createRandomNumber(0., dryTol-zeroTol);
mySolver.hRight = createRandomNumber(0.,dryTol-zeroTol);
mySolver.determineWetDryState();
ASSERTM(printSolverVariables() ,mySolver.wetDryState == solver::AugRie<double>::DryDry);
//test case wet/wet
mySolver.hLeft = createRandomNumber(dryTol+zeroTol, maxWaterHeight);
mySolver.hRight = createRandomNumber(dryTol+zeroTol, maxWaterHeight);
mySolver.determineWetDryState();
ASSERTM(printSolverVariables(), mySolver.wetDryState == solver::AugRie<double>::WetWet);
//test case WetDryInundation
mySolver.bLeft = createRandomNumber(-maxWaterHeight, maxWaterHeight);
mySolver.bRight = mySolver.bLeft+createRandomNumber(0., 100.);
mySolver.hLeft = mySolver.bRight - mySolver.bLeft + createRandomNumber(dryTol+zeroTol, maxWaterHeight);
mySolver.hRight = createRandomNumber(0.,dryTol-zeroTol);
mySolver.determineWetDryState();
ASSERTM(printSolverVariables(), mySolver.wetDryState == solver::AugRie<double>::WetDryInundation);
//test case DryWetInundation
mySolver.bRight = createRandomNumber(-maxWaterHeight, maxWaterHeight);
mySolver.bLeft = mySolver.bRight+createRandomNumber(0., 100.);
mySolver.hLeft = createRandomNumber(0.,dryTol-zeroTol);
mySolver.hRight = mySolver.bLeft - mySolver.bRight + createRandomNumber(dryTol+zeroTol, maxWaterHeight);
mySolver.determineWetDryState();
ASSERTM(printSolverVariables(), mySolver.wetDryState == solver::AugRie<double>::DryWetInundation);
}
}
/**
* Test the function determineWetDrystate(...) of the Augmented Riemann solver for the right inundation limits in one direction.
*
* @param i_leftCellDry true, if the left cell is dry. else: false
*/
void ComponentsTest::checkInundationLimitsInOneDirection(const bool i_leftCellDry) {
//do the tests
for(int i = 0; i < testPhiWallSamples; i++) {
double hLeft = testPhi[0][i];
double hRight = testPhi[1][i];
double huLeft = testPhi[2][i];
double huRight = testPhi[3][i];
double hMiddle = testPhi[4][i];
double bLeft = 0.;
double bRight = 0.;
if(i_leftCellDry == true) {
bLeft = createRandomNumber(-50, 50);
bRight = bLeft - hRight - createRandomNumber(0, 10);
}
else {
bRight = createRandomNumber(-50,50);
bLeft = bRight - hLeft - createRandomNumber(0, 10);
}
solver::AugRie<double>::WetDryState preComputedWetDryState;
if(i_leftCellDry == false) {
if(bLeft + hMiddle < bRight)
preComputedWetDryState = solver::AugRie<double>::WetDryWall;
else
preComputedWetDryState = solver::AugRie<double>::WetDryWallInundation;
}
if(i_leftCellDry == true) {
if(bRight + hMiddle < bLeft)
preComputedWetDryState = solver::AugRie<double>::DryWetWall;
else
preComputedWetDryState = solver::AugRie<double>::DryWetWallInundation;
}
if(i_leftCellDry == true) {
mySolver.hLeft = 0.;
mySolver.huLeft = 0.;
mySolver.hRight = hRight;
mySolver.huRight = huRight;
}
else {
mySolver.hLeft = hLeft;
mySolver.huLeft = huLeft;
mySolver.hRight = 0.;
mySolver.huRight = 0.;
}
mySolver.bLeft = bLeft;
mySolver.bRight = bRight;
mySolver.determineWetDryState();
ASSERT(preComputedWetDryState == mySolver.wetDryState);
}
}
/**
* Test the function determineWetDrystate(...) of the Augmented Riemann solver for inundation with much more effort.
*/
void ComponentsTest::checkInundationLimits() {
checkInundationLimitsInOneDirection(true);
checkInundationLimitsInOneDirection(false);
}
/**
* Check if the function computeNetUpdate(...) of the Augmented Riemann solver computes updates for walls
* in one direction. And Check the positivity of the update.
* @param i_leftCellDry true, if the left cell is dry. else: false.
*/
void ComponentsTest::checkComputeNetUpdatesForWallsInOneDirection(bool i_leftCellDry) {
//do the tests
for(int i = 0; i < testPhiWallSamples; i++) {
double hLeft, hRight, huLeft, huRight, bLeft, bRight;
hLeft = hRight = huLeft = huRight = bLeft = bRight = 0.;
if(i_leftCellDry == true) {
hRight = testPhi[1][i];
huRight = testPhi[3][i];
}
else {
hLeft = testPhi[0][i];
huLeft = testPhi[2][i];
}
if(i_leftCellDry == true) {
bLeft = createRandomNumber(-100, 100);
bRight = bLeft - hRight - createRandomNumber(0, 20);
}
else {
bRight = createRandomNumber(-50,50);
bLeft = bRight - hLeft - createRandomNumber(0, 10);
}
double hUpdateLeft, hUpdateRight, huUpdateLeft, huUpdateRight, maxWaveSpeed = 0.;
mySolver.computeNetUpdates( hLeft, hRight,
huLeft, huRight,
bLeft, bRight,
hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed);
if(mySolver.wetDryState == solver::AugRie<double>::WetDryWall) {
ASSERT_EQUAL_DELTA(hUpdateRight, 0., zeroTol);
ASSERT_EQUAL_DELTA(huUpdateRight, 0., zeroTol);
}
else if(mySolver.wetDryState == solver::AugRie<double>::DryWetWall) {
ASSERT_EQUAL_DELTA(hUpdateLeft, 0., zeroTol);
ASSERT_EQUAL_DELTA(huUpdateLeft, 0., zeroTol);
}
//check if we are positivity preserving
//Mini-Update with CFL
ASSERTM( printSolverVariablesWithResults( hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed ),
hLeft - (.4 / maxWaveSpeed)*hUpdateLeft > -zeroTol );
//Mini-Update with CFL
ASSERTM( printSolverVariablesWithResults( hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed ),
hRight - (.4 / maxWaveSpeed)*hUpdateRight > -zeroTol);
}
}
/**
* Check if the function computeNetUpdate(...) of the
* augmented Riemann solver computes the right updates for walls.
*/
void ComponentsTest::checkComputeNetUpdatesForWalls() {
checkComputeNetUpdatesForWallsInOneDirection(true);
checkComputeNetUpdatesForWallsInOneDirection(false);
}
void ComponentsTest::checkComputeNetUpdatesForPositivity() {
for(int i = 0; i < numberOfRandomTests; i++) {
double hUpdateLeft, hUpdateRight, huUpdateLeft, huUpdateRight, maxWaveSpeed = 0.;
double hLeft = createRandomNumber(0, 200);
double hRight = hLeft - createRandomNumber(-20, 20);
hRight = std::max(0., hRight);
double uLeft = createRandomNumber(-maxWaveSpeed, maxWaveSpeed);
double uRight = maxWaveSpeed + createRandomNumber(-maxWaveSpeedVariation, maxWaveSpeedVariation);
double huLeft = hLeft * uLeft;
double huRight = hRight * uRight;
double bLeft = createRandomNumber(-100, 100);
double bRight = bLeft + createRandomNumber(-2, 2)*(hLeft-hRight);
mySolver.computeNetUpdates( hLeft, hRight,
huLeft, huRight,
bLeft, bRight,
hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed);
if(maxWaveSpeed < zeroTol)
continue;
ASSERTM( printSolverVariablesWithResults( hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed ),
hLeft - (.45 / maxWaveSpeed)*hUpdateLeft > -zeroTol);
ASSERTM( printSolverVariablesWithResults( hUpdateLeft, hUpdateRight,
huUpdateLeft, huUpdateRight,
maxWaveSpeed ),
hRight - (.45 / maxWaveSpeed)*hUpdateRight > -zeroTol);
}
}
/**
* ComponentsTest.h
*
****
**** Collection of elementary unit tests for the Augmented Riemann solver.
****
*
* Created on: Nov 30, 2011
* Last Update: June 12, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*/
#ifndef COMPONENTS_HPP_
#define COMPONENTS_HPP_
#define private public
#define protected public
#include "../solver/AugRie.hpp"
#undef private
#undef protected
#include <string>
class ComponentsTest {
//private:
//! gravity constant.
const double gravity;
//! numerical definition of "dry".
const double dryTol;
//! numerical defition of zero.
const double zeroTol;
//! maximum water height within the tests.
const double maxWaterHeight;
//! maximum wave speed within the tests.
//850km/h = 14166.66 m/s
const double maxWaveSpeed;
//! maximum variation of the speed within the tests.
//50km/h = 833.33 m/s
const double maxWaveSpeedVariation;
//! how many of the tests with random numbers should run.
const int numberOfRandomTests;
//! number of precomputed values available for the tests of the function phi.
const int testPhiSize;
//! number of phi-values, which correspond to "walls", focus: Inundation.
const int testPhiWallSamples;
//! number of phi-values, which correspond to random values.
const int testPhiRandomSamples;
//! maximum number of newton iterations in a regular setup.
const int maxNumberOfNewtonIterationsDefault;
//! maximum number of newton iterations in an expensive setup, focus: test for convergency.
const int maxNumberOfNewtonIterationsExpensive;
//! newton tolerance (when to stop iterating).
const double newtonTol;
//! path of the test file, which contains precomputed values.
const std::string testFileName;
//! Augmented Riemann solver.
solver::AugRie<double> mySolver;
//! water heights and velocities of the Riemann problem.
double hLeft, hRight, uLeft, uRight;
//! array of precomputed test values.
double** testPhi;
//functions
double createRandomNumber(const double min, const double max);
void readTestPhi();
std::string printSolverVariables();
std::string printSolverVariablesWithResults( const double hUpdateLeft, const double hUpdateRight,
const double huUpdateLeft, const double huUpdateRight,
const double maxWaveSpeed );
public:
ComponentsTest();
~ComponentsTest();
//functions
void operator() ();
void checkDetermineRiemannStructure();
void checkComputeMiddleState();
void checkDetermineWetDryStateSimple();
void checkInundationLimitsInOneDirection(const bool i_leftCellDry);
void checkInundationLimits();
void checkComputeNetUpdatesForWallsInOneDirection(const bool i_leftCellDry);
void checkComputeNetUpdatesForWalls();
void checkComputeNetUpdatesForPositivity();
};
#endif /* COMPONENTS_HPP_ */
/**
* UnitTests.cpp
*
****
**** Collection of unit tests for the solvers of the shallow water equations.
****
*
* Created on: Nov 30, 2011
* Last Update: June 12, 2012
*
****
*
* Author: Alexander Breuer
* Homepage: http://www5.in.tum.de/wiki/index.php/Dipl.-Math._Alexander_Breuer
* E-Mail: breuera AT in.tum.de
*
****
*/
#include "cute.h"
#include "ide_listener.h"
#include "cute_runner.h"
#include "ComponentsTest.h"
#include "../solver/AugRieGeoClaw.hpp"
#include <iostream>
/**
* Runs the test suite of unit tests.
*/
void runSuite(){
cute::suite testSuite;
testSuite.push_back(ComponentsTest());
cute::ide_listener lis;
cute::makeRunner(lis)(testSuite, "running the test suite");
}
/**
* Main function.
*
* @return 0 if completed, 1 else.
*/
int main(){
runSuite();
/**
* TODO: Benchmarks will be available with the new 1D-code again (end of 2012?)
*/
// benchmarks::SingleWaveOnASimpleBeach( benchmarks::OneDimensional::AugRie,
// 2000,
// 480,
// "/work/breuera/workspace/tsunami-benchmarks/analytical/single_wave_on_simple_beach/output/SingleWaveOnASimpleBeachAugRie.nc"
// );
//
// benchmarks::SingleWaveOnASimpleBeach( benchmarks::OneDimensional::Hybrid,
// 2000,
// 480,
// "/work/breuera/workspace/tsunami-benchmarks/analytical/single_wave_on_simple_beach/output/SingleWaveOnASimpleBeachHybrid.nc"
// );
// benchmarks::DamBreakDry damBreakDry("/work/breuera/workspace/tsunami-benchmarks/analytical/single_wave_on_simple_beach/output/DamBreakDry");
std::cout << "\nUnit tests finished" << std::endl;
return 0;
}
function[hStar] = calculate_hstar(hLow, hHigh, huLow, huHigh)
%%% constants
zeroTol = 0.00000001;
dryTol = 0.001;
maxWaterHeight = 10000^3;
g = 9.81;
%%% Function phi
phi = @(h) (h <= hLow) .* 2 .* ( sqrt(g.*h) - sqrt(g.*hLow) ) ...
+ (h > hLow) .* (h - hLow) .* sqrt( g/2 .* ( 1 ./ h + 1 ./ hLow ) ) ...
...
+ (h <= hHigh) .* 2 .* ( sqrt(g.*h) - sqrt(g.*hHigh) ) ...
+ (h > hHigh) .* (h - hHigh) .* sqrt( g/2 .* ( 1 ./ h + 1 ./ hHigh ) ) ...
...
+ huHigh ./ hHigh - huLow ./ hLow;
%%%
hMin = min(hLow, hHigh);
%hMax = max(hLow, hHigh)
if phi(hMin) >= 0 && ...
huLow / hLow - huHigh / hHigh + 2*(sqrt(g.*hLow)+sqrt(g.*hHigh)) < zeroTol
hStar = 0.; %large rarefaction
phi(hMin);
return;
end
%tic
hStar = fzero( phi, [zeroTol, maxWaterHeight]);
%toc
%h = zeroTol: 0.01:max(hMax, hStar)+10;
%plot(h, phi(h), hMin, phi(hMin), '-o', hMax, phi(hMax), '-o', hStar, 0, '-o')
%text(hMin, phi(hMin), ' h_{min}')
%text(hMax, phi(hMax), ' h_{max}')
%text(hStar, 0, ' h_{star}')
%xlabel('h')
%ylabel('\phi(h)')
%grid on
\ No newline at end of file
function[size] = create_nc_testphi(path)
%250 meters should be enough (we dont want "extreme"-problems)
maxWaterHeight = 250;
maxHeightVariation = 50;
%300km/h = 5000 m/s should be enough
maxWaveSpeed = 5000;
%25km/h = 416.6666 m/s;
maxSpeedVariation = 416.666666;
dryTol = 0.001;
zeroTol = 0.0000001;
%delete old file
delete(path)
%ask for size
wallSize = input('Please enter the wall sample size: ');
fprintf('wall sample size: %d\n', wallSize);
randomSize = input('Please enter the random sample size: ');
fprintf('random sample size: %d\n', randomSize);
size = randomSize+wallSize;
fprintf('total sample size: %d\n', size);
%create variables
nccreate(path, 'hLow', ...
'Dimensions' , {'sample', size}, ...
'Format', 'classic' ... %netcdf4 seems to have some sort of limit: HDFError
);
nccreate(path, 'hHigh', ...
'Dimensions' , {'sample', size}...
);
nccreate(path, 'huLow', ...
'Dimensions' , {'sample', size}...
);
nccreate(path, 'huHigh', ...
'Dimensions' , {'sample', size}...
);
nccreate(path, 'hStar', ...
'Dimensions' , {'sample', size}...
);
%oprn file (low level)
ncid = netcdf.open(path, 'NC_WRITE');
disp('filling the file with random values')
tic
%set random values
%fill hLow with random values
randHeights = rand(1, size)*maxWaterHeight+dryTol;
varid = netcdf.inqVarID(ncid,'hLow');
%counting starts at 0 for low level access
%and at 1 for hight level acess
netcdf.putVar(ncid, varid, 0, size, randHeights);
varid = netcdf.inqVarID(ncid,'hHigh');
%fill with the same value for walls
netcdf.putVar(ncid, varid, 0, wallSize, randHeights(1:wallSize));
%random values for the rest
randHeights = randHeights(wallSize+1:size) + ...
(2*(rand(1, randomSize)-0.5))*maxHeightVariation;
randHeights = max(randHeights, dryTol+zeroTol);
netcdf.putVar(ncid, varid, wallSize, randomSize, randHeights)
%fill huLow with random values
randSpeeds = transpose((2*(rand(1, size)-0.5))*maxWaveSpeed);
netcdf.sync(ncid); %sync before reading
hLowVec = ncread(path, 'hLow', 1, size);
%hu = h * u
huLowVec = randSpeeds .* hLowVec;
varid = netcdf.inqVarID(ncid,'huLow');
netcdf.putVar(ncid, varid, 0, size, huLowVec);
varid = netcdf.inqVarID(ncid,'huHigh');
%fill with the same values + opposite sign for walls
netcdf.putVar(ncid, varid, 0, wallSize, -huLowVec(1:wallSize));
%random values for the rest
randSpeeds = randSpeeds(wallSize+1:size) + ...
transpose((2*(rand(1, randomSize)-0.5))*maxSpeedVariation);
netcdf.sync(ncid); %sync before reading
hHighVec = ncread(path, 'hLow', wallSize, randomSize);
%hu = h * u
huHighVec = randSpeeds .* hHighVec;
%random values for the rest
netcdf.putVar(ncid, varid, wallSize, randomSize, huHighVec);
netcdf.close(ncid)
toc
ncwriteatt(path,'/','title', 'Computed solutions for the middle state which arises in the Shallow Water Equations for homogeneous Riemann Problems')
ncwriteatt(path,'/','author','Alexander Breuer')
ncwriteatt(path,'/','history', ...
strcat(...
'MATLAB R2011b, shallowwater.m (',...
'maxWaterHeight=', num2str(maxWaterHeight), ' maxHeightVariation=', num2str(maxHeightVariation), ' maxWaveSpeed=', num2str(maxWaveSpeed), ' maxSpeedVariation=', num2str(maxSpeedVariation), ' dryTol=', num2str(dryTol), ' zeroTol=', num2str(zeroTol)...
,')'...
))
ncwriteatt(path,'/','institution','Technische Universitt Mnchen, Department of Informatics, Chair of Scientific Computing')
ncwriteatt(path,'/','source','roots of an algebraic function')
ncwriteatt(path,'/','references','http://www5.in.tum.de')
ncwriteatt(path,'/','creation_date',datestr(now))
ncdisp(path)
%ncread(path, 'hLow', 1, size)
%ncread(path, 'hHigh', 1, size)
%ncread(path, 'huLow', 1, size)
%ncread(path, 'huHigh', 1, size)
\ No newline at end of file
function[hLowVec, hHighVec, huLowVec, huHighVec] = read_nc_testphi(path)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment