00001 #ifndef VIENNAFEM_LOG_LATEX_HPP
00002 #define VIENNAFEM_LOG_LATEX_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <vector>
00019 #include <fstream>
00020 #include "viennafem/forwards.h"
00021 #include "viennafem/log/interface.hpp"
00022 #include "viennafem/cell_quan.hpp"
00023
00024 #include "viennamath/manipulation/latex.hpp"
00025
00030 namespace viennafem
00031 {
00032 template <typename InterfaceType>
00033 class latex_logger;
00034
00035 namespace detail
00036 {
00037
00038 template <typename EquationArray, typename InterfaceType>
00039 void write_strong_form(EquationArray const & pde_system,
00040 latex_logger<InterfaceType> & log);
00041
00042 template <typename EquationArray, typename InterfaceType>
00043 void write_weak_form(EquationArray const & weak_form,
00044 latex_logger<InterfaceType> & log);
00045
00046 template <typename EquationArray, typename InterfaceType>
00047 void write_coordinated_weak_form(EquationArray const & weak_form,
00048 latex_logger<InterfaceType> & log);
00049
00050 template <typename EquationArray, typename InterfaceType>
00051 void write_transformed_weak_form(EquationArray const & weak_form,
00052 latex_logger<InterfaceType> & log);
00053
00054 template <typename EquationArray, typename InterfaceType>
00055 void write_test_and_trial_space(EquationArray const & test_space,
00056 EquationArray const & trial_space,
00057 latex_logger<InterfaceType> & log);
00058
00059 template <typename InterfaceType>
00060 void write_linear_solver_stats(latex_logger<InterfaceType> & log);
00061
00062 }
00063
00064
00065
00066
00067
00073 template <typename CellType, typename InterfaceType>
00074 class rt_latex_dt_dx_processor : public viennamath::rt_latex_processor_interface<InterfaceType>
00075 {
00076 typedef typename InterfaceType::numeric_type NumericType;
00077 typedef viennafem::cell_quan<CellType, InterfaceType> CellQuanType;
00078
00079 public:
00080
00081 std::string process(InterfaceType const * ptr, bool use_parenthesis, viennamath::rt_latex_translator<InterfaceType> const & translator) const
00082 {
00083 if (dynamic_cast< const CellQuanType * >(ptr) != NULL)
00084 {
00085 const CellQuanType * temp = dynamic_cast< const CellQuanType * >(ptr);
00086 return process_impl(*temp, use_parenthesis, translator);
00087 }
00088
00089 return "";
00090 }
00091
00092 bool customize(InterfaceType const * e, std::string const & str)
00093 {
00094 return false;
00095 }
00096
00097 private:
00098
00099 std::string process_impl(CellQuanType const & e, bool use_parenthesis, viennamath::rt_latex_translator<InterfaceType> const & translator) const
00100 {
00101 typedef viennamath::expr ExpressionType;
00102
00103 std::stringstream ss;
00104
00105 viennamath::variable x(0);
00106 viennamath::variable y(1);
00107 viennamath::variable z(2);
00108
00109 std::auto_ptr< detail::cell_quan_interface<CellType> > temp(e.wrapper().clone());
00110
00111 if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<0,0>, ExpressionType> * >(temp.get()) != NULL
00112 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<0,0>, NumericType> * >(temp.get()) != NULL)
00113 {
00114 ss << " \\frac{\\partial \\xi}{\\partial x} ";
00115 }
00116 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<1,0>, ExpressionType> * >(temp.get()) != NULL
00117 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<1,0>, NumericType> * >(temp.get()) != NULL)
00118 {
00119 ss << " \\frac{\\partial \\eta}{\\partial x} ";
00120 }
00121 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<2,0>, ExpressionType> * >(temp.get()) != NULL
00122 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<2,0>, NumericType> * >(temp.get()) != NULL)
00123 {
00124 ss << " \\frac{\\partial \\nu}{\\partial x} ";
00125 }
00126
00127 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<0,1>, ExpressionType> * >(temp.get()) != NULL
00128 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<0,1>, NumericType> * >(temp.get()) != NULL)
00129 {
00130 ss << " \\frac{\\partial \\xi}{\\partial y} ";
00131 }
00132 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<1,1>, ExpressionType> * >(temp.get()) != NULL
00133 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<1,1>, NumericType> * >(temp.get()) != NULL)
00134 {
00135 ss << " \\frac{\\partial \\eta}{\\partial y} ";
00136 }
00137 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<2,1>, ExpressionType> * >(temp.get()) != NULL
00138 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<2,1>, NumericType> * >(temp.get()) != NULL)
00139 {
00140 ss << " \\frac{\\partial \\nu}{\\partial y} ";
00141 }
00142
00143 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<0,2>, ExpressionType> * >(temp.get()) != NULL
00144 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<0,2>, NumericType> * >(temp.get()) != NULL)
00145 {
00146 ss << " \\frac{\\partial \\xi}{\\partial z} ";
00147 }
00148 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<1,2>, ExpressionType> * >(temp.get()) != NULL
00149 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<1,2>, NumericType> * >(temp.get()) != NULL)
00150 {
00151 ss << " \\frac{\\partial \\eta}{\\partial z} ";
00152 }
00153 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::dt_dx_key<2,2>, ExpressionType> * >(temp.get()) != NULL
00154 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::dt_dx_key<2,2>, NumericType> * >(temp.get()) != NULL)
00155 {
00156 ss << " \\frac{\\partial \\nu}{\\partial z} ";
00157 }
00158
00159 else if (dynamic_cast< detail::cell_quan_expr<CellType, viennafem::det_dF_dt_key, ExpressionType> * >(temp.get()) != NULL
00160 || dynamic_cast< detail::cell_quan_constant<CellType, viennafem::det_dF_dt_key, NumericType> * >(temp.get()) != NULL)
00161 {
00162 ss << " \\mathrm{det} F ";
00163 }
00164 else
00165 std::cerr << "Warning: could not find string for cell_quan!" << std::endl;
00166
00167 return ss.str();
00168 }
00169
00170 };
00171
00172
00173
00178 template <typename InterfaceType>
00179 class latex_logger : public logger_interface<InterfaceType>
00180 {
00181 typedef logger_interface<InterfaceType> BaseType;
00182 typedef typename BaseType::EquationType EquationType;
00183
00184 public:
00185 latex_logger(std::string const & filename) : stream_(filename.c_str()), filename_(filename), something_written(false)
00186 {
00187 viennamath::function_symbol u0(0, viennamath::unknown_tag<>());
00188 viennamath::function_symbol u1(1, viennamath::unknown_tag<>());
00189 viennamath::function_symbol u2(2, viennamath::unknown_tag<>());
00190
00191 viennamath::function_symbol v0(0, viennamath::test_tag<>());
00192 viennamath::function_symbol v1(1, viennamath::test_tag<>());
00193 viennamath::function_symbol v2(2, viennamath::test_tag<>());
00194
00195 translator_.customize(u0, "u_0");
00196 translator_.customize(u1, "u_1");
00197 translator_.customize(u2, "u_2");
00198
00199 translator_.customize(v0, "v_0");
00200 translator_.customize(v1, "v_1");
00201 translator_.customize(v2, "v_2");
00202 }
00203
00204 latex_logger(const latex_logger & other) : stream_(other.filename_.c_str()),
00205 filename_(other.filename_),
00206 something_written(false),
00207 translator_(other.translator_) {}
00208
00209 ~latex_logger()
00210 {
00211
00212 if (something_written)
00213 stream_ << "\\end{document}" << std::endl;
00214
00215 stream_.close();
00216 }
00217
00218 void write_strong_form(std::vector<EquationType> const & pdes) { viennafem::detail::write_strong_form(pdes, *this); }
00219 void write_weak_form(std::vector<EquationType> const & pdes) { viennafem::detail::write_weak_form(pdes, *this); }
00220 void write_coordinated_weak_form(std::vector<EquationType> const & pdes) { viennafem::detail::write_coordinated_weak_form(pdes, *this); }
00221 void write_transformed_weak_form(std::vector<EquationType> const & pdes) { viennafem::detail::write_transformed_weak_form(pdes, *this); }
00222 void write_test_and_trial_space(std::vector<viennamath::expr> const & test_space,
00223 std::vector<viennamath::expr> const & trial_space)
00224 {
00225 viennafem::detail::write_test_and_trial_space(test_space, trial_space, *this);
00226 }
00227
00228
00229 void write_header()
00230 {
00231 stream_ << "\\documentclass[11pt]{article}\n";
00232 stream_ << "\\usepackage{amsmath}\n";
00233 stream_ << "\\usepackage[cm]{fullpage}\n";
00234 stream_ << "\\title{ViennaFEM Protocol}\n";
00235 stream_ << "\n";
00236 stream_ << "\\begin{document}\n";
00237 stream_ << "\\begin{center}\n";
00238 stream_ << "\\LARGE ViennaFEM Protocol\n";
00239 stream_ << "\\end{center}\n";
00240 stream_ << "\n";
00241
00242 }
00243
00244 template <typename T>
00245 void stream(T const & t)
00246 {
00247 if (!something_written)
00248 {
00249 write_header();
00250 something_written = true;
00251 }
00252 stream_ << t;
00253 }
00254 void flush() { }
00255
00256 viennamath::latex_translator & translator() { return translator_; }
00257
00258 private:
00259 latex_logger & operator=(latex_logger const & other);
00260
00261 std::ofstream stream_;
00262 const std::string filename_;
00263 bool something_written;
00264 viennamath::latex_translator translator_;
00265 };
00266
00268 template <typename InterfaceType, typename T>
00269 latex_logger<InterfaceType> & operator<<(latex_logger<InterfaceType> & logger, T const & t)
00270 {
00271 logger.stream(t);
00272 return logger;
00273 }
00274
00275
00276
00277 namespace detail
00278 {
00279
00281 template <typename EquationArray, typename InterfaceType>
00282 void write_strong_form(EquationArray const & pdes,
00283 latex_logger<InterfaceType> & log)
00284 {
00285 log << "\\section{Strong Formulation}\n";
00286 log << "The strong formulation of the problem is to solve\n";
00287 log << "\\begin{align}\n";
00288 log << log.translator()(pdes[0]) << " \n";
00289 log << "\\end{align}\n";
00290 log << "in $\\Omega$ with suitable boundary conditions.\n";
00291 }
00292
00294 template <typename EquationArray, typename InterfaceType>
00295 void write_weak_form(EquationArray const & weak_form,
00296 latex_logger<InterfaceType> & log)
00297 {
00298 log << "\\section{Weak Formulation}\n";
00299 log << "After multiplication with a test function $v$, integration over $\\Omega$ and partial integration, the weak formulation of the problem is obtained as\n";
00300 log << "\\begin{align}\n";
00301 for (typename EquationArray::const_iterator it = weak_form.begin();
00302 it != weak_form.end();
00303 ++it)
00304 log << log.translator()(*it) << " \n";
00305 log << "\\end{align}\n";
00306 log << "for all test functions $v$.\n";
00307 }
00308
00310 template <typename EquationArray, typename InterfaceType>
00311 void write_coordinated_weak_form(EquationArray const & weak_form,
00312 latex_logger<InterfaceType> & log)
00313 {
00314 log << "Written in coordinates for the underlying simulation domain, the weak form is \n";
00315 log << "\\begin{align}\n";
00316 for (typename EquationArray::const_iterator it = weak_form.begin();
00317 it != weak_form.end();
00318 ++it)
00319 log << log.translator()(*it) << " \n";
00320 log << "\\end{align}\n";
00321 log << "for all testfunctions $v$.\n";
00322 }
00323
00325 template <typename EquationArray, typename InterfaceType>
00326 void write_transformed_weak_form(EquationArray const & weak_form,
00327 latex_logger<InterfaceType> & log)
00328 {
00329
00330 log << "\\section{Discrete Approximation by Finite Elements}\n";
00331 log << "The discrete approximation to the continuous problem is obtained by a Galerkin approach:\n";
00332 log << "\\begin{align}\n";
00333 log << " u_h = \\sum_j \\alpha_j \\varphi_j \n";
00334 log << "\\end{align}\n";
00335 log << "with trial functions $\\varphi_j$.\n";
00336
00337 log << "In a Galerkin approach, test functions $v$ are also chosen from a finite-dimensional space:\n";
00338 log << "\\begin{align}\n";
00339 log << " v_h = \\sum_i \\beta_i \\psi_i \n";
00340 log << "\\end{align}\n";
00341 log << "Due to integral transformations, it is sufficient to define the trial and test functions on the reference cell.\n";
00342 log << "After transformation to the reference cell, the weak form on a cell reads\n";
00343
00344
00345 viennamath::variable xi(0);
00346 viennamath::variable eta(1);
00347 viennamath::variable nu(2);
00348
00349 log.translator().customize(xi, "\\xi");
00350 log.translator().customize(eta, "\\eta");
00351 log.translator().customize(nu, "\\nu");
00352
00353 viennamath::function_symbol u0(0, viennamath::unknown_tag<>());
00354 viennamath::function_symbol u1(1, viennamath::unknown_tag<>());
00355 viennamath::function_symbol u2(2, viennamath::unknown_tag<>());
00356
00357 viennamath::function_symbol v0(0, viennamath::test_tag<>());
00358 viennamath::function_symbol v1(1, viennamath::test_tag<>());
00359 viennamath::function_symbol v2(2, viennamath::test_tag<>());
00360
00361 log.translator().customize(u0, "\\tilde{u}_0");
00362 log.translator().customize(u1, "\\tilde{u}_1");
00363 log.translator().customize(u2, "\\tilde{u}_2");
00364
00365 log.translator().customize(v0, "\\tilde{v}_0");
00366 log.translator().customize(v1, "\\tilde{v}_1");
00367 log.translator().customize(v2, "\\tilde{v}_2");
00368
00369 log << "\\begin{align}\n";
00370 for (typename EquationArray::const_iterator it = weak_form.begin();
00371 it != weak_form.end();
00372 ++it)
00373 log << log.translator()(*it) << " \\ . \n";
00374 log << "\\end{align}\n";
00375
00376
00377
00378
00379 }
00380
00382 template <typename EquationArray, typename InterfaceType>
00383 void write_test_and_trial_space(EquationArray const & test_space,
00384 EquationArray const & trial_space,
00385 latex_logger<InterfaceType> & log)
00386 {
00387 log << "The trial functions used for the discrete approximation of $u_h$ on the reference element are \n";
00388 log << "\\begin{align*}\n";
00389 std::size_t func_index = 0;
00390 for (typename EquationArray::const_iterator it = trial_space.begin();
00391 it != trial_space.end();
00392 ++it)
00393 {
00394 if (func_index > 0)
00395 log << " \\ , \\\\ \n";
00396
00397 log << "\\varphi_{" << func_index << "} &= " << log.translator()(*it);
00398 ++func_index;
00399 }
00400 log << " \\ . \n \\end{align*}\n";
00401 log << "The test functions on the reference element are\n";
00402 log << "\\begin{align*}\n";
00403 func_index = 0;
00404 for (typename EquationArray::const_iterator it = test_space.begin();
00405 it != test_space.end();
00406 ++it)
00407 {
00408 if (func_index > 0)
00409 log << " \\ , \\\\ \n";
00410
00411 log << "\\psi_{" << func_index << "} &= " << log.translator()(*it);
00412 ++func_index;
00413 }
00414 log << " \\ . \n \\end{align*}\n";
00415 log << "\n";
00416 }
00417
00419 template <typename InterfaceType>
00420 void write_linear_solver_stats(latex_logger<InterfaceType> & log)
00421 {
00422 log << "write linear solver stats\n";
00423 }
00424
00425 }
00426
00427 }
00428
00429 #endif