Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

Commit e59d6928 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

First working nonlinear solver (but very restricted).

parent deb831ee
......@@ -145,7 +145,6 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/io/ValueReader.cc
${SOURCE_DIR}/io/ValueWriter.cc
${SOURCE_DIR}/io/VtkWriter.cc
${SOURCE_DIR}/nonlin/NonLinUpdater.cc
${SOURCE_DIR}/nonlin/ProblemNonLin.cc
${SOURCE_DIR}/parallel/InteriorBoundary.cc
${SOURCE_DIR}/time/RosenbrockAdaptInstationary.cc
......@@ -323,6 +322,11 @@ INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/parallel/)
list(APPEND deb_add_dirs "include/amdis/parallel")
FILE(GLOB HEADERS "${SOURCE_DIR}/nonlin/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/nonlin/)
list(APPEND deb_add_dirs "include/amdis/nonlin")
FILE(GLOB HEADERS "${SOURCE_DIR}/time/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/time/)
......
......@@ -122,9 +122,13 @@
#include "io/ValueWriter.h"
#include "io/VtkWriter.h"
#include "nonlin/ProblemNonLin.h"
#include "nonlin/NonLinSolver.h"
#include "time/RosenbrockAdaptInstationary.h"
#include "time/RosenbrockStationary.h"
#if HAVE_PARALLEL_DOMAIN_AMDIS
#include "parallel/InteriorBoundary.h"
#include "parallel/MpiHelper.h"
......
......@@ -26,6 +26,7 @@
#include "DOFMatrix.h"
#include "UmfPackSolver.h"
#include "time/RosenbrockMethod.h"
#include "nonlin/NonLinSolver.h"
namespace AMDiS {
......@@ -142,4 +143,11 @@ namespace AMDiS {
addCreator("ros3p", new Ros3p::Creator);
addCreator("rodasp", new Rodasp::Creator);
}
template<>
void CreatorMap<NonLinSolver>::addDefaultCreators()
{
addCreator("newton", new Newton::Creator);
}
}
......@@ -634,8 +634,6 @@ namespace AMDiS {
{
FUNCNAME("ProblemStat::buildAfterCoarsen()");
VtkWriter::writeFile(rhs->getDOFVector(0), "test.vtu");
// buildAfterCoarsen_sebastianMode(adaptInfo, flag);
// return;
......@@ -780,7 +778,6 @@ namespace AMDiS {
if (asmMatrix) {
solverMatrix.setMatrix(*systemMatrix);
createPrecon();
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
}
......@@ -971,8 +968,6 @@ namespace AMDiS {
solverMatrix.setMatrix(*systemMatrix);
createPrecon();
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n",
TIME_USED(first, clock()));
......@@ -1232,9 +1227,6 @@ namespace AMDiS {
solverMatrix.setMatrix(*systemMatrix);
createPrecon();
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n",
......@@ -1242,24 +1234,6 @@ namespace AMDiS {
}
void ProblemStatSeq::createPrecon()
{
/*string preconType("no");
Parameters::get(name + "->solver->left precon", preconType);
CreatorInterface<ITL_BasePreconditioner> *preconCreator =
CreatorMap<ITL_BasePreconditioner>::getCreator(preconType);
solver->setLeftPrecon(preconCreator->create(solverMatrix.getMatrix()));
preconType= "no";
Parameters::get(name + "->solver->right precon", preconType);
preconCreator = CreatorMap<ITL_BasePreconditioner>::getCreator(preconType);
solver->setRightPrecon(preconCreator->create(solverMatrix.getMatrix()));*/
}
void ProblemStatSeq::writeFiles(AdaptInfo *adaptInfo, bool force)
{
FUNCNAME("ProblemStat::writeFiles()");
......@@ -1570,91 +1544,31 @@ namespace AMDiS {
Mesh *mesh = feSpace->getMesh();
const BasisFunction *basisFcts = feSpace->getBasisFcts();
#ifdef _OPENMP
TraverseParallelStack stack(0, 1);
#else
TraverseStack stack;
#endif
// == Initialize matrix and vector. If we have to assemble in parallel, ===
// == temporary thread owned matrix and vector must be created. ===
#ifdef _OPENMP
#pragma omp parallel
#endif
{
BoundaryType *bound =
useGetBound ? new BoundaryType[basisFcts->getNumber()] : NULL;
// Create for every thread its private matrix and vector, on that
// the thread will assemble its part of the mesh.
DOFMatrix *tmpMatrix = NULL;
DOFVector<double> *tmpVector = NULL;
#ifdef _OPENMP
if (matrix) {
tmpMatrix = new DOFMatrix(matrix->getRowFeSpace(), matrix->getColFeSpace(), "tmp");
// Copy the global matrix to the private matrix, because we need the
// operators defined on the global matrix in the private one. Only the
// values have to be set to zero.
*tmpMatrix = *matrix;
tmpMatrix->clear();
tmpMatrix->getBaseMatrix().change_dim(matrix->getRowFeSpace()->getAdmin()->getUsedSize(),
matrix->getColFeSpace()->getAdmin()->getUsedSize());
tmpMatrix->startInsertion(10);
}
if (vector) {
tmpVector = new DOFVector<double>(vector->getFeSpace(), "tmp");
// Copy the global vector to the private vector, because we need the
// operatirs defined on the global vector in the private one. But set
// the values to zero of the private vector after copying.
*tmpVector = *vector;
tmpVector->set(0.0);
}
#else
if (matrix) {
tmpMatrix = matrix;
tmpMatrix->startInsertion(matrix->getNnz());
}
if (vector) {
tmpVector = vector;
tmpVector->set(0.0);
}
#endif
// == Traverse mesh (either sequentially or in parallel) and assemble. ==
matrix->startInsertion(matrix->getNnz());
vector->set(0.0);
// Because we are using the parallel traverse stack, each thread will
// traverse only a part of the mesh.
// == Traverse mesh and assemble. ==
ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag);
// After creating privat copies of the DOFMatrix and the DOFVector, all threads
// have to wait at this barrier. Especially for small problems this is required,
// because otherwise one thread may be finished with assembling, before another
// has made his private copy.
#ifdef _OPENMP
#pragma omp barrier
#endif
while (elInfo) {
if (useGetBound)
basisFcts->getBound(elInfo, bound);
if (matrix) {
tmpMatrix->assemble(1.0, elInfo, bound);
matrix->assemble(1.0, elInfo, bound);
// Take the matrix boundary manager from the public matrix,
// but assemble the boundary conditions on the thread private matrix.
if (matrix->getBoundaryManager())
matrix->getBoundaryManager()->fillBoundaryConditions(elInfo, tmpMatrix);
matrix->getBoundaryManager()->fillBoundaryConditions(elInfo, matrix);
}
if (vector)
tmpVector->assemble(1.0, elInfo, bound, NULL);
vector->assemble(1.0, elInfo, bound, NULL);
elInfo = stack.traverseNext(elInfo);
}
......@@ -1662,61 +1576,11 @@ namespace AMDiS {
// == Finally, if we have assembled in parallel, we have to add the thread ==
// == private matrix and vector to the global one. ==
#ifdef _OPENMP
if (tmpMatrix)
tmpMatrix->finishInsertion();
// After mesh traverse, all thread have to added their private matrices and
// vectors to the global public matrix and public vector. Therefore, this is
// a critical section, which is allowed to be executed by on thread only at
// the same time.
if (matrix) {
#pragma omp critical
{
matrix->getBaseMatrix() += tmpMatrix->getBaseMatrix();
}
}
#pragma omp barrier
#pragma omp master
{
if (matrix)
matrix->startInsertion();
}
#pragma omp barrier
if (matrix) {
// Remove rows corresponding to DOFs on a Dirichlet boundary.
#pragma omp critical
matrix->removeRowsWithDBC(tmpMatrix->getApplyDBCs());
delete tmpMatrix;
}
if (vector) {
#pragma omp critical
*vector += *tmpVector;
delete tmpVector;
}
#else
if (matrix)
matrix->removeRowsWithDBC(matrix->getApplyDBCs());
#endif
if (useGetBound)
delete [] bound;
} // pragma omp parallel
// INFO(info, 8)("Assemble matrix with %d mat ops and %d vec ops needed %.5f seconds\n",
// matrix ? matrix->getOperators().size() : 0,
// vector ? vector->getOperators().size() : 0,
// TIME_USED(first, clock()));
}
......@@ -1727,6 +1591,7 @@ namespace AMDiS {
{
FUNCNAME("ProblemStat::assembleBoundaryConditions()");
// === Initialization of vectors ===
if (rhs->getBoundaryManager())
......@@ -1734,55 +1599,6 @@ namespace AMDiS {
if (solution->getBoundaryManager())
solution->getBoundaryManager()->initVector(solution);
#ifdef _OPENMP
// === Parallel boundary assemblage ===
TraverseParallelStack stack;
#pragma omp parallel
{
// Each thread assembles on its own dof-vectors.
DOFVector<double> *tmpRhsVec = new DOFVector<double>(rhs->getFeSpace(), "tmpRhs");
DOFVector<double> *tmpSolVec = new DOFVector<double>(solution->getFeSpace(), "tmpSol");
tmpRhsVec->set(0.0);
tmpSolVec->set(0.0);
// (Parallel) traverse of mesh.
ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag);
while (elInfo) {
if (rhs->getBoundaryManager())
rhs->getBoundaryManager()-> fillBoundaryConditions(elInfo, tmpRhsVec);
if (solution->getBoundaryManager())
solution->getBoundaryManager()->fillBoundaryConditions(elInfo, tmpSolVec);
elInfo = stack.traverseNext(elInfo);
}
// After (parallel) mesh traverse, the result is applied to the final
// vectors. This section is not allowed to be executed by more than one
// thread at the same time.
#pragma omp critical
{
DOFVector<double>::Iterator rhsIt(rhs, USED_DOFS);
DOFVector<double>::Iterator solIt(solution, USED_DOFS);
DOFVector<double>::Iterator tmpRhsIt(tmpRhsVec, USED_DOFS);
DOFVector<double>::Iterator tmpSolIt(tmpSolVec, USED_DOFS);
for (rhsIt.reset(), solIt.reset(), tmpRhsIt.reset(), tmpSolIt.reset();
!rhsIt.end();
++rhsIt, ++solIt, ++tmpRhsIt, ++tmpSolIt) {
*rhsIt += *tmpRhsIt;
*solIt += *tmpSolIt;
}
} // pragma omp critical
delete tmpRhsVec;
delete tmpSolVec;
} // pragma omp parallel
#else
// === Sequentiell boundary assemblage ===
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag);
while (elInfo) {
......@@ -1794,7 +1610,6 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
#endif
// === Finalize vectors ===
......
......@@ -48,6 +48,7 @@ namespace AMDiS {
Flag operatorType;
};
/** \brief
* This class defines the stationary problem definition in sequential
* computations. For parallel computations, see
......@@ -195,9 +196,6 @@ namespace AMDiS {
void dualAssemble(AdaptInfo *adaptInfo, Flag flag,
bool asmMatrix = true, bool asmVector = true);
void createPrecon();
/** \brief
* Determines the execution order of the single adaption steps. If adapt is
* true, mesh adaption will be performed. This allows to avoid mesh adaption,
......
......@@ -26,6 +26,7 @@
#include "CreatorInterface.h"
#include "NonLinSolver.h"
#include "OEMSolver.h"
#include "io/VtkWriter.h"
namespace AMDiS {
......@@ -45,114 +46,93 @@ namespace AMDiS {
public:
virtual ~Creator() {}
/** \brief
* Returns a new Newton object.
*/
/// Returns a new Newton object.
NonLinSolver* create()
{
return new Newton(this->name, this->linearSolver, this->nonLinUpdater);
return new Newton(this->name, this->linearSolver);
}
};
/** \brief
* Calls constructor of base class NonLinSolver
*/
Newton(const std::string& name_,
OEMSolver *linSolver_,
NonLinUpdater *updater)
: NonLinSolver(name_, linSolver_, updater),
/// Calls constructor of base class NonLinSolver
Newton(const std::string& name, OEMSolver *linSolver)
: NonLinSolver(name, linSolver),
b(NULL)
{}
private:
/** \brief
* realisation of NonLinSolver::init
*/
void init()
{}
/// Realisation of NonLinSolver::init
void init() {}
/** \brief
* realisation of NonLinSolver::nlsolve
*/
/// realisation of NonLinSolver::nlsolve
int nlsolve(SolverMatrix<Matrix<DOFMatrix*> >& mat,
SystemVector& x, SystemVector& rhs)
SystemVector& x, SystemVector& rhs,
AdaptInfo *adaptInfo,
ProblemStat *prob)
{
//DOFVector<T> *d = problem->getRHS();
//DOFVector<T> *x = problem->getSolution();;
FUNCNAME("Newton::nlsolve()");
if (b == NULL)
b = new SystemVector(x);
*b = rhs;
// // copy operators from fh to b
// std::vector<Operator*>::iterator op;
// std::vector<double*>::iterator fac;
// for(op = d->getOperatorsBegin(),
// fac = d->getOperatorFactorBegin();
// op != d->getOperatorsEnd();
// ++op, ++fac)
// {
// b->addOperator(*op, *fac);
// }
double err = 0.0, err_old = -1.0;
double err = 0.0, errOld = -1.0;
int iter, n;
INFO(this->info,2)("iter. | this->residual | red. | n |\n");
MSG("iter. | this->residual | red. | n |\n");
for (iter = 1; iter <= this->maxIter; iter++) {
/*--- Assemble DF(x) and F(x) ----------------------------------------------*/
this->nonLinUpdater->update(/*x,*/true, b);
/*--- Initial guess is zero ------------------------------------------------*/
rhs.set(0.0);
/*--- solve linear system --------------------------------------------------*/
// Assemble DF(x) and F(x)
prob->buildAfterCoarsen(adaptInfo, 0, true, true);
// Initial guess is zero
b->set(0.0);
// Solve linear system
n = solveLinearSystem(mat, *b, rhs);
/*--- x = x - d ------------------------------------------------------------*/
x -= rhs;
// x = x + d
x += *b;
if (this->usedNorm == NO_NORM || this->usedNorm == L2_NORM)
err = L2Norm(&rhs); // sollte hier nicht b genommen werden (s. NewtonS) ?
err = L2Norm(b);
else
err = H1Norm(&rhs); // sollte hier nicht b genommen werden (s. NewtonS) ?
err = H1Norm(b);
if (iter == 1) this->initial_residual = err;
if (iter == 1)
this->initialResidual = err;
if (err_old <= 0) {
INFO(this->info,2)("%5d | %12.5e | -------- | %4d |\n", iter, err, n);
} else {
INFO(this->info,2)("%5d | %12.5e | %8.2e | %4d |\n",
iter, err, err/err_old, n);
}
if (errOld <= 0)
MSG("%5d | %12.5e | -------- | %4d |\n", iter, err, n);
else
MSG("%5d | %12.5e | %8.2e | %4d |\n", iter, err, err/errOld, n);
if ((this->residual = err) < this->tolerance) {
INFO(this->info,4)("finished successfully\n");
residual = err;
if (err < this->tolerance) {
MSG("Finished successfully!\n");
return iter;
}
err_old = err;
errOld = err;
}
if (this->info < 2)
INFO(this->info,1)("iter. %d, residual: %12.5e\n", iter, err);
INFO(this->info,1)("tolerance %e not reached\n", this->tolerance);
MSG("iter. %d, residual: %12.5e\n", iter, err);
MSG("tolerance %e not reached\n", this->tolerance);
this->residual = err;
return iter;
}
/** \brief
* realisation of NonLinSolver::exit
*/
/// Realisation of NonLinSolver::exit
void exit()
{
if (b != NULL)
if (b != NULL) {
delete b;
b = NULL;
}
}
private:
/** \brief
* internal used data
*/
/// Internal used data
SystemVector *b;
};
......
......@@ -30,6 +30,7 @@
#include "MatrixVector.h"
#include "DOFMatrix.h"
#include "OEMSolver.h"
#include "ProblemStat.h"
namespace AMDiS {
......@@ -37,27 +38,23 @@ namespace AMDiS {
* \ingroup Solver
*
* \brief
* Pure virtual base class for Newton, NewtonS and Banach which all
* solves non linear equation systems. Sub classes must implement the methods
* \ref init, \ref exit and \ref nlsolve.
* Pure virtual base class for specific non linear solvers.
*/
class NonLinSolver
{
public:
/** \brief
* constructor.
* \param name name of this solver
* Constructor
*
* \param name Name of this solver
*/
NonLinSolver(const std::string &name_,
OEMSolver *solver,
NonLinUpdater *updater)
: name(name_),
NonLinSolver(const std::string &name, OEMSolver *solver)
: name(name),
linSolver(solver),
nonLinUpdater(updater),
tolerance(1.e-4),
tolerance(1.e-8),
maxIter(50),
info(8),
initial_residual(0.0),
initialResidual(0.0),
residual(0.0),
usedNorm(NO_NORM)
{
......@@ -67,20 +64,22 @@ namespace AMDiS {
Parameters::get(name + "->norm", usedNorm);
}
/** \brief
* destructor
*/
/// Destructor
virtual ~NonLinSolver() {}
/** \brief
* solves the non linear system. Uses sub class methods
*/
inline int solve(SolverMatrix<Matrix<DOFMatrix*> >& mat,
SystemVector &x, SystemVector &rhs)
SystemVector &solution, SystemVector &rhs,
AdaptInfo *adaptInfo,
ProblemStat *prob)
{
init();
int result = nlsolve(mat, x, rhs);
solution.set(0.0);
int result = nlsolve(mat, solution, rhs, adaptInfo, prob);
exit();
return result;
}
......@@ -99,68 +98,63 @@ namespace AMDiS {
return linSolver;
}
inline void setNonLinUpdater(NonLinUpdater *up)
{
nonLinUpdater = up;
}
inline NonLinUpdater *getNonLinUpdater()
{
return nonLinUpdater;
}
protected:
/** \brief
* Allocates needed memory. Must be overriden in sub classes.
*/
/// Allocates needed memory. Must be overriden in sub classes.
virtual void init() = 0;
/** \brief
* Solves the non linear system. Must be overriden in sub classes.
*/
/// Solves the non linear system. Must be overriden in sub classes.
virtual int nlsolve(SolverMatrix<Matrix<DOFMatrix*> >& matVec,