1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_DGF_PROJECTIONBLOCK_HH
4 #define DUNE_DGF_PROJECTIONBLOCK_HH
5 
6 #include <map>
7 
8 #include <dune/grid/common/boundaryprojection.hh>
9 #include <dune/grid/io/file/dgfparser/blocks/basic.hh>
10 
11 namespace Dune
12 {
13 
14   namespace dgf
15   {
16 
17     // ProjectionBlock
18     // ---------------
19 
20     class ProjectionBlock
21       : public BasicBlock
22     {
23       struct Token
24       {
25         friend std::ostream &operator<< ( std::ostream &, const Token & );
26 
27         enum Type
28         {
29           string, number,
30           defaultKeyword, functionKeyword, segmentKeyword,
31           sqrtKeyword, sinKeyword, cosKeyword, piKeyword,
32           comma,
33           equals,
34           openingParen, closingParen, openingBracket, closingBracket, normDelim,
35           additiveOperator, multiplicativeOperator, powerOperator,
36           endOfLine
37         };
38 
39         Type type;
40         char symbol;
41         std::string literal;
42         double value;
43 
setSymbolDune::dgf::ProjectionBlock::Token44         void setSymbol ( const Type &t, char c )
45         {
46           type = t;
47           symbol = c;
48         }
49       };
50 
51       friend std::ostream &operator<< ( std::ostream &, const Token & );
52 
53     public:
54       struct Expression;
55 
56       typedef std::shared_ptr< Expression > ExpressionPointer;
57       typedef std::pair< ExpressionPointer, std::string > ExpressionPair ;
58 
59     private:
60       template< int dimworld >
61       class BoundaryProjection;
62 
63       void registerProjectionFactory( const int dimworld );
64 
blockId()65       static const char* blockId() { return "Projection"; }
66     public:
67       ProjectionBlock ( std::istream &in, int dimworld );
68 
69       template< int dimworld >
defaultProjection() const70       const DuneBoundaryProjection< dimworld > *defaultProjection () const
71       {
72         if( defaultFunction_.first )
73         {
74           return new BoundaryProjection< dimworld >( defaultFunction_ );
75         }
76         else
77           return 0;
78       }
79 
numBoundaryProjections() const80       size_t numBoundaryProjections () const
81       {
82         return boundaryFunctions_.size();
83       }
84 
boundaryFace(const size_t i) const85       const std::vector< unsigned int > &boundaryFace ( const size_t i ) const
86       {
87         assert( i < numBoundaryProjections() );
88         return boundaryFunctions_[ i ].first;
89       }
90 
91       template< int dimworld >
boundaryProjection(const size_t i) const92       const DuneBoundaryProjection< dimworld > *boundaryProjection ( const size_t i ) const
93       {
94         assert( i < numBoundaryProjections() );
95         return new BoundaryProjection< dimworld >( boundaryFunctions_[ i ].second );
96       }
97 
function(const std::string & name) const98       ExpressionPointer function ( const std::string &name ) const
99       {
100         const FunctionMap::const_iterator it = functions_.find( name );
101         return (it != functions_.end() ? it->second.first : 0);
102       }
103 
lastFunctionInserted() const104       ExpressionPair lastFunctionInserted () const
105       {
106         assert( ! functions_.empty() );
107         return functions_.begin()->second;
108       }
109 
createExpression(const std::string & funcexpr,const int dimworld)110       static ProjectionBlock::ExpressionPair createExpression( const std::string& funcexpr, const int dimworld )
111       {
112         std::stringstream str;
113         str << blockId() << std::endl;
114         str << funcexpr << std::endl;
115         str << "#" << std::endl;
116         ProjectionBlock problock( str, dimworld );
117         return problock.lastFunctionInserted();
118       }
119 
120 
121 
122     private:
123       void parseFunction ( const std::string& exprname );
124       ExpressionPointer parseBasicExpression ( const std::string &variableName );
125       ExpressionPointer parsePostfixExpression ( const std::string &variableName );
126       ExpressionPointer parseUnaryExpression ( const std::string &variableName );
127       ExpressionPointer parsePowerExpression ( const std::string &variableName );
128       ExpressionPointer parseMultiplicativeExpression ( const std::string &variableName );
129       ExpressionPointer parseExpression ( const std::string &variableName );
130       void parseDefault ();
131       void parseSegment ();
132 
133       void matchToken ( const Token::Type &type, const std::string &message );
134       void nextToken ();
135 
lowerCase(char c)136       static char lowerCase ( char c )
137       {
138         return ((c >= 'A') && (c <= 'Z') ? c + ('a' - 'A') : c);
139       }
140 
141     protected:
142       typedef std::map< std::string, ExpressionPair >     FunctionMap;
143       typedef std::pair< std::vector< unsigned int >, ExpressionPair > BoundaryFunction;
144 
145       using BasicBlock::line;
146 
147       Token token;
148       FunctionMap functions_;
149       ExpressionPair defaultFunction_;
150       std::vector< BoundaryFunction > boundaryFunctions_;
151     };
152 
153 
154     std::ostream &operator<< ( std::ostream &out, const ProjectionBlock::Token &token );
155 
156 
157     struct ProjectionBlock::Expression
158     {
159       typedef std::vector< double > Vector;
160 
~ExpressionDune::dgf::ProjectionBlock::Expression161       virtual ~Expression ()
162       {}
163 
164       virtual void evaluate ( const Vector &argument, Vector &result ) const = 0;
165     };
166 
167 
168     template< int dimworld >
169     class ProjectionBlock::BoundaryProjection
170       : public DuneBoundaryProjection< dimworld >
171     {
172       typedef DuneBoundaryProjection< dimworld > Base;
173       typedef BoundaryProjection < dimworld >    This;
174       typedef typename Base :: ObjectStreamType  ObjectStreamType;
175 
176     public:
177       typedef typename Base::CoordinateType CoordinateType;
178 
BoundaryProjection(const ExpressionPair & exprpair)179       BoundaryProjection ( const ExpressionPair& exprpair )
180         : expression_( exprpair.first ),
181           expressionName_( exprpair.second )
182       {}
183 
BoundaryProjection(ObjectStreamType & buffer)184       BoundaryProjection( ObjectStreamType& buffer )
185       {
186         int size = 0;
187         buffer.read( (char *) &size, sizeof(int) );
188         expressionName_.resize( size );
189         buffer.read( (char *) expressionName_.c_str(), size );
190         expression_ = ProjectionBlock::createExpression( expressionName_, dimworld ).first;
191       }
192 
operator ()(const CoordinateType & global) const193       virtual CoordinateType operator() ( const CoordinateType &global ) const override
194       {
195         std::vector< double > x( dimworld );
196         for( int i = 0; i < dimworld; ++i )
197           x[ i ] = global[ i ];
198         std::vector< double > y;
199         expression_->evaluate( x, y );
200         CoordinateType result;
201         for( int i = 0; i < dimworld; ++i )
202           result[ i ] = y[ i ];
203         return result;
204       }
205 
206       // backup name of expression that should allow to recreate this class
backup(std::stringstream & buffer) const207       virtual void backup( std::stringstream& buffer ) const override
208       {
209         buffer.write( (const char *) &key(), sizeof( int ));
210         int size = expressionName_.size();
211         buffer.write( (const char *) &size, sizeof(int) );
212         buffer.write( expressionName_.c_str(), size );
213       }
214 
registerFactory()215       static void registerFactory()
216       {
217         if( key() < 0 )
218         {
219           key() = Base::template registerFactory< This >();
220         }
221       }
222 
223     protected:
key()224       static int& key ()
225       {
226         static int k = -1;
227         return k;
228       }
229 
230       ExpressionPointer expression_;
231       std::string expressionName_;
232     };
233 
registerProjectionFactory(const int dimworld)234     inline void ProjectionBlock::registerProjectionFactory( const int dimworld )
235     {
236       if( dimworld == 3 ) {
237         BoundaryProjection< 3 > :: registerFactory();
238       }
239       else if ( dimworld == 2 ) {
240         BoundaryProjection< 2 > :: registerFactory();
241       }
242       else if ( dimworld == 1 ) {
243         BoundaryProjection< 1 > :: registerFactory();
244       }
245       else {
246         DUNE_THROW(NotImplemented,"ProjectionBlock::registerProjectionFactory not implemented for dimworld = " << dimworld);
247       }
248     }
249 
250   }
251 
252 }
253 
254 #endif // #ifndef DUNE_DGF_PROJECTIONBLOCK_HH
255