From 6374f084a08571f5bbaf8a624a16a1b9d8c68c6d Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Wed, 15 Jun 2011 07:42:04 +0000 Subject: [PATCH] addBoundary*Operator, static updateAnimationFile and small changes in Initfile --- AMDiS/src/Global.h | 2 + AMDiS/src/Initfile.cc | 96 ++++---- AMDiS/src/Initfile.h | 364 ++++++++++++++++------------ AMDiS/src/ProblemStat.cc | 26 ++ AMDiS/src/ProblemStat.h | 20 ++ AMDiS/src/io/VtkWriter.h | 2 +- AMDiS/src/reinit/ElementLevelSet.cc | 2 +- demo/init/bunny.init | 1 + demo/init/ellipt.dat.2d | 27 ++- demo/src/bunny.cc | 6 +- demo/src/ellipt.cc | 302 ++++++++++++++++++++++- 11 files changed, 626 insertions(+), 222 deletions(-) diff --git a/AMDiS/src/Global.h b/AMDiS/src/Global.h index 0be17a4b..8bdb675c 100644 --- a/AMDiS/src/Global.h +++ b/AMDiS/src/Global.h @@ -56,6 +56,7 @@ #include <mpi.h> #endif +#include <boost/algorithm/string.hpp> #include "boost/tuple/tuple.hpp" #include "AMDiS_fwd.h" @@ -461,6 +462,7 @@ namespace AMDiS { GRD_PSI, GRD_PHI }; + } #endif // AMDIS_GLOBAL_H diff --git a/AMDiS/src/Initfile.cc b/AMDiS/src/Initfile.cc index 595795aa..d0aef6f9 100644 --- a/AMDiS/src/Initfile.cc +++ b/AMDiS/src/Initfile.cc @@ -8,25 +8,29 @@ using namespace std; namespace AMDiS { - /// the small parser for the initfile. see description of read(Initfile&, istream&) + /// the small parser for the initfile. see description of + /// read(Initfile&,istream&) struct Parser { Parser(const string& line) { size_t pos = line.find(':'); - if (pos == string::npos) - throw runtime_error("cannot find the delimiter ':' in line '" + line + "'"); + if (pos == string::npos) { + throw runtime_error("cannot find the delimiter ':' in line " + "'" + line + "'"); + } name = line.substr(0, pos); value = line.substr(pos + 1, line.length() - (pos + 1)); // remove everything after the % pos = value.find('%'); if (pos != string::npos) - value = value.substr(0, pos); + value = value.substr(0, pos); } string name; string value; }; + Initfile* Initfile::singlett= NULL; std::set<std::string> Initfile::fn_include_list; @@ -39,7 +43,7 @@ namespace AMDiS { fn_include_list.clear(); singlett->read(in); singlett->getInternalParameters(); - + // initialize global strcutures using parameters Global::init(); } @@ -53,8 +57,8 @@ namespace AMDiS { std::ifstream inputFile; inputFile.open(fn.c_str(), std::ios::in); if (!inputFile.is_open()) - throw runtime_error("init-file cannot be opened for reading"); - + throw runtime_error("init-file cannot be opened for reading"); + fn_include_list.insert(fn); read(inputFile); } @@ -71,34 +75,37 @@ namespace AMDiS { std::string whitespaces = " \t\r\f"; std::string sw(swap); size_t pos0 = sw.find_first_not_of(whitespaces); - - if (pos0 != std::string::npos && sw[pos0] != '%' && sw[pos0] != '#' && sw[pos0] != 0) { - // parse line and extract map: tag->value - Parser parser(sw); - operator[](parser.name) = parser.value; - } else if (sw[pos0] == '#' && static_cast<size_t>(sw.find("#include")) == pos0) { - // include file by '#include "filename"' or '#include <filename>' - size_t pos = sw.find_first_not_of(whitespaces, std::string("#include").size() + 1); - size_t epos = 0; - std::string fn = ""; - std::stringstream errorMsg; - switch (char c= swap[pos++]) { - case '<': - c= '>'; - case '\"': - whitespaces += c; - epos = sw.find_first_of(whitespaces, pos); - fn = sw.substr(pos, epos - pos); - - if (sw[epos]!=c) { - errorMsg << "filename in #include not terminated by " << c; - throw std::runtime_error(errorMsg.str()); - } - break; - default: - throw std::runtime_error("no filename given for #include"); - } - read(fn); + + if (pos0 != std::string::npos && sw[pos0] != '%' + && sw[pos0] != '#' && sw[pos0] != 0) { + // parse line and extract map: tag->value + Parser parser(sw); + operator[](parser.name) = parser.value; + } else if (sw[pos0] == '#' + && static_cast<size_t>(sw.find("#include")) == pos0) { + // include file by '#include "filename"' or '#include <filename>' + size_t pos = sw.find_first_not_of(whitespaces, + std::string("#include").size() + 1); + size_t epos = 0; + std::string fn = ""; + std::stringstream errorMsg; + switch (char c= swap[pos++]) { + case '<': + c= '>'; + case '\"': + whitespaces += c; + epos = sw.find_first_of(whitespaces, pos); + fn = sw.substr(pos, epos - pos); + + if (sw[epos]!=c) { + errorMsg << "filename in #include not terminated by " << c; + throw std::runtime_error(errorMsg.str()); + } + break; + default: + throw std::runtime_error("no filename given for #include"); + } + read(fn); } in.getline(swap, line_length); } @@ -109,8 +116,8 @@ namespace AMDiS { { for (int i = 0; i < argc; i++) { if (strcmp("-rs", argv[i]) == 0) { - std::string input(argv[i + 1]); - add("argv->rs", input, 0); + std::string input(argv[i + 1]); + add("argv->rs", input, 0); } } } @@ -122,15 +129,15 @@ namespace AMDiS { int val = 0; get("level of information", val, 0); msgInfo = val; - + val = 1; get("WAIT", val, 0); msgWait = val; - + val = 1; get("parameter information", val, 0); paramInfo = val; - + val = 0; get("break on missing tag", val, 0); breakOnMissingTag = val; @@ -145,7 +152,7 @@ namespace AMDiS { { initIntern(); for (Initfile::iterator it = singlett->begin(); it != singlett->end(); it++) - std::cout << (*it).first << " => " << (*it).second << std::endl; + std::cout << (*it).first << " => " << (*it).second << std::endl; } @@ -153,7 +160,7 @@ namespace AMDiS { void Initfile::write(ostream& out) { for (Initfile::iterator it = begin() ; it!=end(); it++) - out << (*it).first << ": " << (*it).second << std::endl; + out << (*it).first << ": " << (*it).second << std::endl; } @@ -164,8 +171,7 @@ namespace AMDiS { outFile.open(fn.c_str(), std::ios::out); if (!outFile.is_open()) throw runtime_error("init-file cannot be opened for writing"); - + write(outFile); } - -} +} // end namespace AMDiS diff --git a/AMDiS/src/Initfile.h b/AMDiS/src/Initfile.h index 90538216..e23c0210 100644 --- a/AMDiS/src/Initfile.h +++ b/AMDiS/src/Initfile.h @@ -1,3 +1,14 @@ +// +// Software License for AMDiS +// +// Copyright (c) 2010 Dresden University of Technology +// All rights reserved. +// Authors: Simon Vey, Thomas Witkowski et al. +// +// This file is part of AMDiS +// +// See also license.opensource.txt in the distribution. + #ifndef INITFILE_H #define INITFILE_H @@ -25,23 +36,25 @@ namespace AMDiS { namespace InitfileInternal { - + /// Exceptions struct WrongVectorSize : std::runtime_error { WrongVectorSize(std::string m) - : std::runtime_error(m) + : std::runtime_error(m) {} }; + struct NoDelim : std::runtime_error { NoDelim(std::string m) - : std::runtime_error(m) + : std::runtime_error(m) {} }; + struct WrongVectorFormat : std::runtime_error { WrongVectorFormat(std::string m) - : std::runtime_error(m) + : std::runtime_error(m) {} }; @@ -49,33 +62,33 @@ namespace AMDiS { struct WrongValueFormat : std::runtime_error { static std::string name(int) { - return "int"; + return "int"; } - + static std::string name(bool) { - return "bool"; + return "bool"; } - + static std::string name(double) { - return "double"; + return "double"; } - + static std::string name(unsigned int) { - return "unsigned int"; + return "unsigned int"; } template<typename G> static std::string name(G) { - return std::string(typeid(G).name()); + return std::string(typeid(G).name()); } - + WrongValueFormat(std::string value) - : std::runtime_error(std::string("cannot convert '") + - value + std::string("' into <") + name(T()) + ">") + : std::runtime_error(std::string("cannot convert '") + + value + std::string("' into <") + name(T()) + ">") {} }; @@ -83,38 +96,38 @@ namespace AMDiS { struct BadArithmeticExpression : std::runtime_error { static std::string name(int) { - return "int"; + return "int"; } - + static std::string name(bool) { - return "bool"; + return "bool"; } - + static std::string name(double) { - return "double"; + return "double"; } - + static std::string name(unsigned int) { - return "unsigned int"; + return "unsigned int"; } - + template<typename G> static std::string name(G) { - return std::string(typeid(G).name()); + return std::string(typeid(G).name()); } - + BadArithmeticExpression(std::string m, std::string value) - : std::runtime_error(std::string("cannot evaluate expression '") + - value + std::string("' into <") + name(T()) + - ">\nParser message: '" + m + "'") + : std::runtime_error(std::string("cannot evaluate expression '") + + value + std::string("' into <") + name(T()) + + ">\nParser message: '" + m + "'") {} }; - + /// trim std::string inline std::string trim(const std::string& oldStr) { @@ -124,14 +137,15 @@ namespace AMDiS { } - /// return the delimiter or throw an exception if there is no known delimiter in value + /// return the delimiter or throw an exception if there is no known + /// delimiter in value inline size_t checkDelim(const std::string& value, const std::string& delims) { size_t pos(std::string::npos); for (unsigned i = 0; i < delims.length(); i++) { - pos = value.find(delims[i]); - if (pos != std::string::npos) - return i; + pos = value.find(delims[i]); + if (pos != std::string::npos) + return i; } throw NoDelim("cannot detect the delimiter in " + value); return 0; @@ -139,12 +153,12 @@ namespace AMDiS { /** parse an container from tag tag. The Container must have the properties: - * - type value_type - * - member function push_back - */ + * - type value_type + * - member function push_back + */ template< typename Container > inline void getContainer(const std::string val_, Container& c) - { + { // accepted brackets and delimiters for vector input std::string begBrackets= "{[("; std::string endBrackets= "}])"; @@ -154,35 +168,37 @@ namespace AMDiS { std::string val = trim(val_); size_t pos = begBrackets.find(val[0]); if (pos == std::string::npos) - throw WrongVectorFormat("cannot convert '" + val + "' into a list. No leading bracket found!"); + throw WrongVectorFormat("cannot convert " + "'" + val + "' into a list. No leading bracket found!"); if (val[val.length() - 1] != endBrackets[pos]) - throw WrongVectorFormat("begin and end bracket are different in value '" + val + "'"); + throw WrongVectorFormat("begin and end bracket are different in" + " value '" + val + "'"); size_t oldPos = 1; size_t curDelim = 0; typedef typename Container::value_type ValueType; ValueType swap; try { - curDelim = checkDelim(val, delims); - pos = val.find(delims[curDelim], oldPos); - while (pos != std::string::npos) { - std::string curWord = val.substr(oldPos, pos - oldPos); - oldPos = pos + 1; - convert(curWord, swap); - c.push_back(swap); - pos= val.find(delims[curDelim], oldPos); - } - //last entry - std::string curWord = val.substr(oldPos, val.length() - 1 - oldPos); - convert(curWord, swap); - c.push_back(swap); + curDelim = checkDelim(val, delims); + pos = val.find(delims[curDelim], oldPos); + while (pos != std::string::npos) { + std::string curWord = val.substr(oldPos, pos - oldPos); + oldPos = pos + 1; + convert(curWord, swap); + c.push_back(swap); + pos = val.find(delims[curDelim], oldPos); + } + //last entry + std::string curWord = val.substr(oldPos, val.length() - 1 - oldPos); + convert(curWord, swap); + c.push_back(swap); } catch (NoDelim nd) { - std::string curWord = val.substr(1, val.length() - 2); - curWord = trim(curWord); - if (curWord.length() > 0) { - // container with one entry - convert(curWord, swap); - c.push_back(swap); - } + std::string curWord = val.substr(1, val.length() - 2); + curWord = trim(curWord); + if (curWord.length() > 0) { + // container with one entry + convert(curWord, swap); + c.push_back(swap); + } } } @@ -197,43 +213,62 @@ namespace AMDiS { /// convert string to intrinsic type template<typename T> inline void convert(const std::string valStr, T& value , - typename boost::enable_if<boost::is_pod<T> >::type* p = NULL , - typename boost::disable_if<boost::is_enum<T> >::type* p2 = NULL) + typename boost::enable_if<boost::is_pod<T> >::type* p = NULL , + typename boost::disable_if<boost::is_enum<T> >::type* p2 = NULL) { using boost::lexical_cast; using boost::numeric_cast; mu::Parser parser; - parser.DefineConst(_T("M_PI"), m_pi); parser.DefineConst(_T("M_E"), m_e); + try { - parser.SetExpr(valStr); - value = numeric_cast< T >(parser.Eval()); - } catch(boost::bad_lexical_cast e) { - throw WrongValueFormat< T >(valStr); - } catch(boost::bad_numeric_cast e) { - throw WrongValueFormat< T >(valStr); + parser.SetExpr(valStr); + value = numeric_cast< T >(parser.Eval()); + } catch (boost::bad_lexical_cast e) { + throw WrongValueFormat< T >(valStr); + } catch (boost::bad_numeric_cast e) { + throw WrongValueFormat< T >(valStr); } catch (mu::Parser::exception_type &e) { - throw BadArithmeticExpression<T>(e.GetMsg(), valStr); + throw BadArithmeticExpression<T>(e.GetMsg(), valStr); } } template<typename T> inline void convert(const std::string valStr, T& value, - typename boost::enable_if< boost::is_enum< T > >::type* p = NULL) + typename boost::enable_if< boost::is_enum< T > >::type* p = NULL) { - unsigned int swap = 0; + int swap = 0; try { - swap = boost::lexical_cast<unsigned int>(trim(valStr)); - } catch(boost::bad_lexical_cast e) { - throw WrongValueFormat< T >(valStr); + swap = boost::lexical_cast<int>(trim(valStr)); + } catch (boost::bad_lexical_cast e) { + throw WrongValueFormat< T >(valStr); } value = static_cast< T >(swap); } + /// convert special enums + inline void convert(const std::string valStr, Norm& value) + { + std::string swapStr = boost::to_upper_copy(valStr); + + if (swapStr == "NO_NORM") + value = static_cast< Norm >(NO_NORM); + else if (swapStr == "H1_NORM") + value = static_cast< Norm >(H1_NORM); + else if (swapStr == "L2_NORM") + value = static_cast< Norm >(L2_NORM); + else { + int swap= 0; + convert(valStr, swap); + value = static_cast< Norm >(swap); + } + } + + /// convert string to WorldVector template< typename T > inline void convert(const std::string valStr, WorldVector<T>& c) @@ -241,10 +276,10 @@ namespace AMDiS { std::vector<T> temp_vec; getContainer(valStr, temp_vec); if (static_cast<int>(temp_vec.size()) != c.getSize()) - throw WrongVectorSize("wrong number of entries for WorldVector"); - + throw WrongVectorSize("wrong number of entries for WorldVector"); + for (unsigned i = 0; i < temp_vec.size(); i++) - c[i] = temp_vec[i]; + c[i] = temp_vec[i]; } @@ -264,13 +299,15 @@ namespace AMDiS { } - /// convert value of arbitrary type to string using stringstream and operator<< for type + /// convert value of arbitrary type to string using stringstream and + /// operator<< for type template<typename T> inline void convert(const T value, std::string& valStr) { std::stringstream ss; + ss.precision(6); ss << value; - valStr= ss.str(); + valStr = ss.str(); } @@ -280,24 +317,23 @@ namespace AMDiS { { std::vector<T> temp_vec(c.getSize()); for (unsigned i = 0; i < temp_vec.size(); i++) - temp_vec[i] = c[i]; + temp_vec[i] = c[i]; convert(temp_vec, valStr); } } // end namespace InitfileInternal - - /** The entry in an initfile. This helper class was constructed to allow calls like - * val = data.get(tag) - * for arbitrary types of val. At current stage, only double and bool is supported - */ + /** The entry in an initfile. This helper class was constructed to allow calls + * like val = data.get(tag) for arbitrary types of val. At current stage, only + * double and bool is supported + */ struct InitEntry { ///the value as string std::string valStr; /// initialize with value as string InitEntry(std::string v = "") - : valStr(v) + : valStr(v) {} /// cast string to type T @@ -341,59 +377,71 @@ namespace AMDiS { } - /** Basis data container as a map of tag on a value as strings. The container throws an exception, if the tag was not found. - */ + /** Basis data container as a map of tag on a value as strings. The container + * throws an exception, if the tag was not found. + */ struct Initfile : public std::map<std::string, std::string> { typedef std::map< std::string, std::string > super; + /// Exceptions struct TagNotFound : std::invalid_argument { TagNotFound(std::string m) - : std::invalid_argument(m) + : std::invalid_argument(m) {} }; - struct TagNotFoundBreak : std::invalid_argument { // print 'tag not found' and exit + + struct TagNotFoundBreak : std::invalid_argument { + // print 'tag not found' and exit TagNotFoundBreak(std::string m) - : std::invalid_argument(m) + : std::invalid_argument(m) {} }; - - /** initialize init-file from file with filename in, read data and save it to singleton-map - * @param in: filename string - */ + + + /** initialize init-file from file with filename in, read data and save it + * to singleton-map + * @param in: filename string + */ static void init(std::string in); static void init(int print, string filename, const char *flags = NULL) { - WARNING("Parameters::init(int,std::string,const char*) is depreciated. Use Parameters::init(std::string) instead!\n"); - init(filename); + WARNING("Parameters::init(int,std::string,const char*) is depreciated. " + "Use Parameters::init(std::string) instead!\n"); + init(filename); } - - /** Static get routine for getting parameter-values from init-file initialized in init()-method. - * Cast the value to the desired type using std::stringstream. - * @param tag: The tag to look for - * @param value: The result. - * @param debugInfo: msgInfo for current parameter. (0..no printing, 1..print missing parameter info, 2..print parameter value) [optional] - */ + + + /** Static get routine for getting parameter-values from init-file + * initialized in init()-method. + * Cast the value to the desired type using std::stringstream. + * @param tag: The tag to look for + * @param value: The result. + * @param debugInfo: msgInfo for current parameter. (0..no printing, + * 1..print missing parameter info, 2..print parameter value) [optional] + */ template<typename T> static void get(const std::string tag, T& value, int debugInfo = -1) { using namespace InitfileInternal; initIntern(); if (debugInfo == -1) - debugInfo = singlett->getMsgInfo(); - + debugInfo = singlett->getMsgInfo(); + try { - std::string valStr(singlett->checkedGet(tag)); - valStr = trim(valStr); - convert(valStr, value); - if (debugInfo == 2) - std::cout << "Parameter '" << tag << "' initialized with: " << value << std::endl; + std::string valStr(singlett->checkedGet(tag)); + valStr = trim(valStr); + convert(valStr, value); + if (debugInfo == 2) { + std::cout << "Parameter '" << tag << "'" + << " initialized with: " << value << std::endl; + } } catch (TagNotFound ia) { - if (debugInfo >= 1) - std::cout << ia.what() << std::endl; + if (debugInfo >= 1) + std::cout << ia.what() << std::endl; } } @@ -405,16 +453,16 @@ namespace AMDiS { int debugInfo = singlett->getMsgInfo(); InitEntry result; try { - std::string valStr(singlett->checkedGet(tag)); - valStr = trim(valStr); - result = InitEntry(valStr); + std::string valStr(singlett->checkedGet(tag)); + valStr = trim(valStr); + result = InitEntry(valStr); } catch (TagNotFound ia) { - if (debugInfo >= 1) - std::cout << ia.what() << std::endl; + if (debugInfo >= 1) + std::cout << ia.what() << std::endl; } return result; } - + /// update map tag->value_old to tag->value in singleton template<typename T> @@ -423,17 +471,19 @@ namespace AMDiS { using namespace InitfileInternal; initIntern(); if (debugInfo == -1) - debugInfo = singlett->getMsgInfo(); - + debugInfo = singlett->getMsgInfo(); + std::string swap = ""; convert(value, swap); (*singlett)[trim(tag)] = swap; // update msg parameters msgInfo, msgWait, paramInfo singlett->getInternalParameters(); if (debugInfo == 2) - std::cout << "Parameter '" << tag << "' set to: " << value << std::endl; + std::cout << "Parameter '" << tag << "'" + << " set to: " << value << std::endl; } - + + /// add map tag->value to data in singleton template< typename T > static void add(const std::string tag, T& value, int debugInfo = -1) @@ -441,43 +491,51 @@ namespace AMDiS { set(tag, value, debugInfo); } + /// rescheduling parameter static void readArgv(int argc, char **argv); + /// Returns specified info level static int getMsgInfo() { return (singlett != NULL) ? singlett->msgInfo : 0; } + /// Returns specified wait value static int getMsgWait() { return (singlett != NULL) ? singlett->msgWait : 0; } - + + /// Checks whether parameters are initialized. if not, call init() static bool initialized() { return (singlett != NULL); } + /// return pointer to singleton static Initfile *getSingleton() { return singlett; } - + + /// print all data in singleton to std::cout static void printParameters(); + /// clear data in singleton static void clearData() { initIntern(); singlett->clear(); } - + + /// save singlett-data to file with filename fn static void save(std::string fn) { @@ -485,64 +543,70 @@ namespace AMDiS { singlett->write(fn); } - protected: +protected: Initfile() - : msgInfo(0), - msgWait(1), - paramInfo(1), - breakOnMissingTag(0) + : msgInfo(0), + msgWait(1), + paramInfo(1), + breakOnMissingTag(0) {} - + + static void initIntern() { if (singlett == NULL) - singlett = new Initfile; + singlett = new Initfile; } + /// list of processed files static std::set< std::string > fn_include_list; + /// pointer to the singleton that contains the data static Initfile* singlett; - - /// return the value of the given tag or throws an exception if the tag does not exist + + + /// return the value of the given tag or throws an exception if the tag + /// does not exist std::string checkedGet(const std::string& tag) const { super::const_iterator it = find(tag); if (it == end()) { - if (breakOnMissingTag == 0 || msgInfo <= 2) - throw TagNotFound("there is no tag '"+ tag + "'"); - else - throw TagNotFoundBreak("required tag '"+ tag + "' not found"); + if (breakOnMissingTag == 0 || msgInfo <= 2) + throw TagNotFound("there is no tag '" + tag + "'"); + else + throw TagNotFoundBreak("required tag '" + tag + "' not found"); } return it->second; } + /** Fill the initfile from an input stream. - * @param in: the stream to fill the data from. - * Current dataformat: tag:value - * Comment char: percent '%' - * Include files: #include "filename" or #include <filename> - */ + * @param in: the stream to fill the data from. + * Current dataformat: tag:value + * Comment char: percent '%' + * Include files: #include "filename" or #include <filename> + */ void read(std::istream& in); /// Fill the initfile from a file with filename fn void read(std::string fn); - + /** Write data-map to initfile - * @param out: the stream to fill the data in. - */ + * @param out: the stream to fill the data in. + */ void write(std::ostream& out); /// Write data-map to initfile with filename fn void write(std::string fn); - + /// read parameters for msgInfo, msgWait, paramInfo void getInternalParameters(); - + int msgInfo, msgWait, paramInfo, breakOnMissingTag; }; - + typedef Initfile Parameters; } // end namespace AMDiS diff --git a/AMDiS/src/ProblemStat.cc b/AMDiS/src/ProblemStat.cc index 047c9f77..97e56a52 100644 --- a/AMDiS/src/ProblemStat.cc +++ b/AMDiS/src/ProblemStat.cc @@ -1535,6 +1535,32 @@ namespace AMDiS { } + void ProblemStatSeq::addBoundaryMatrixOperator(BoundaryType type, + Operator *op, int row, int col) + { + FUNCNAME("ProblemStat::addBoundaryOperator()"); + + RobinBC *robin = + new RobinBC(type, NULL, op, componentSpaces[row], componentSpaces[col]); + + if (systemMatrix && (*systemMatrix)[row][col]) + (*systemMatrix)[row][col]->getBoundaryManager()->addBoundaryCondition(robin); + } + + + void ProblemStatSeq::addBoundaryVectorOperator(BoundaryType type, + Operator *op, int row) + { + FUNCNAME("ProblemStat::addBoundaryOperator()"); + + RobinBC *robin = + new RobinBC(type, op, NULL, componentSpaces[row]); + + if (rhs) + rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(robin); + } + + void ProblemStatSeq::assembleOnOneMesh(FiniteElemSpace *feSpace, Flag assembleFlag, DOFMatrix *matrix, DOFVector<double> *vector) diff --git a/AMDiS/src/ProblemStat.h b/AMDiS/src/ProblemStat.h index 6e870973..a04a3aa5 100644 --- a/AMDiS/src/ProblemStat.h +++ b/AMDiS/src/ProblemStat.h @@ -289,6 +289,26 @@ namespace AMDiS { /// Adds a periodic boundary condition. virtual void addPeriodicBC(BoundaryType type, int row, int col); + /// add boundary operator to matrix side + virtual void addBoundaryMatrixOperator(BoundaryType type, + Operator *op, int row, int col); + + virtual void addBoundaryMatrixOperator(BoundaryType type, + Operator &op, int row, int col) + { + addBoundaryMatrixOperator(type, &op, row, col); + } + + /// add boundary operator to rhs (vector) side + virtual void addBoundaryVectorOperator(BoundaryType type, + Operator *op, int row); + + virtual void addBoundaryVectorOperator(BoundaryType type, + Operator &op, int row) + { + addBoundaryVectorOperator(type, &op, row); + } + /** \brief * This function assembles a DOFMatrix and a DOFVector for the case, * the meshes from row and col FE-space are equal. diff --git a/AMDiS/src/io/VtkWriter.h b/AMDiS/src/io/VtkWriter.h index a10939b0..430a3efc 100644 --- a/AMDiS/src/io/VtkWriter.h +++ b/AMDiS/src/io/VtkWriter.h @@ -102,7 +102,7 @@ namespace AMDiS { } /// Adds a new entry to a ParaView animation file. - int updateAnimationFile(std::string valueFilename, + static int updateAnimationFile(std::string valueFilename, std::vector< std::string > *paraViewAnimationFrames, std::string animationFilename); protected: diff --git a/AMDiS/src/reinit/ElementLevelSet.cc b/AMDiS/src/reinit/ElementLevelSet.cc index 9c3e6cc7..64ae1956 100644 --- a/AMDiS/src/reinit/ElementLevelSet.cc +++ b/AMDiS/src/reinit/ElementLevelSet.cc @@ -404,7 +404,7 @@ ElementLevelSet::calcIntersecNormal_3d(WorldVector<double> &normalVec) int ElementLevelSet::getVertexPos(const DimVec<double> barCoords) { - double vertex_val; + double vertex_val= 0.0; for (int i=0; i<=dim; ++i) { if (barCoords[i] > 1-1.e-15) { diff --git a/demo/init/bunny.init b/demo/init/bunny.init index 0e496538..7c67faf2 100644 --- a/demo/init/bunny.init +++ b/demo/init/bunny.init @@ -6,6 +6,7 @@ bunnyMesh->global refinements: 0 bunny->mesh: bunnyMesh bunny->dim: 2 +bunny->components: 1 bunny->polynomial degree[0]: 1 bunny->solver: cg diff --git a/demo/init/ellipt.dat.2d b/demo/init/ellipt.dat.2d index e01f7688..3a5ce968 100644 --- a/demo/init/ellipt.dat.2d +++ b/demo/init/ellipt.dat.2d @@ -1,32 +1,35 @@ dimension of world: 2 -elliptMesh->macro file name: ./macro/macro.stand.2d +elliptMesh->macro file name: ./macro/macro.square.2d elliptMesh->global refinements: 0 ellipt->mesh: elliptMesh ellipt->dim: 2 ellipt->polynomial degree[0]: 1 -ellipt->components: 1 +ellipt->polynomial degree[1]: 1 +ellipt->components: 2 -ellipt->solver: cg +ellipt->solver: umfpack %cg +ellipt->solver->symmetric strategy: 1 +ellipt->solver->store symbolic: 0 ellipt->solver->max iteration: 1000 ellipt->solver->tolerance: 1.e-8 ellipt->solver->info: 2 ellipt->solver->left precon: diag ellipt->solver->right precon: no -ellipt->estimator[0]: residual -ellipt->estimator[0]->error norm: 1 % 1: H1_NORM, 2: L2_NORM -ellipt->estimator[0]->C0: 0.1 % constant of element residual -ellipt->estimator[0]->C1: 0.1 % constant of jump residual +%ellipt->estimator[0]: residual +%ellipt->estimator[0]->error norm: H1_NORM % 1: H1_NORM, 2: L2_NORM +%ellipt->estimator[0]->C0: 0.1 % constant of element residual +%ellipt->estimator[0]->C1: 0.1 % constant of jump residual -ellipt->marker[0]->strategy: 2 % 0: no adaption 1: GR 2: MS 3: ES 4:GERS -ellipt->marker[0]->MSGamma: 0.5 +%ellipt->marker[0]->strategy: 0 % 0: no adaption 1: GR 2: MS 3: ES 4:GERS +%ellipt->marker[0]->MSGamma: 0.5 -ellipt->adapt[0]->tolerance: 1e-4 -ellipt->adapt[0]->refine bisections: 2 +%ellipt->adapt[0]->tolerance: 1e-4 +%ellipt->adapt[0]->refine bisections: 2 -ellipt->adapt->max iteration: 10 +ellipt->adapt->max iteration: 0 ellipt->output->filename: output/ellipt ellipt->output->ParaView format: 1 diff --git a/demo/src/bunny.cc b/demo/src/bunny.cc index 883e7d18..43fae19c 100644 --- a/demo/src/bunny.cc +++ b/demo/src/bunny.cc @@ -56,10 +56,10 @@ int main(int argc, char* argv[]) bunny.initialize(INIT_ALL); // === create adapt info === - AdaptInfo *adaptInfo = new AdaptInfo("bunny->adapt"); + AdaptInfo adaptInfo("bunny->adapt"); // === create adapt === - AdaptStationary *adapt = new AdaptStationary("bunny->adapt", &bunny, adaptInfo); + AdaptStationary adapt("bunny->adapt", bunny, adaptInfo); // ===== create matrix operator ===== Operator matrixOperator(bunny.getFeSpace()); @@ -75,7 +75,7 @@ int main(int argc, char* argv[]) bunny.addVectorOperator(&rhsOperator, 0); // ===== start adaption loop ===== - adapt->adapt(); + adapt.adapt(); bunny.writeFiles(adaptInfo, true); diff --git a/demo/src/ellipt.cc b/demo/src/ellipt.cc index b52698c1..a5ad31d1 100644 --- a/demo/src/ellipt.cc +++ b/demo/src/ellipt.cc @@ -1,4 +1,6 @@ #include "AMDiS.h" +#include "ProblemStatDbg.h" +#include "Debug.h" using namespace AMDiS; using namespace std; @@ -7,6 +9,284 @@ using namespace std; // ===== function definitions ================================================ // =========================================================================== +class MyProblemVec : public ProblemStatDbg +{ +public: + MyProblemVec(std::string nameStr, ProblemIterationInterface *problemIteration = NULL) + : ProblemStatDbg(nameStr,problemIteration) {} + + SolverMatrix<Matrix<DOFMatrix*> >* getSolverMatrix() { return &solverMatrix; } + void setSolverMatrix(SolverMatrix<Matrix<DOFMatrix*> >& solverMatrix_) { solverMatrix= solverMatrix_; } + + + inline DOFVector<double>* getRhsVector(int i = 0) + { + return rhs->getDOFVector(i); + } +}; + +class MyIteration : public StandardProblemIteration +{ +public: + MyIteration(MyProblemVec *prob_) : StandardProblemIteration(prob_), prob(prob_) {} + ~MyIteration() {} + + Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION) + { FUNCNAME("PIteration::oneIteration()"); + Flag flag, markFlag; + + if (toDo.isSet(MARK)) + markFlag = prob->markElements(adaptInfo); + else + markFlag = 3; + + // refine + if (toDo.isSet(ADAPT) && markFlag.isSet(MESH_REFINED)) + flag= prob->refineMesh(adaptInfo); + // coarsen + if (toDo.isSet(ADAPT) && markFlag.isSet(MESH_COARSENED)) + flag|= prob->coarsenMesh(adaptInfo); + + if (toDo.isSet(SOLVE)) { + prob->buildAfterCoarsen(adaptInfo, markFlag, true, true); + + MSG("apply Dirichlet BC...\n"); + bool inside= false; + WorldVector<double> p1; + p1[0]= 1.0; + p1[1]= -1.0; + for (int i= 0; i<prob->getSolution()->getSize(); ++i) { + DegreeOfFreedom idx1= getDOFidxAtCoords(prob->getSolution()->getDOFVector(i), p1, inside); + if(inside) { + MSG("set DBC to row %d...\n",idx1); + applyDbc(prob->getSystemMatrix(i,i)->getBaseMatrix(), *prob->getRhsVector(i), idx1, 0.0); + } else { + MSG("idx not found!!!\n"); + } + } + +// prob->writeDbgMatrix("ellipt_mat.dat"); +// applySingularPertubation(prob->getSystemMatrix(0,0)->getBaseMatrix()); +// applySingularDBC(prob->getSystemMatrix(0,0)->getBaseMatrix()); + + SolverMatrix<Matrix<DOFMatrix*> > solverMatrix; + solverMatrix.setMatrix(*prob->getSystemMatrix()); + prob->setSolverMatrix(solverMatrix); + + debug::writeMatlabMatrix(*(prob->getSystemMatrix()), "ellipt_mat.m"); + prob->solve(adaptInfo, false); + } + + if (toDo.isSet(ESTIMATE)) { + prob->estimate(adaptInfo); + } + return flag; + }; + + template <typename Matrix> + void applySingularPertubation(Matrix& m) + { + using namespace mtl; + // Type of m's elements + typedef typename mtl::Collection<Matrix>::value_type value_type; + int nnz= m.nnz_local(m.num_rows()-1); + // Create inserter for matrix m + // Existing values are not overwritten but inserted + matrix::inserter<Matrix, update_times<value_type> > ins(m, nnz); + + ins[m.num_rows()-1][m.num_rows()-1] << 1.0+1.e-5; + } + + template <typename Matrix> + void applySingularDBC(Matrix& m) + { + using namespace mtl; + + typename traits::row<Matrix>::type r(m); + typename traits::col<Matrix>::type c(m); + typename traits::value<Matrix>::type v(m); + typedef typename traits::range_generator<tag::row, Matrix>::type c_type; + typedef typename traits::range_generator<tag::nz, c_type>::type ic_type; +// typedef typename Collection<Matrix>::value_type value_type; + + for (c_type cursor(begin<tag::row>(m)), cend(end<tag::row>(m)); cursor != cend; ++cursor) { + for (ic_type icursor(begin<tag::nz>(cursor)), icend(end<tag::nz>(cursor)); icursor != icend; ++icursor) { + v(*icursor, (r(*icursor)==c(*icursor)?1.0:0.0)); + } + break; + } + } + + template <typename Matrix, typename Vector> + void applyDbc(Matrix& m, Vector& vec, DegreeOfFreedom idx, double value) + { + using namespace mtl; + typename Matrix::size_type idx_= idx; + + typename traits::row<Matrix>::type r(m); + typename traits::col<Matrix>::type c(m); + typename traits::value<Matrix>::type v(m); + typedef typename traits::range_generator<tag::row, Matrix>::type c_type; + typedef typename traits::range_generator<tag::nz, c_type>::type ic_type; +// typedef typename Collection<Matrix>::value_type value_type; + + for (c_type cursor(begin<tag::row>(m)+idx_), cend(begin<tag::row>(m)+idx_+1); cursor != cend; ++cursor) { + for (ic_type icursor(begin<tag::nz>(cursor)), icend(end<tag::nz>(cursor)); icursor != icend; ++icursor) { + v(*icursor, (r(*icursor)==c(*icursor)?1.0:0.0)); + if(r(*icursor)==c(*icursor)) { + MSG("DBC set to (%d, %d)\n", r(*icursor), c(*icursor)); + } + } + break; + } + + vec[idx]= value; + } + + +DegreeOfFreedom getDOFidxAtCoords(DOFVector<double> *vec, WorldVector<double> &p, bool &inside, ElInfo *oldElInfo=NULL, bool useOldElInfo=false) +{ + const FiniteElemSpace *feSpace = vec->getFeSpace(); + Mesh *mesh = vec->getFeSpace()->getMesh(); + const BasisFunction *basFcts = feSpace->getBasisFcts(); + + int dim = mesh->getDim(); + int numBasFcts = basFcts->getNumber(); + + DegreeOfFreedom *localIndices = new DegreeOfFreedom[numBasFcts]; + DimVec<double> lambda(dim, NO_INIT); + + ElInfo *elInfo = mesh->createNewElInfo(); + int dofIdx=0; + inside=false; + + if(oldElInfo && useOldElInfo && oldElInfo->getMacroElement()) { + inside=mesh->findElInfoAtPoint(p,elInfo,lambda,oldElInfo->getMacroElement(),NULL,NULL); + delete oldElInfo; + } else { + inside=mesh->findElInfoAtPoint(p,elInfo,lambda,NULL,NULL,NULL); + } + if(oldElInfo) oldElInfo=elInfo; + if(inside) { + basFcts->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), localIndices); + FixVec<WorldVector<double>, VERTEX> coords = elInfo->getMacroElement()->getCoord(); + int minIdx=-1; + double minDist=1.e15; + for(int i=0;i<coords.size();++i) { + WorldVector<double> dist = coords[i]-p; + double newDist = AMDiS::norm(dist); + if(newDist<minDist) { + minIdx=i; + minDist=newDist; + } + } + if(minIdx>=0) { + dofIdx = localIndices[minIdx]; + } + } + delete [] localIndices; + if(!oldElInfo) delete elInfo; + return dofIdx; +}; +protected: +MyProblemVec *prob; +}; + +/// < factor*phase*grad(u) , grad(psi) > +class Phase_SOT : public SecondOrderTerm +{ +public: + /// Constructor. + Phase_SOT(DOFVectorBase<double>* phaseDV_, double fac_=1.0) : + SecondOrderTerm(6), phaseDV(phaseDV_), fac(fac_) + { + TEST_EXIT(phaseDV_)("no vector phase!\n"); + auxFeSpaces.insert(phaseDV_->getFeSpace()); + }; + + void initElement(const ElInfo* elInfo, SubAssembler* subAssembler, + Quadrature *quad = NULL) { + getVectorAtQPs(phaseDV, elInfo, subAssembler, quad, phase); + }; + + void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad = NULL) { + getVectorAtQPs(phaseDV, smallElInfo, largeElInfo, subAssembler, quad, phase); + }; + + inline void getLALt(const ElInfo *elInfo, std::vector<mtl::dense2D<double> > &LALt) const + { + const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda(); + const int nPoints = static_cast<int>(LALt.size()); + + for (int iq = 0; iq < nPoints; iq++) + l1lt(Lambda, LALt[iq], f(iq) * phase[iq] * fac); + }; + + inline void eval(int nPoints, + const AMDiS::ElementVector&, + const WorldVector<double> *grdUhAtQP, + const WorldMatrix<double> *D2UhAtQP, + ElementVector& result, + double opFactor) + { + if (D2UhAtQP) { + for (int iq = 0; iq < nPoints; iq++) { + double feval = f(iq) * phase[iq] * opFactor * fac; + double resultQP = 0.0; + for (int i = 0; i < dimOfWorld; i++) + resultQP += D2UhAtQP[iq][i][i]; + result[iq] += feval * resultQP; + } + } + }; + + void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, + std::vector<WorldVector<double> > &result) + { + int nPoints = grdUhAtQP.size(); + for (int iq = 0; iq < nPoints; iq++) { + double factor = f(iq) * phase[iq] * fac; + axpy(factor, grdUhAtQP[iq], result[iq]); + } + }; + + virtual double f(const int iq) const + { + return 1.0; + }; + void setFactor(const double fac_) { fac=fac_; } + +protected: + DOFVectorBase<double> *phaseDV; + mtl::dense_vector<double> phase; + double fac; +}; + +/// simple circle: phi_0(x,y) := sqrt(x^2+y^2)-r +class Circle : public AbstractFunction<double, WorldVector<double> > +{ +public: + Circle(double radius_, WorldVector<double> midPoint_) : + radius(radius_), midPoint(midPoint_) {} + Circle(double radius_) : + radius(radius_) { midPoint.set(0.0); } + double operator()(const WorldVector<double>& x) const + { + double result = 0.0; + + for(int k=0; k<x.getSize(); k++) { + result += sqr(x[k]-midPoint[k]); + } + result = sqrt(result)-radius; + return result; + }; +private: + double radius; + WorldVector<double> midPoint; +}; + /// Dirichlet boundary function class G : public AbstractFunction<double, WorldVector<double> > { @@ -15,7 +295,7 @@ public: /// Implementation of AbstractFunction::operator(). double operator()(const WorldVector<double>& x) const { - return exp(-10.0 * (x * x)); + return 0.0; } }; @@ -29,10 +309,7 @@ public: /// Implementation of AbstractFunction::operator(). double operator()(const WorldVector<double>& x) const { - int dow = Global::getGeo(WORLD); - double r2 = (x * x); - double ux = exp(-10.0 * r2); - return -(400.0 * r2 - 20.0 * dow) * ux; + return sin(M_PI*x[0]); } }; @@ -53,22 +330,25 @@ int main(int argc, char* argv[]) // ===== create and init the scalar problem ===== - ProblemStat ellipt("ellipt"); + MyProblemVec ellipt("ellipt"); ellipt.initialize(INIT_ALL); - + MyIteration elIter(&ellipt); // === create adapt info === - AdaptInfo adaptInfo("ellipt->adapt"); + AdaptInfo adaptInfo("ellipt->adapt", 2); // === create adapt === - AdaptStationary adapt("ellipt->adapt", ellipt, adaptInfo); + AdaptStationary adapt("ellipt->adapt", elIter, adaptInfo); +// DOFVector<double> phase(ellipt.getFeSpace(), "phase"); +// phase.interpol(new Circle(0.25)); // ===== create matrix operator ===== Operator matrixOperator(ellipt.getFeSpace()); matrixOperator.addSecondOrderTerm(new Simple_SOT); ellipt.addMatrixOperator(matrixOperator, 0, 0); + ellipt.addMatrixOperator(matrixOperator, 1, 1); // ===== create rhs operator ===== @@ -76,10 +356,12 @@ int main(int argc, char* argv[]) Operator rhsOperator(ellipt.getFeSpace()); rhsOperator.addZeroOrderTerm(new CoordsAtQP_ZOT(new F(degree))); ellipt.addVectorOperator(rhsOperator, 0); + ellipt.addVectorOperator(rhsOperator, 1); // ===== add boundary conditions ===== - ellipt.addDirichletBC(1, 0, 0, new G); + ellipt.addDirichletBC(3, 0, 0, new G); + ellipt.addDirichletBC(5, 1, 1, new G); // ===== start adaption loop ===== -- GitLab