Commit c3eaaa42 authored by Thomas Witkowski's avatar Thomas Witkowski

And the last steps to first AMDiS version.

parent 29045c03
......@@ -25,8 +25,6 @@ option(USE_PETSC_DEV false)
set(ENABLE_PARMETIS false)
option(ENABLE_ZOLTAN false)
option(ENABLE_UMFPACK "use umfpack solver" false)
option(ENABLE_MKL "use the mkl" false)
SET(MKL_DIR "" CACHE PATH "MKL directory")
option(ENABLE_TESTS "compile the tests" false)
if(ENABLE_INTEL)
......@@ -259,11 +257,6 @@ if(ENABLE_UMFPACK)
LIST(APPEND AMDiS_LIBS amdis blas amd umfpack)
endif(ENABLE_UMFPACK)
if(ENABLE_MKL)
include_directories(${MKL_DIR})
SET(COMPILEFLAGS "${COMPILEFLAGS} -DHAVE_MKL=1")
endif(ENABLE_MKL)
SET(COMPOSITE_SOURCE_DIR ${SOURCE_DIR}/compositeFEM)
SET(COMPOSITE_FEM_SRC ${COMPOSITE_SOURCE_DIR}/CFE_Integration.cc
${COMPOSITE_SOURCE_DIR}/CFE_NormAndErrorFcts.cc
......
......@@ -45,7 +45,7 @@ int main(int argc, char* argv[])
FUNCNAME("main");
// ===== check for init file =====
TEST_EXIT(argc == 2)("usage: ellipt initfile\n");
TEST_EXIT(argc >= 2)("usage: ellipt initfile\n");
// ===== init parameters =====
......
\section{Composite finite elements}
\subsection{Source code}
\subsection{Parameter file}
\subsection{Macro file}
\subsection{Output}
\ No newline at end of file
\section{Coupled problems}
\label{s:couple}
In this example, we solve the same problem as in Section \ref{s:vecellipt}, but here we treat the two equations as two coupled problems. The main difference is that the equations now aren't assembled into the same large system of equations, but into two separated systems of equations, that have to be solved separately. We define the two problems
\begin{eqnarray}
-\Delta u &=& f ~~~\mbox{in } \Omega \subset \mathbb{R}^{dim}\\
u &=& g ~~~ \mbox{on } \partial\Omega
\end{eqnarray}
and
\begin{equation}
v = u.
\end{equation}
We first solve the first problem and then use its solution to solve the second problem. This happens in every iteration of the adaptation loop. Both problems should use the same mesh. Mesh adaptation is done by the first problem. So one iteration now looks like illustrated in Figure \ref{f:coupled iteration}.
\begin{figure}
\center
\includegraphics[width=0.9\textwidth]{fig/coupled_iteration.pdf}
\caption{State diagram of the coupled iteration.}
\label{f:coupled iteration}
\end{figure}
\begin{table}
\center
\begin{tabular}{|cc|c|c|c|}
\hline
& & {\bf 1d} & {\bf 2d} & {\bf 3d} \\
\hline
{\bf source code} & \tt src/ & \multicolumn{3}{|c|}{\tt couple.cc} \\
\hline
{\bf parameter file} & \tt init/ & \tt couple.dat.1d & \tt couple.dat.2d & \tt couple.dat.3d \\
\hline
{\bf macro file} & \tt macro/ & \tt macro.stand.1d & \tt macro.stand.2d & \tt macro.stand.3d \\
\hline
{\bf output files} & \tt output/ & \multicolumn{3}{|c|}{\tt couple.mesh, couple.dat} \\
\hline
\end{tabular}
\caption{Files of the {\tt couple} example.}
\end{table}
\subsection{Source code}
In the previous examples, the iteration was implemented always by the corresponding problem class. In this example, we want to couple two problems within one iteration, so the default implementation can't be used. For that reason, we define our own coupled iteration class\\ \verb+MyCoupledIteration+ which implements the \verb+ProblemIterationInterface+:
\begin{lstlisting}{}
class MyCoupledIteration : public ProblemIterationInterface
{
public:
MyCoupledIteration(ProblemStatBase *prob1,
ProblemStatBase *prob2)
: problem1(prob1),
problem2(prob2)
{}
\end{lstlisting}
In the constructor pointers to the two problems are assigned to the private members \verb+problem1+ and \verb+problem2+. Note that the pointers point to the interface \verb+ProblemStatBase+ and not to\\ \verb+ProblemScal+. This leads to a more general implementation. If e.g. two vector valued problems should be coupled in the future, we could use our iteration class without modifications.
Now, we implement the needed interface methods:
\begin{lstlisting}{}
void beginIteration(AdaptInfo *adaptInfo)
{
FUNCNAME("StandardProblemIteration::beginIteration()");
MSG("\n");
MSG("begin of iteration %d\n", adaptInfo->getSpaceIteration()+1);
MSG("=============================\n");
}
void endIteration(AdaptInfo *adaptInfo) {
FUNCNAME("StandardProblemIteration::endIteration()");
MSG("\n");
MSG("end of iteration %d\n", adaptInfo->getSpaceIteration()+1);
MSG("=============================\n");
}
\end{lstlisting}
These two functions are called at the beginning and at the end of each iteration. Here, we only prompt some output.
The method \verb+oneIteration+ is the crucial part of our implementation:
\begin{lstlisting}{}
Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION)
{
Flag flag, markFlag;
if (toDo.isSet(MARK)) markFlag = problem1->markElements(adaptInfo);
if (toDo.isSet(ADAPT) && markFlag.isSet(MESH_REFINED))
flag = problem1->refineMesh(adaptInfo);
if (toDo.isSet(BUILD)) problem1->buildAfterCoarsen(adaptInfo, markFlag);
if (toDo.isSet(SOLVE)) problem1->solve(adaptInfo);
if (toDo.isSet(BUILD)) problem2->buildAfterCoarsen(adaptInfo, markFlag);
if (toDo.isSet(SOLVE)) problem2->solve(adaptInfo);
if (toDo.isSet(ESTIMATE)) problem1->estimate(adaptInfo);
return flag;
}
\end{lstlisting}
The \verb+toDo+ flag is used by the adaptation loop to determine which parts of the iteration should be performed. The first iteration is always an iteration without mesh adaptation (see Figure \ref{f:stationary loop}). So we start our iteration by marking and adapting the mesh. The mesh and its adaptation is managed by the first problem. So we call \verb+markElements+ and \verb+refineMesh+ of \verb+problem1+. Note that no mesh coarsenings have to be performed in our example. Afterwards, \verb+problem1+ assembles its system of equations by \verb+buildAfterCoarsen+. Assemblage and mesh adaptation are nested operations in AMDiS (\verb+buildBeforeRefine+, \verb+refineMesh+, \verb+buildBeforeCoarsen+,\\\verb+coarsenMesh+,\verb+buildAfterCoarsen+). Here, we implement a simplified version.
After \verb+problem1+ has solved its system of equations, \verb+problem2+ can assemble and solve its equations system using the solution of the first problem as right hand side. In the method \verb+oneIteration+, only the order of method calls is determined. The dependency to the solution of the first problem is created later when the operator for the right hand side of \verb+problem2+ is created.
After also the second problem computed its solution, \verb+problem1+ does the error estimation (remember: mesh adaptation is managed by \verb+problem1+).
\begin{figure}
\center
\includegraphics[width=0.9\textwidth]{fig/stationary_loop.pdf}
\caption{Stationary adaptation loop.}
\label{f:stationary loop}
\end{figure}
Now, the access to the coupled problems is implemented and the member variables are defined:
\begin{lstlisting}{}
int getNumProblems()
{
return 2;
}
ProblemStatBase *getProblem(int number = 0)
{
FUNCNAME("CoupledIteration::getProblem()");
if (number == 0) return problem1;
if (number == 1) return problem2;
ERROR_EXIT("invalid problem number\n");
return NULL;
}
private:
ProblemStatBase *problem1;
ProblemStatBase *problem2;
};
\end{lstlisting}
The class \verb+MyCoupledIteration+ is finished now.
The next class, \verb+Identity+, implements the identity $I(x)=x$ for \verb+double+ variables. An arbitrary degree can be given to it. The class is used later to determine the quadrature degree used for the right hand side of \verb+problem2+.
\begin{lstlisting}{}
class Identity : public AbstractFunction<double, double>
{
public:
Identity(int degree) : AbstractFunction<double, double>(degree) {}
double operator()(const double& x) const
{
return x;
}
};
\end{lstlisting}
Now, we start with the main program:
\begin{lstlisting}{}
int main(int argc, char* argv[])
{
FUNCNAME("main");
TEST_EXIT(argc == 2)("usage: couple initfile\n");
Parameters::init(true, argv[1]);
// ===== create and init the first problem =====
ProblemScal problem1("problem1");
problem1.initialize(INIT_ALL);
// ===== add boundary conditions for problem1 =====
problem1.addDirichletBC(1, new G);
\end{lstlisting}
So far, we created and initialized \verb+problem1+ and its boundary conditions.
Now, we create \verb+problem2+. It should have its own finite element space, system, solver and file writer, but the mesh should be adopted from \verb+problem1+.
\begin{lstlisting}{}
// ===== create and init the second problem =====
Flag initFlag =
INIT_FE_SPACE |
INIT_SYSTEM |
INIT_SOLVER |
INIT_FILEWRITER;
Flag adoptFlag =
CREATE_MESH |
INIT_MESH;
ProblemScal problem2("problem2");
problem2.initialize(initFlag,
&problem1,
adoptFlag);
\end{lstlisting}
The operators for the first problem are defined like in Section
\ref{s:ellipt code}. Here, we only show the operators of
\verb+problem2+.
\begin{lstlisting}{}
// ===== create operators for problem2 =====
Operator matrixOperator2(problem2.getFeSpace());
matrixOperator2.addZeroOrderTerm(new Simple_ZOT);
problem2.addMatrixOperator(&matrixOperator2);
Operator rhsOperator2(problem2.getFeSpace());
rhsOperator2.addZeroOrderTerm(new VecAtQP_ZOT(problem1.getSolution(),
new Identity(degree)));
problem2.addVectorOperator(&rhsOperator2);
\end{lstlisting}
At the left hand side, we have just an ordinary \verb+Simple_ZOT+. At
the right hand side, we have a zero order term of the form $f(u)$ with
$f=I$ the identity. $u$ is given by the solution DOF vector of
\verb+problem1+. $I$ maps the values of the DOF vector evaluated at
quadrature points to itself. The function degree is used to determine
the needed quadrature degree in the assembler.
Now, the adaptation loop is created:
\begin{lstlisting}{}
// ===== create adaptation loop and iteration interface =====
AdaptInfo *adaptInfo = new AdaptInfo("couple->adapt", 1);
MyCoupledIteration coupledIteration(&problem1, &problem2);
AdaptStationary *adapt = new AdaptStationary("couple->adapt",
&coupledIteration,
adaptInfo);
\end{lstlisting}
Note that not a pointer to one of the problems is passed to the
adaptation loop, but a pointer to the \verb+coupledIteration+ object,
which in turn knows both problems.
The adaptation loop is now started. After it is finished, the
solutions of both problems are written.
\begin{lstlisting}{}
// ===== start adaptation loop =====
adapt->adapt();
// ===== write solution =====
problem1.writeFiles(adaptInfo, true);
problem2.writeFiles(adaptInfo, true);
}
\end{lstlisting}
\subsection{Parameter file}
We have one adaptation loop called \verb+couple->adapt+:
\begin{lstlisting}{}
couple->adapt->tolerance: 1e-8
couple->adapt->max iteration: 10
couple->adapt->refine bisections: 2
\end{lstlisting}
The coupled problem consits of two sub problems. The first problem
creates the mesh, solves its linear system of equations, estimates the
error, adapts the mesh, and finally writes its output:
\begin{lstlisting}{}
coupleMesh->macro file name: ./macro/macro.stand.2d
coupleMesh->global refinements: 0
problem1->mesh: coupleMesh
problem1->dim: 2
problem1->polynomial degree: 1
problem1->solver: cg % no, bicgstab, cg, gmres, odir, ores
problem1->solver->max iteration: 1000
problem1->solver->tolerance: 1.e-8
problem1->solver->left precon: diag
problem1->estimator: residual
problem1->estimator->C0: 0.1 % constant of element residual
problem1->estimator->C1: 0.1 % constant of jump residual
problem1->marker->strategy: 2 % 0: no 1: GR 2: MS 3: ES 4:GERS
problem1->marker->MSGamma: 0.5
problem1->output->filename: output/problem1
problem1->output->AMDiS format: 1
problem1->output->AMDiS mesh ext: .mesh
problem1->output->AMDiS data ext: .dat
\end{lstlisting}
The second problem uses the mesh of \verb+problem1+. So it creates no
mesh, no estimator, and no marker. But a solver is needed to solve
\verb+problem2+s linear system of equations, and a file writer to
write the solution:
\begin{lstlisting}{}
problem2->dim: 2
problem2->polynomial degree: 1
problem2->solver: cg % no, bicgstab, cg, gmres, odir, ores
problem2->solver->max iteration: 1000
problem2->solver->tolerance: 1.e-8
problem2->solver->left precon: diag
problem2->estimator: no
problem2->marker->strategy: 0
problem2->output->filename: output/problem2
problem2->output->AMDiS format: 1
problem2->output->AMDiS mesh ext: .mesh
problem2->output->AMDiS data ext: .dat
\end{lstlisting}
\subsection{Macro file}
We again use the macro file \verb+macro/macro.stand.2d+, which was
described in Section \ref{s:ellipt macro}.
\subsection{Output}
The solution of the first problem is written to the files
\verb+output/problem1.mesh+ and\\ \verb+output/problem1.dat+. The
solution of the second problem is written to the files\\
\verb+output/problem2.mesh+ and \verb+output/problem2.dat+. We don't
visualize the results here, because they conform with the results
showed in Section \ref{s:vecellipt output}.
......@@ -123,7 +123,7 @@ int main(int argc, char* argv[])
FUNCNAME("main");
// ===== check for init file =====
TEST_EXIT(argc == 2)("usage: ellipt initfile\n");
TEST_EXIT(argc >= 2)("usage: ellipt initfile\n");
// ===== init parameters =====
Parameters::init(true, argv[1]);
......@@ -141,11 +141,11 @@ argument specifies, whether the initialized parameters should be
printed after initialization for debug reasons. The second argument is
the name of the parameter file.
Now, a scalar problem with name \verb+ellipt+ is created and initialized:
Now, a stationary problem with name \verb+ellipt+ is created and initialized:
\begin{lstlisting}{}
// ===== create and init the scalar problem =====
ProblemScal ellipt("ellipt");
ProblemStat ellipt("ellipt");
ellipt.initialize(INIT_ALL);
\end{lstlisting}
......@@ -154,9 +154,9 @@ parameter file that belong to this problem. In this case, all
parameters with prefix \verb+ellipt->+ are associated to this
problem. The initialization argument \verb+INIT_ALL+ means that all
problem modules are created in a standard way. Those are: The finite
element space including the corresponding mesh, needed system matrices
and vectors, an iterative solver, an estimator, a marker, and a file
writer for the computed solution. The initialization of these
element space including the corresponding mesh, the required system
matrices and vectors, an iterative solver, an estimator, a marker, and
a file writer for the computed solution. The initialization of these
components can be controlled through the parameter file (see Section
\ref{s:ellipt parameter}).
......@@ -182,47 +182,49 @@ used as parameter prefix, the problem as implementation of an
iteration interface, and the \verb+AdaptInfo+ object. The adaptation
loop only knows when to perform which part of an iteration. The
implementation and execution of the single steps is delegated to an
iteration interface, here implemented by the scalar problem
iteration interface, here implemented by the stationary problem
\verb+ellipt+.
Now, we define boundary conditions:
\begin{lstlisting}{}
// ===== add boundary conditions =====
ellipt.addDirichletBC(1, new G);
\end{lstlisting}
We have one Dirichlet boundary condition associated with identifier
$1$. All nodes belonging to this boundary are set to the value of
function \verb+G+ at the corresponding coordinates. In the macro file
(see Section \ref{s:ellipt macro}) the Dirichlet boundary is marked
with identifier $1$, too. So the nodes can be uniquely determined.
The operators now are defined as follows:
\begin{lstlisting}{}
// ===== create matrix operator =====
Operator matrixOperator(ellipt.getFeSpace());
matrixOperator.addSecondOrderTerm(new Laplace_SOT);
ellipt.addMatrixOperator(&matrixOperator);
ellipt.addMatrixOperator(matrixOperator, 0, 0);
// ===== create rhs operator =====
int degree = ellipt.getFeSpace()->getBasisFcts()->getDegree();
Operator rhsOperator(ellipt.getFeSpace());
rhsOperator.addZeroOrderTerm(new CoordsAtQP_ZOT(new F(degree)));
ellipt.addVectorOperator(&rhsOperator);
ellipt.addVectorOperator(rhsOperator, 0);
\end{lstlisting}
First, we define a matrix operator (left hand side operator) on the
finite element space of the problem. Now, we add the term $-\Delta u$
to it. Note that the minus sign isn't explicitly given, but implicitly
We define a matrix operator (left hand side operator) on the finite
element space of the problem. The term $-\Delta u$ is added to
it. Note that the minus sign isn't explicitly given, but implicitly
contained in \verb+Laplace_SOT+. With \verb+addMatrixOperator+ we add
the operator to the problem. The definition of the right hand side is
done in a similar way. We choose the degree of our function to be
equal to the current basis function degree.
the operator to the stationary problem definition. The both zeros
represent the position of the operator in the operator matrix. As we
are about to define a scalar equation, there is only the 0/0 position
in the operator matrix. The definition of the right hand side is done
in a similar way. We choose the degree of our function to be equal to
the current basis function degree.
Finally we start the adaptation loop and afterwards write out the results:
Now, we define boundary conditions:
\begin{lstlisting}{}
// ===== add boundary conditions =====
ellipt.addDirichletBC(1, 0, 0, new G);
\end{lstlisting}
We have one Dirichlet boundary condition associated with identifier
$1$. All nodes belonging to this boundary are set to the value of
function \verb+G+ at the corresponding coordinates. In the macro file
(see Section \ref{s:ellipt macro}) the Dirichlet boundary is marked
with identifier $1$, too. So the nodes can be uniquely determined. As
with adding operators to the operator matrix, we have to define the
operator, on which the boundary condition will be applied. Thus we
have to provide the matrix position indices after the boundary
identifier.
Finally we start the adaptation loop and afterwards write out the results:
\begin{lstlisting}{}
// ===== start adaption loop =====
adapt.adapt();
......@@ -269,12 +271,15 @@ a finer mesh.
ellipt->mesh: elliptMesh
ellipt->dim: 2
ellipt->polynomial degree: 1
ellipt->components: 1
\end{lstlisting}
Now, we construct the finite element space for the problem
\verb+ellipt+ (see Section \ref{s:ellipt code}). We use the mesh
\verb+elliptMesh+, set the problem dimension to 2, and choose Lagrange
basis functions of degree 1.
basis functions of degree 1. The number of components, i.e.\
variables, in the equation is set to 1, since we are about to define a
scalar PDE.
\begin{lstlisting}{}
ellipt->solver: cg
......@@ -290,10 +295,10 @@ tolerance of $10^{-8}$ is reached. Furthermore, we apply diagonal left
preconditioning, and no right preconditioning.
\begin{lstlisting}{}
ellipt->estimator: residual
ellipt->estimator->error norm: 1
ellipt->estimator->C0: 0.1
ellipt->estimator->C1: 0.1
ellipt->estimator[0]: residual
ellipt->estimator[0]->error norm: 1
ellipt->estimator[0]->C0: 0.1
ellipt->estimator[0]->C1: 0.1
\end{lstlisting}
As error estimator we use the residual method. The used error norm is
......@@ -301,17 +306,18 @@ the H1-norm (instead of the L2-norm: 2). Element residuals (C0) and
jump residuals (C1) both are weighted by factor $0.1$.
\begin{lstlisting}{}
ellipt->marker->strategy: 2 % 0: no 1: GR 2: MS 3: ES 4:GERS
ellipt->marker->MSGamma: 0.5
ellipt->marker[0]->strategy: 2 % 0: no 1: GR 2: MS 3: ES 4:GERS
ellipt->marker[0]->MSGamma: 0.5
\end{lstlisting}
After error estimation, elements are marked for refinement and
coarsening. Here, we use the maximum strategy with $\gamma = 0.5$.
\begin{lstlisting}{}
ellipt->adapt->tolerance: 1e-4
ellipt->adapt[0]->tolerance: 1e-4
ellipt->adapt[0]->refine bisections: 2
ellipt->adapt->max iteration: 10
ellipt->adapt->refine bisections: 2
\end{lstlisting}
The adaptation loop stops, when an error tolerance of $10^{-4}$ is
......
......@@ -4,7 +4,6 @@
\input{ellipt.tex}
\input{heat.tex}
\input{vecellipt.tex}
\input{couple.tex}
\input{neumann.tex}
\input{periodic.tex}
\input{projections.tex}
......
......@@ -95,19 +95,18 @@ the same way.
Now, we begin with the implementation of class \verb+Heat+, that
represents the instationary problem. In Figure \ref{f:heat_uml}, its
class diagram is shown. \verb+Heat+ is derived from class
\verb+ProblemInstatScal+ which leads to following properties:
\verb+ProblemInstat+ which leads to following properties:
\begin{description}
\item \verb+Heat+ implements the \verb+ProblemTimeInterface+, so the
adaptation loop can set the current time and schedule timesteps.
\item \verb+Heat+ implements \verb+ProblemStatBase+ in the role as
initial (stationary) problem. The adaptation loop can compute the
initial solution through this interface. The single iteration steps
can be overloaded by sub classes of
\verb+ProblemInstatScal+. Actually, the initial solution is computed
through the method \verb+solveInitialProblem+ of
\verb+ProblemTimeInterface+. But this method is implemented by
\verb+ProblemInstatScal+ interpreting itself as initial stationary
problem.
can be overloaded by sub classes of \verb+ProblemInstat+. Actually,
the initial solution is computed through the method
\verb+solveInitialProblem+ of \verb+ProblemTimeInterface+. But this
method is implemented by \verb+ProblemInstat+ interpreting
itself as initial stationary problem.
\item \verb+Heat+ knows another implementation of
\verb+ProblemStatBase+: This other implementation represents a
stationary problem which is solved within each
......@@ -116,14 +115,14 @@ class diagram is shown. \verb+Heat+ is derived from class
The first lines of class \verb+Heat+ are:
\begin{lstlisting}{}
class Heat : public ProblemInstatScal
class Heat : public ProblemInstat
{
public:
Heat(ProblemScal &heatSpace)
: ProblemInstatScal("heat", heatSpace)
Heat(ProblemStat &heatSpace)
: ProblemInstat("heat", heatSpace)
{
theta = -1.0;
GET_PARAMETER(0, name + "->theta", "%f", &theta);
Parameters::get(name + "->theta", theta);
TEST_EXIT(theta >= 0)("theta not set!\n");
theta1 = theta - 1.0;
}
......@@ -131,7 +130,7 @@ public:
The argument \verb+heatSpace+ is a pointer to the stationary problem
which is solved each timestep. It is directly handed to the base class
constructor of \verb+ProblemInstatScal+. In the body of the
constructor of \verb+ProblemInstat+. In the body of the
constructor, $\theta$ is read from the parameter file and stored in a
member variable. The member variable \verb+theta1+ stores the value of
$\theta - 1$. A pointer to this value is used later as factor in the
......@@ -148,7 +147,7 @@ The next lines show the implementation of the time interface.
void closeTimestep(AdaptInfo *adaptInfo)
{
ProblemInstatScal::closeTimestep(adaptInfo);
ProblemInstat::closeTimestep(adaptInfo);
WAIT;
}
\end{lstlisting}
......@@ -163,7 +162,7 @@ boundary function $g$ at $t^{new}$, which is the current time.
The method \verb+closeTimestep+ is called at the end of each timestep
by the adaptation loop. In the default implementation of
\verb+ProblemInstatScal::closeTimestep+, the solution is written to
\verb+ProblemInstat::closeTimestep+, the solution is written to
output files, if specified in the parameter file. Note that the base
class implementation of a method must be explicitly called, if the
method is overwritten in a sub class. The macro \verb+WAIT+ waits
......@@ -197,7 +196,7 @@ the initial problem by implementing this interface.
Here, only the solve and the estimate step are overloaded. For the
other steps, there are empty default implementations in
\verb+ProblemInstatScal+. Since the mesh is not adapted in the initial
\verb+ProblemInstat+. Since the mesh is not adapted in the initial
problem, the initial adaptation loop will stop after one iteration. In
the solve step, the exact solution is interpolated on the macro mesh
and stored in the solution vector of the stationary problem. In the
......@@ -242,7 +241,7 @@ int main(int argc, char** argv)
Parameters::readArgv(argc, argv);
// ===== create and init stationary problem =====
ProblemScal heatSpace("heat->space");
ProblemStat heatSpace("heat->space");
heatSpace.initialize(INIT_ALL);
// ===== create instationary problem =====
......@@ -253,7 +252,7 @@ int main(int argc, char** argv)
So far, the stationary space problem \verb+heatSpace+ and the
instationary problem \verb+heat+ were created and
initialized. \verb+heatSpace+ is an instance of
\verb+ProblemScal+. \verb+heat+ is an instance of the class
\verb+ProblemStat+. \verb+heat+ is an instance of the class
\verb+Heat+ we defined above. \verb+heatSpace+ is given to \verb+heat+
as its stationary problem.
......@@ -277,9 +276,9 @@ and of the instationary adaptation loop:
The object \verb+heatSpace+ is handed as
\verb+ProblemIterationInterface+ (implemented by class\\
\verb+ProblemScal+) to the adaptation loop. \verb+heat+ is interpreted
\verb+ProblemStat+) to the adaptation loop. \verb+heat+ is interpreted
as \verb+ProblemTimeInterface+ (implemented by class
\verb+ProblemInstatScal+).
\verb+ProblemInstat+).
The function $g$ is declared in the following way:
\begin{lstlisting}{}
......@@ -309,11 +308,11 @@ Now, we define the operators:
// create laplace
Operator A(heatSpace.getFeSpace());
A.addSecondOrderTerm(new Laplace_SOT);
A.setUhOld(heat.getOldSolution());
A.setUhOld(heat.getOldSolution(0));
if (*(heat.getThetaPtr()) != 0.0)
heatSpace.addMatrixOperator(A, heat.getThetaPtr(), &one);
heatSpace.addMatrixOperator(A,