• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List

/export/development/ViennaFEM/viennafem/weak_form.hpp

Go to the documentation of this file.
00001 #ifndef VIENNAMATH_WEAK_FORM_HPP
00002 #define VIENNAMATH_WEAK_FORM_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2012, Institute for Microelectronics,
00006                        Institute for Analysis and Scientific Computing,
00007                        TU Wien.
00008                              -----------------
00009                ViennaFEM - The Vienna Finite Element Method Library
00010                              -----------------
00011 
00012    Author:     Karl Rupp                          rupp@iue.tuwien.ac.at
00013 
00014    License:    MIT (X11), see file LICENSE in the ViennaFEM base directory
00015 ============================================================================ */
00016 
00017 
00018 
00019 #include "viennamath/expression.hpp"
00020 #include "viennamath/manipulation/substitute.hpp"
00021 
00026 namespace viennafem
00027 {
00028   //
00029   // Compile time transformation
00030   //
00031   
00032   //TODO: Not finished in time for the 1.0.0 release. Scheduled for ViennaFEM 1.1.0.
00033 
00034 
00035 
00036   //
00037   // Run time transformation
00038   //
00039 
00040   namespace detail
00041   {
00042     
00047     template <typename InterfaceType>
00048     struct weak_form_checker : public viennamath::rt_traversal_interface<>
00049     {
00050       public:
00051         weak_form_checker() : is_weak_(false) {}
00052         
00053         void operator()(InterfaceType const * e) const 
00054         {
00055           if (viennamath::callback_if_castable< viennamath::rt_unary_expr<InterfaceType> >::apply(e, *this))
00056             return;
00057         }
00058         
00059         void operator()(viennamath::rt_unary_expr<InterfaceType> const & unary_expr) const
00060         {
00061           typedef viennamath::op_unary<viennamath::op_rt_symbolic_integral<InterfaceType>, InterfaceType>  SymbolicIntegrationType;
00062           
00063           if (dynamic_cast<const SymbolicIntegrationType *>(unary_expr.op()) != NULL)
00064             is_weak_ = true;        
00065         }
00066         
00067         bool is_weak() const { return is_weak_; }
00068         
00069       private:
00070         mutable bool is_weak_; //TODO: Should not be necessary here...
00071     };
00072     
00073   } //namespace detail
00074   
00076   template <typename InterfaceType>
00077   bool is_weak_form(viennamath::rt_equation<InterfaceType> const & strong_formulation)
00078   {
00079     detail::weak_form_checker<InterfaceType> * checker = new detail::weak_form_checker<InterfaceType>();
00080     
00081     viennamath::rt_traversal_wrapper<> wrapped_checker( checker ); //Note: checker pointer is auto-ptr'ed here, therefore no need for an explicit 'delete checker;' at the end of the function.
00082 
00083     strong_formulation.lhs().get()->recursive_traversal( wrapped_checker );
00084     return checker->is_weak();
00085   }
00086 
00087 
00088 
00089 
00090 
00091 
00092   namespace detail
00093   {
00095     template <typename InterfaceType>
00096     struct weak_form_creator : public viennamath::rt_manipulation_interface<InterfaceType>
00097     {
00098       public:
00099         InterfaceType * operator()(InterfaceType const * e) const 
00100         {
00101           if (   !viennamath::callback_if_castable< viennamath::rt_unary_expr<InterfaceType> >::apply(e, *this)
00102               && !viennamath::callback_if_castable< viennamath::rt_binary_expr<InterfaceType> >::apply(e, *this))
00103           {
00104             //this if-body is only executed for trivial expressions such as 'u' (L^2-projection)
00105             
00106             //multiply with test function and integrate
00107             viennamath::rt_function_symbol<InterfaceType> test_func(0, viennamath::test_tag<0>());
00108             viennamath::rt_expr<InterfaceType> temp(e->clone());
00109             integrated_expr = viennamath::integral(viennamath::symbolic_interval(), temp * test_func);
00110           }
00111           
00112           return integrated_expr.get()->clone();
00113           
00114         }
00115         
00116         void operator()(viennamath::rt_unary_expr<InterfaceType> const & unary_expr) const
00117         {
00118           typedef typename InterfaceType::numeric_type   NumericType;
00119           typedef viennamath::op_unary<viennamath::op_divergence<NumericType>, InterfaceType>  DivergenceOperatorType;
00120           
00121           if (dynamic_cast<const DivergenceOperatorType *>(unary_expr.op()) != NULL) //this is something of the form div(expr) with some expression expr
00122           {
00123             //std::cout << "Detected divergence operator!" << std::endl;
00124             viennamath::rt_expr<InterfaceType> minus1 = -1;
00125             viennamath::rt_expr<InterfaceType> lhs(unary_expr.lhs()->clone());
00126             viennamath::rt_expr<InterfaceType> rhs = viennamath::grad(viennamath::rt_function_symbol<InterfaceType>(0, viennamath::test_tag<0>()));
00127             integrated_expr = viennamath::integral(viennamath::symbolic_interval(),
00128                                                   minus1 * (lhs * rhs)            
00129                                                   );
00130           }
00131           else
00132             throw "Cannot derive weak form!";
00133         }
00134 
00135         void operator()(viennamath::rt_binary_expr<InterfaceType> const & bin) const
00136         {
00137           typedef typename InterfaceType::numeric_type   NumericType;
00138           typedef viennamath::op_binary<viennamath::op_plus<NumericType>, InterfaceType>   PlusOperatorType;
00139           typedef viennamath::op_binary<viennamath::op_minus<NumericType>, InterfaceType>  MinusOperatorType;
00140           typedef viennamath::op_binary<viennamath::op_mult<NumericType>, InterfaceType>   ProductOperatorType;
00141           typedef viennamath::op_binary<viennamath::op_div<NumericType>, InterfaceType>  DivisionOperatorType;
00142           
00143           if (    dynamic_cast<const PlusOperatorType *>(bin.op()) != NULL
00144               || dynamic_cast<const MinusOperatorType *>(bin.op()) != NULL) //integration is additive :-)
00145           {
00146             viennamath::rt_manipulation_wrapper<InterfaceType> manipulator(new weak_form_creator<InterfaceType>());
00147             //Note: In the following, directly passing *this is not possible due to the need for a wrapper...
00148             integrated_expr = new viennamath::rt_binary_expr<InterfaceType>(bin.lhs()->recursive_manipulation(manipulator),
00149                                                                         bin.op()->clone(),
00150                                                                         bin.rhs()->recursive_manipulation(manipulator));
00151           }
00152           else if (dynamic_cast<const ProductOperatorType *>(bin.op()) != NULL
00153                     || dynamic_cast<const DivisionOperatorType *>(bin.op()) != NULL)
00154           {
00155             //handle the cases const * div(...) and div(...) * const
00156             
00157             if (bin.lhs()->is_constant())
00158             {
00159               viennamath::rt_manipulation_wrapper<InterfaceType> manipulator(new weak_form_creator<InterfaceType>());
00160               //Note: In the following, directly passing *this is not possible due to the need for a wrapper...
00161               integrated_expr = new viennamath::rt_binary_expr<InterfaceType>(bin.lhs()->clone(),
00162                                                                           bin.op()->clone(),
00163                                                                           bin.rhs()->recursive_manipulation(manipulator));
00164             }
00165             else if (bin.rhs()->is_constant())
00166             {
00167               viennamath::rt_manipulation_wrapper<InterfaceType> manipulator(new weak_form_creator<InterfaceType>());
00168               //Note: In the following, directly passing *this is not possible due to the need for a wrapper...
00169               integrated_expr = new viennamath::rt_binary_expr<InterfaceType>(bin.lhs()->recursive_manipulation(manipulator),
00170                                                                           bin.op()->clone(),
00171                                                                           bin.rhs()->clone());
00172             }
00173             else
00174             {
00175               throw "cannot derive weak form!";
00176             }
00177           }
00178           else //TODO: Add checks!
00179           {
00180             //multiply with test function and integrate
00181             viennamath::rt_function_symbol<InterfaceType> test_func(0, viennamath::test_tag<0>());
00182             integrated_expr = viennamath::integral(viennamath::symbolic_interval(),
00183                                                   bin * test_func);
00184           }
00185         }
00186 
00187         bool modifies(InterfaceType const * e) const { return true; }
00188         
00189       private:
00190         mutable viennamath::rt_expr<InterfaceType> integrated_expr;
00191     };
00192 
00193   } //namespace detail
00194 
00195   //tries to automatically derive the weak formulation from the strong formulation
00197   template <typename InterfaceType>
00198   viennamath::rt_equation<InterfaceType> make_weak_form(viennamath::rt_equation<InterfaceType> const & strong_formulation)
00199   {
00200     if (is_weak_form(strong_formulation))
00201     {
00202       std::cout << "ViennaFEM: make_weak_form(): Nothing to do, problem already in weak form!" << std::endl;
00203       return strong_formulation;
00204     }
00205     
00206     viennamath::rt_manipulation_wrapper<InterfaceType> wrapped_checker( new detail::weak_form_creator<InterfaceType>() );
00207     viennamath::rt_expr<InterfaceType> weak_lhs(strong_formulation.lhs().get()->recursive_manipulation( wrapped_checker ));
00208     viennamath::rt_expr<InterfaceType> weak_rhs = 
00209         viennamath::integral(viennamath::symbolic_interval(),
00210                              strong_formulation.rhs() * viennamath::rt_function_symbol<InterfaceType>(0, viennamath::test_tag<0>())
00211                             );
00212     
00213     return viennamath::rt_equation<InterfaceType>(weak_lhs, weak_rhs);
00214     
00215   }
00216 
00217 }
00218 
00219 #endif

Generated on Wed Feb 29 2012 21:51:05 for ViennaFEM - The Vienna Finite Element Method Library by  doxygen 1.7.1