Mercurial > fem-fenics-eugenio
comparison doc/doc.tex @ 199:b8bde50ffb44
Update description of classes.
author | gedeone-octave <marcovass89@hotmail.it> |
---|---|
date | Fri, 20 Dec 2013 11:08:10 +0100 |
parents | 8fb754d059be |
children | 3f3db13d7bc2 |
comparison
equal
deleted
inserted
replaced
198:8fb754d059be | 199:b8bde50ffb44 |
---|---|
1 \documentclass[a4paper,10pt]{book} | 1 \documentclass[a4paper,11pt]{book} |
2 \usepackage[utf8x]{inputenc} | 2 \usepackage[utf8x]{inputenc} |
3 \usepackage{graphicx} | 3 \usepackage{graphicx} |
4 \usepackage{amsmath} | 4 \usepackage{amsmath} |
5 \usepackage{amssymb} | 5 \usepackage{amssymb} |
6 \usepackage{caption} | 6 \usepackage{caption} |
81 {\large \today} | 81 {\large \today} |
82 | 82 |
83 \end{center} | 83 \end{center} |
84 \end{titlepage} | 84 \end{titlepage} |
85 | 85 |
86 \frontmatter | |
87 | |
86 \tableofcontents | 88 \tableofcontents |
89 | |
90 \mainmatter | |
87 | 91 |
88 \chapter{Introduction} | 92 \chapter{Introduction} |
89 Fem-fenics is an open source package (pkg) for the resolution of partial differential equations with Octave. | 93 Fem-fenics is an open source package (pkg) for the resolution of partial differential equations with Octave. |
90 The project has been developed during the Google Summer of Code 2013 with the help and the sustain of the GNU-Octave | 94 The project has been developed during the Google Summer of Code 2013 with the help and the sustain of the GNU-Octave |
91 community under the supervision of prof. De Falco. | 95 community under the supervision of prof. De Falco. |
107 \end{center} | 111 \end{center} |
108 while if you want to see how the project has grown during the time you can give a look at | 112 while if you want to see how the project has grown during the time you can give a look at |
109 \begin{center} | 113 \begin{center} |
110 \url{http://gedeone-gsoc.blogspot.com/} | 114 \url{http://gedeone-gsoc.blogspot.com/} |
111 \end{center} | 115 \end{center} |
112 Finally, the API is available as Appendix but also at the following address | 116 The API is available as Appendix \ref{app} but also at the following address |
113 \begin{center} | 117 \begin{center} |
114 \url{http://octave.sourceforge.net/fem-fenics/overview.html} | 118 \url{http://octave.sourceforge.net/fem-fenics/overview.html} |
119 \end{center} | |
120 and if you would like to contribute to the project or give a look to the source code | |
121 you can clone it from the following repository using mercurial | |
122 \begin{center} | |
123 \url{http://sourceforge.net/p/octave/fem-fenics/} . | |
115 \end{center} | 124 \end{center} |
116 | 125 |
117 \chapter{Introduction to Fem-fenics}\label{intr} | 126 \chapter{Introduction to Fem-fenics}\label{intr} |
118 | 127 |
119 \section{Installation} | 128 \section{Installation} |
392 \begin{itemize} | 401 \begin{itemize} |
393 \item keep the syntax as close as possible to the original one in Fenics (Python) | 402 \item keep the syntax as close as possible to the original one in Fenics (Python) |
394 \item make the interface as simple as possible. | 403 \item make the interface as simple as possible. |
395 \end{itemize} | 404 \end{itemize} |
396 | 405 |
397 \section{General layout of a class} | 406 \section{General layout of a class}\label{class} |
398 Seven new classes are implemented for dealing with FEniCS objects and for using them inside Octave: | 407 Seven new classes are implemented for dealing with FEniCS objects and for using them inside Octave: |
399 \begin{itemize} | 408 \begin{itemize} |
400 \item \textbf{boundarycondition} stores and builds a dolfin::DirichletBC | 409 \item \textbf{boundarycondition} stores and builds a dolfin::DirichletBC |
401 \item \textbf{coefficient} stores an expression object which is used for the | 410 \item \textbf{coefficient} stores an expression object which is used for the |
402 evaluation of user defined values | 411 evaluation of user defined values |
868 \end{center} | 877 \end{center} |
869 | 878 |
870 where the Finite Elements denoted with * are not yet fully supported inside FEniCS. | 879 where the Finite Elements denoted with * are not yet fully supported inside FEniCS. |
871 | 880 |
872 \section{General layout of a function} | 881 \section{General layout of a function} |
873 There are three general kinds of functions in the code: functions which create an abstract problem | 882 There are two general kinds of functions in the code: functions which create an abstract problem |
874 (wrappers to UFL), | 883 (wrappers to UFL) and |
875 functions which create the specific instance of a problem (wrapper to FEniCS) and functions | 884 functions which create the specific instance of a problem and discretize it (wrapper to DOLFIN). |
876 which discretize the problem and generate the matrices. | 885 \section{Wrappers to UFL} |
877 \subsection{Wrappers to UFL} | 886 As stated in section \ref{genlayout}, a problem is divided in two files: a \texttt{.ufl} file |
878 As stated in section \ref{genlayout}, a problem is divided in two files:a \textit{.ufl} file | |
879 where the abstract problem is described in Unified Form Language (UFL), | 887 where the abstract problem is described in Unified Form Language (UFL), |
880 and a script file \textit{.m} where a specific problem is implemented and solved. | 888 and a script file \texttt{.m} where a specific problem is implemented and solved. |
881 We suppose that they are called Poisson.ufl and Poisson.m . | 889 We suppose that they are called \texttt{Poisson.ufl} and \texttt{Poisson.m} . |
882 In order to use the information stored in the UFL file, i.e. the bilinear and the linear form, | 890 In order to use the information stored in the UFL file, i.e. the bilinear and the linear form, |
883 they have to be imported inside Octave. | 891 they have to be ``imported'' inside Octave. This is done using the |
884 When the UFL file is compiled using the ffc compiler, a header file \textit{Poisson.h} is generated. | 892 functions \texttt{import\_ufl\_BilinearForm, import\_ufl\_LinearForm, ...} . |
893 \subsection{Generation of code on the fly} | |
894 When a UFL file is compiled using the ffc compiler, a header file \texttt{Poisson.h} is generated. | |
885 In this header file, it is defined the Poisson class, which derives from dolfin::Form, | 895 In this header file, it is defined the Poisson class, which derives from dolfin::Form, |
886 and the constructor for the bilinear and linear form are set. | 896 and the constructor for the bilinear and linear form are set. |
887 This file is thus available only at compilation time, but it has to be included somehow | 897 This file is thus available only at compilation time, but it has to be included somehow |
888 in the wrapper function for the Bilinear and the Linear form. | 898 in the wrapper function for the Bilinear and the Linear form. |
889 An easy solution would have been to write a set of pre established problems where the user could only | 899 An easy solution would have been to write a set of pre established problems where the user could only |
890 change the values of the coefficient for a specific problem; | 900 change the values of the coefficient for a specific problem; |
891 but, as we want to let the user free to write his own | 901 but, as we want to let the user free to write his own |
892 variational problem, a different approach has been adopted. | 902 variational problem, a different approach has been adopted. |
893 The ufl file is compiled at run time and generates a header file. | 903 The \texttt{ufl} file is compiled at run time and generates its header file. |
894 Then, a Poisson.cc file is written from a template which takes as input the name | 904 Then, a Poisson.cc file is written from a template which takes as input the name |
895 of the header file and is compiled including the Poisson.h file; | 905 of the header file and is compiled including the Poisson.h file; |
896 now the corresponding octave functions for the specific problem is available and will be used from | 906 now the corresponding Octave functions for the specific problem are available and |
897 BilinearForm, LinearForm, FunctionSpace, ... . | 907 will be later used from |
908 \texttt{BilinearForm, LinearForm, FunctionSpace, ...} . | |
898 As an example it is presented the import\_ufl\_BilinearForm function. | 909 As an example it is presented the import\_ufl\_BilinearForm function. |
899 | 910 |
900 \begin{lstlisting}[language=Octave] | 911 \begin{lstlisting}[language=Octave] |
901 function import_ufl_BilinearForm (var_prob) | 912 function import_ufl_BilinearForm (var_prob) |
902 | 913 |
903 ... | 914 ... |
904 | 915 |
905 %the function which writes the var-prob.cc file | 916 %the function which writes the var_prob.cc file (see below) |
906 generate_rhs (var_prob); | 917 generate_rhs (var_prob); |
907 | 918 |
908 %the function which writes the makefile | 919 %the function which writes the makefile |
909 generate_makefile (var_prob, private); | 920 generate_makefile (var_prob, private); |
910 | 921 |
954 | 965 |
955 endfunction | 966 endfunction |
956 \end{lstlisting} | 967 \end{lstlisting} |
957 | 968 |
958 | 969 |
959 \subsection{Wrappers to DOLFIN} | 970 \section{Wrappers to DOLFIN} |
960 The general layout of a function is very simple and it is composed of 4 steps which we describe using an example: | 971 The general layout of a function is very simple and it is composed of 4 steps which we describe using an example: |
961 \begin{lstlisting} | 972 \begin{lstlisting} |
962 DEFUN_DLD (fem_fs, args, , "initialize a fs from a mesh") | 973 DEFUN_DLD (FunctionSpace, args, , "initialize a FunctionSpace from a mesh") |
963 { | 974 { |
964 // 1 read data | 975 // 1 read data |
965 const mesh & msho = static_cast<const mesh&> (args(0).get_rep ()); | 976 const mesh & msho = static_cast<const mesh&> (args(0).get_rep ()); |
966 // 2 convert the data from octave to dolfin | 977 |
978 // 2 extract the data stored in the Octave class as a DOLFIN object | |
967 const dolfin::Mesh & mshd = msho.get_msh (); | 979 const dolfin::Mesh & mshd = msho.get_msh (); |
968 // 3 build the new object using dolfin | 980 |
981 // 3 build a new object or extract the information needed using DOLFIN | |
969 boost::shared_ptr <const dolfin::FunctionSpace> g (new Laplace::FunctionSpace (mshd)); | 982 boost::shared_ptr <const dolfin::FunctionSpace> g (new Laplace::FunctionSpace (mshd)); |
970 // 4 convert the new object from dolfin to Octave and return it | 983 |
984 // 4 convert the new object from DOLFIN to Octave and return it | |
971 octave_value retval = new functionspace(g); | 985 octave_value retval = new functionspace(g); |
972 return retval; | 986 return retval; |
973 } | 987 } |
974 \end{lstlisting} | 988 \end{lstlisting} |
975 All the functions presented above follow this general structure, and thus here we present | 989 All the functions presented above follow this general structure, and thus here we present |
976 in detail only functions which present some differences. | 990 in detail only functions which present some differences. |
977 \subsubsection{Sparse Matrices} | 991 |
978 \subsubsection{Polymorphism} | 992 \subsection{DirichletBC and Coefficient} |
979 \subsubsection{DirichletBC and Coefficient} | |
980 These two functions take as input a function handle which cannot be directly evaluated by | 993 These two functions take as input a function handle which cannot be directly evaluated by |
981 a dolfin function to set, respectively, the value on the boundary or the value of the coefficient. | 994 a dolfin function to set, respectively, the value on the boundary or the value of the coefficient. |
982 It has thus been derived from dolfin::Expression a class "expression" which has as private member | 995 It has thus been derived from dolfin::Expression a class "expression" which has as private member |
983 an octave function handle and which overloads the function eval(). In this way, an object of | 996 an octave function handle and which overloads the function eval(). In this way, an object of |
984 the class expression can be initialized throughout a function handle and can be used inside dolfin because | 997 the class expression can be initialized throughout a function handle and can be used inside dolfin because |
1021 The coefficient of the variational problem can be specified using either a Coefficient | 1034 The coefficient of the variational problem can be specified using either a Coefficient |
1022 or a Function. They are different objects which behave in different ways: a Coefficient, as exlained above, | 1035 or a Function. They are different objects which behave in different ways: a Coefficient, as exlained above, |
1023 overloads the \verb$eval()$ method of the dolfin::Expression class and it is evaluated at | 1036 overloads the \verb$eval()$ method of the dolfin::Expression class and it is evaluated at |
1024 run time using the octave function \verb$feval()$. A Function instead doesn't need to be evaluated | 1037 run time using the octave function \verb$feval()$. A Function instead doesn't need to be evaluated |
1025 because it is assembled copying element-by-element the values contained in the input vector. | 1038 because it is assembled copying element-by-element the values contained in the input vector. |
1039 | |
1040 \subsection{Sparse Matrices} | |
1041 The \texttt{assemble} function discretize the continuos problem and | |
1042 return a sparse matrix. To deal with problems of big size, they are stored | |
1043 using a compressed technique \cite{Formaggia_matr} both in DOLFIN and in Octave. | |
1044 Unfortunately, DOLFIN uses row major orientation while Octave uses | |
1045 column major orientation. They have thus to be converted efficiently from | |
1046 one type to the other. | |
1047 \begin{lstlisting}[language=C++] | |
1048 | |
1049 #include "form.h" | |
1050 #include "boundarycondition.h" | |
1051 | |
1052 DEFUN_DLD (assemble, args, nargout, " ") | |
1053 { | |
1054 int nargin = args.length (); | |
1055 octave_value_list retval; | |
1056 | |
1057 if (! boundarycondition_type_loaded) | |
1058 { | |
1059 boundarycondition::register_type (); | |
1060 boundarycondition_type_loaded = true; | |
1061 mlock (); | |
1062 } | |
1063 | |
1064 if (! form_type_loaded) | |
1065 { | |
1066 form::register_type (); | |
1067 form_type_loaded = true; | |
1068 mlock (); | |
1069 } | |
1070 | |
1071 ... | |
1072 | |
1073 // Extract form object from the input | |
1074 const form & frm = static_cast<const form&> (args(0).get_rep ()); | |
1075 | |
1076 const dolfin::Form & a = frm.get_form (); | |
1077 a.check (); | |
1078 | |
1079 ... | |
1080 | |
1081 // Assemble the Matrix in DOLFIN | |
1082 dolfin::parameters["linear_algebra_backend"] = "uBLAS"; | |
1083 dolfin::Matrix A; | |
1084 dolfin::assemble (A, a); | |
1085 | |
1086 // Extract BC from input and apply BC | |
1087 ... | |
1088 const boundarycondition & bc | |
1089 = static_cast<const boundarycondition&> (args(i).get_rep ()); | |
1090 | |
1091 const std::vector<boost::shared_ptr <const dolfin::DirichletBC> > | |
1092 & pbc = bc.get_bc (); | |
1093 | |
1094 for (std::size_t j = 0; j < pbc.size (); ++j) | |
1095 pbc[j]->apply(A); | |
1096 | |
1097 | |
1098 // Get capacity of the dolfin sparse matrix | |
1099 boost::tuples::tuple<const std::size_t*, | |
1100 const std::size_t*, | |
1101 const double*, int> | |
1102 aa = A.data (); | |
1103 | |
1104 // Create the Matrix for Octave | |
1105 | |
1106 ... | |
1107 | |
1108 for (std::size_t i = 0; i < nr; ++i) | |
1109 { | |
1110 A.getrow (i, cidx_tmp, data_tmp); | |
1111 nz += cidx_tmp.size (); | |
1112 | |
1113 for (octave_idx_type j = 0; | |
1114 j < cidx_tmp.size (); ++j) | |
1115 { | |
1116 orow [ii + j] = i; | |
1117 oc [ii + j] = cidx_tmp [j]; | |
1118 ov [ii + j] = data_tmp [j]; | |
1119 } | |
1120 | |
1121 ii = nz; | |
1122 } | |
1123 | |
1124 dims(0) = ii; | |
1125 ridx.resize (dims); | |
1126 cidx.resize (dims); | |
1127 data.resize (dims); | |
1128 | |
1129 SparseMatrix sm (data, ridx, cidx, nr, nc); | |
1130 retval(0) = sm; | |
1131 | |
1132 ... | |
1133 | |
1134 return retval; | |
1135 } | |
1136 \end{lstlisting} | |
1137 | |
1138 | |
1139 \subsection{Polymorphism} | |
1140 The objects which belong to the new classes presented in section \ref{class} | |
1141 have to overload some of the methods already available in Octave. | |
1142 For example, we want to be able to \texttt{plot} a \texttt{Mesh} or a \texttt{function}, to \texttt{save} it | |
1143 and to evaluate it at a specific point in the space (\texttt{feval}). | |
1144 As Octave is a dynamically typed language it could be a difficult task to achieve, but hopefully | |
1145 the Octave interpreter takes care of it and it is enough to put the polymorphic function | |
1146 in a folder named as the type. For example, in the \texttt{@function} folder | |
1147 inside the Fem-fenics directory we can find the \texttt{plot, save, feval} functions. | |
1148 | |
1026 \iffalse | 1149 \iffalse |
1027 | 1150 |
1028 \paragraph{other function} | 1151 \paragraph{other function} |
1029 | 1152 |
1030 | 1153 |
1052 we can instead use the command \verb$assemble_system$ (). Finally, if we are solving a non-linear problem | 1175 we can instead use the command \verb$assemble_system$ (). Finally, if we are solving a non-linear problem |
1053 and we need to apply essential BC, we should provide to the function also the vector with the | 1176 and we need to apply essential BC, we should provide to the function also the vector with the |
1054 tentative solution in order to modify the entries corresponding to the boundary values. | 1177 tentative solution in order to modify the entries corresponding to the boundary values. |
1055 This will be illustrated below in the HyperElasticity example. | 1178 This will be illustrated below in the HyperElasticity example. |
1056 \fi | 1179 \fi |
1057 | |
1058 \subsection{Wrapper to FEniCS} | |
1059 | |
1060 \subsection{Code on the fly} | |
1061 | |
1062 \iffalse | |
1063 For the creation on the fly of the code from the header file, | |
1064 Juan Pablo provided me a python code which makes a great job. I have spent some | |
1065 time adapting it to my problem, but when I finally got a working code, we realized | |
1066 that it was probably enough to use the functions available inside Octave because | |
1067 the problem was rather simple. The pyton code is however available here, while the | |
1068 final solution adopted can be found there. | |
1069 \fi | |
1070 | |
1071 | 1180 |
1072 | 1181 |
1073 \chapter{More Advanced Examples}\label{exem} | 1182 \chapter{More Advanced Examples}\label{exem} |
1074 In this chapter more examples are provided. | 1183 In this chapter more examples are provided. |
1075 At the beginning of each section, the problem is briefly presented and then | 1184 At the beginning of each section, the problem is briefly presented and then |
1137 # File MixedPoisson.ufl | 1246 # File MixedPoisson.ufl |
1138 # a = (dot(sigma, tau) + div(tau)*u + div(sigma)*v)*dx | 1247 # a = (dot(sigma, tau) + div(tau)*u + div(sigma)*v)*dx |
1139 # L = - f*v*dx | 1248 # L = - f*v*dx |
1140 a = BilinearForm ('MixedPoisson', V, V); | 1249 a = BilinearForm ('MixedPoisson', V, V); |
1141 L = LinearForm ('MixedPoisson', V, f); | 1250 L = LinearForm ('MixedPoisson', V, f); |
1251 | |
1252 | |
1142 | 1253 |
1143 | 1254 |
1144 | 1255 |
1145 | 1256 |
1146 | 1257 |
1296 # we can also use the msh pkg to generate the L-shape domain | 1407 # we can also use the msh pkg to generate the L-shape domain |
1297 # as showed above | 1408 # as showed above |
1298 | 1409 |
1299 mesh = Mesh ('lshape.xml'); | 1410 mesh = Mesh ('lshape.xml'); |
1300 | 1411 |
1301 # Define function spaces (P2-P1). From ufl file | 1412 # Define function spaces (P2-P1). UFL file |
1302 # V = VectorElement("CG", triangle, 2) | 1413 # V = VectorElement("CG", triangle, 2) |
1303 # Q = FiniteElement("CG", triangle, 1) | 1414 # Q = FiniteElement("CG", triangle, 1) |
1304 V = FunctionSpace ('VelocityUpdate', mesh); | 1415 V = FunctionSpace ('VelocityUpdate', mesh); |
1305 Q = FunctionSpace ('PressureUpdate', mesh); | 1416 Q = FunctionSpace ('PressureUpdate', mesh); |
1306 | 1417 |
1442 p = TrialFunction(Q) | 1553 p = TrialFunction(Q) |
1443 v = TestFunction(V) | 1554 v = TestFunction(V) |
1444 q = TestFunction(Q) | 1555 q = TestFunction(Q) |
1445 | 1556 |
1446 # Set parameter values | 1557 # Set parameter values |
1558 nu = 0.01 | |
1447 dt = 0.01 | 1559 dt = 0.01 |
1448 T = 3 | 1560 T = 3 |
1449 nu = 0.01 | |
1450 | 1561 |
1451 # Define time-dependent pressure BC | 1562 # Define time-dependent pressure BC |
1452 p_in = Expression("sin(3.0*t)", t=0.0) | 1563 p_in = Expression("sin(3.0*t)", t=0.0) |
1453 | 1564 |
1454 # Define boundary conditions | 1565 # Define boundary conditions |
1482 | 1593 |
1483 | 1594 |
1484 # Velocity update | 1595 # Velocity update |
1485 a3 = inner(u, v)*dx | 1596 a3 = inner(u, v)*dx |
1486 L3 = inner(u1, v)*dx - k*inner(grad(p1), v)*dx | 1597 L3 = inner(u1, v)*dx - k*inner(grad(p1), v)*dx |
1487 | |
1488 | 1598 |
1489 | 1599 |
1490 # Assemble matrices | 1600 # Assemble matrices |
1491 A1 = assemble(a1) | 1601 A1 = assemble(a1) |
1492 A2 = assemble(a2) | 1602 A2 = assemble(a2) |
1712 # Create Dirichlet boundary conditions | 1822 # Create Dirichlet boundary conditions |
1713 bcl = DirichletBC (V, @(x,y,z) [0; 0; 0], 1); | 1823 bcl = DirichletBC (V, @(x,y,z) [0; 0; 0], 1); |
1714 bcr = DirichletBC (V, Rotation, 2); | 1824 bcr = DirichletBC (V, Rotation, 2); |
1715 bcs = {bcl, bcr}; | 1825 bcs = {bcl, bcr}; |
1716 | 1826 |
1717 | |
1718 # Define source and boundary traction functions | 1827 # Define source and boundary traction functions |
1719 | |
1720 B = Constant ('B', [0.0; -0.5; 0.0]); | 1828 B = Constant ('B', [0.0; -0.5; 0.0]); |
1721 T = Constant ('T', [0.1; 0.0; 0.0]); | 1829 T = Constant ('T', [0.1; 0.0; 0.0]); |
1722 | 1830 |
1723 | 1831 |
1724 | 1832 |
1922 | 2030 |
1923 \colplacechunks | 2031 \colplacechunks |
1924 \end{parcolumns} | 2032 \end{parcolumns} |
1925 \end{changemargin} | 2033 \end{changemargin} |
1926 | 2034 |
2035 \iffalse | |
1927 \section{Fictitious Domain} | 2036 \section{Fictitious Domain} |
1928 A penalization method to take into account obstacles in incompressible viscous flows | 2037 A penalization method to take into account obstacles in incompressible viscous flows |
1929 | 2038 \fi |
1930 \newpage | 2039 \newpage |
2040 | |
2041 \backmatter | |
2042 | |
1931 \appendix | 2043 \appendix |
1932 \chapter{API reference} | 2044 \chapter{API reference}\label{app} |
1933 | 2045 |
1934 \section{Import problem defined with ufl} | 2046 \section{Import problem defined with ufl} |
1935 \subsection*{import\_ufl\_BilinearForm} | 2047 \subsection*{import\_ufl\_BilinearForm} |
1936 \subimport{latex/}{API/import_ufl_BilinearForm.tex} | 2048 \subimport{latex/}{API/import_ufl_BilinearForm.tex} |
1937 \subsection*{import\_ufl\_LinearForm} | 2049 \subsection*{import\_ufl\_LinearForm} |
2042 #endif | 2154 #endif |
2043 return 0; | 2155 return 0; |
2044 } | 2156 } |
2045 | 2157 |
2046 \end{lstlisting} | 2158 \end{lstlisting} |
2159 \iffalse | |
2047 \paragraph {Warning} If in the Makefile.in you write something like | 2160 \paragraph {Warning} If in the Makefile.in you write something like |
2048 \begin{lstlisting}[language=make] | 2161 \begin{lstlisting}[language=make] |
2049 HAVE_DOLFIN_H = @HAVE_DOLFIN_H@ | 2162 HAVE_DOLFIN_H = @HAVE_DOLFIN_H@ |
2050 ifdef HAVE_DOLFIN_H | 2163 ifdef HAVE_DOLFIN_H |
2051 CPPFLAGS += -DHAVE_DOLFIN_H | 2164 CPPFLAGS += -DHAVE_DOLFIN_H |
2052 LIBS += -ldolfin | 2165 LIBS += -ldolfin |
2053 endif | 2166 endif |
2054 \end{lstlisting} | 2167 \end{lstlisting} |
2055 it doesn't work because the variable \verb$HAVE_DOLFIN_H$ seems to be always defined, even if the header is not available. | 2168 it doesn't work because the variable \verb$HAVE_DOLFIN_H$ seems to be always defined, even if the header is not available. |
2169 \fi | |
2056 | 2170 |
2057 \bibliographystyle{unsrt} | 2171 \bibliographystyle{unsrt} |
2058 \bibliography{doc} | 2172 \bibliography{doc} |
2059 \end{document} | 2173 \end{document} |