/*
$Id: problemnl.cc,v 1.3 1996/10/08 07:53:02 roitzsch Exp $
(C)opyright 1996 by Konrad-Zuse-Center, Berlin
All rights reserved.
Part of the Kaskade distribution
*/
#include "problemnl.h"
#include "physics.h"
#include "nonlin.h"
#include "int.h"
#include "triang.h"
#include "elements.h"
#include "dirichlettr.h"
#include "materialstr.h"
#include "precondnl.h"
#include "cmdpars.h"
extern CmdPars Cmd;
//-------------------------------------------------------------------------
NonLinearProblem:: NonLinearProblem() : nonLinearity(0)
{
if (Cmd.isSet("Problem","Obstacle")) nonLinearity = new Obstacle();
else if (Cmd.isSet("Problem","Stefan")) nonLinearity = new Stefan();
else if (Cmd.isSet("Problem","Casting")) nonLinearity = new Casting();
else if (Cmd.isSet("Problem","PorousMedia"))nonLinearity = new PorousMedia();
if (nonLinearity == 0)
{
cout << "\n*** NonLinearProblem: no NonLinearity specified\n";
cout.flush(); abort();
}
}
//-------------------------------------------------------------------------
NonLinearProblem:: ~NonLinearProblem() { delete nonLinearity; }
//-------------------------------------------------------------------------
DirichletBCs* NonLinearProblem:: newDirichletBCs()
{
if (Cmd.isSet("DirichletBCs","ConstDirichlet"))
return new ConstDirichletBCs(fileName);
else if (Cmd.isSet("DirichletBCs","StefanDirichlet"))
return new StefanDirichletBCs();
else if (Cmd.isSet("DirichletBCs","CastingDirichlet"))
return new CastingDirichletBCs();
else if (Cmd.isSet("DirichletBCs","PorousMediaDirichlet"))
return new PorousMediaDirichletBCs();
else MissingParameter("DirichletBCs");
return 0;
}
//-------------------------------------------------------------------------
void NonLinearProblem:: newMaterial()
{
delete material;
if (Cmd.isSet("Material","DefaultMaterial"))
material = new DefaultMaterial(fileName, spaceDim);
else if (Cmd.isSet("Material","CastingMaterial"))
material = new CastingMaterial(fileName, spaceDim);
else if (Cmd.isSet("Material","StefanSource"))
material = new StefanSource(fileName, spaceDim);
else MissingParameter("Material");
}
//-------------------------------------------------------------------------
void NonLinearProblem:: newPreconditioner()
{
delete precond;
if (Cmd.isSet("precond","NonLinSGGS"))
precond = new NonLinearSGGS(*nonLinearity);
else if (Cmd.isSet("precond","NonLinMLGS"))
precond = new NonLinearMLGS(*nonLinearity);
else if (Cmd.isSet("precond","TrcNonLinMLGS"))
precond = new TrcNonLinearMLGS(*nonLinearity);
else MissingParameter("Non-Linear Preconditioner");
}
//-------------------------------------------------------------------------
void NonLinearProblem:: assembleGlobal(Real time0)
{
nonLinearity->update(*interface);
Problem::assembleGlobal(time0);
};
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void StaticNonLinearProblem:: assemble(const Element& elem, const PATCH& t,
const Jacobian& Jac, Matrix<Num>& A,
Vector<Num>& b,
const Matrix<Bool>* pattern,
Bool errorEstimatorCall)
{
int i;
if (!elem.assembleEllip(t,A,Jac,pattern)) missingMaterialTerm("elliptic",
t.Class());
elem.assembleMass(t,A,Jac,pattern);
elem.assembleSource(t,b,Jac,pattern);
if (t.onBoundary())
{
elem.assembleCauchyBCs(t,A,b,pattern);
elem.assembleNeumannBCs(t,b,pattern);
}
if (Mesh()->innerBoundary) elem.assembleInnerBCs(t,b,pattern);
//if (Cmd.isTrue("innerBoundary")) elem.assembleInnerBCs(t,b,pattern);
// -- assemble area weights for non-linear contributions:
if (!errorEstimatorCall) // if not called by error estimator
{
const int dim = elem.NoOfNodes();
Vector<Real> LNorm(dim);
Vector<int> nodes(dim);
FORALL(LNorm,i) LNorm[i] = 0.0;
elem.assembleLNorm(t,LNorm,Jac,pattern);
interface->getGlobalNodes(&t,nodes);
nonLinearity->addAreaWeight(LNorm,nodes);
}
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void TransientNonLinearProblem:: assembleGlobal(Real time0)
{
uPrevOnNewMesh.resize(1,interface->Dim());
solutionToNewMesh(uPrevOnNewMesh);
nonLinearity->update(*interface);
Problem::assembleGlobal(time0);
};
//-------------------------------------------------------------------------
void TransientNonLinearProblem:: assemble(const Element& elem, const PATCH& t,
const Jacobian& Jac, Matrix<Num>& A,
Vector<Num>& b,
const Matrix<Bool>* pattern,
Bool errorEstimatorCall)
{
int i, k, node;
const int dim = elem.NoOfNodes();
Vector<Num> s(dim);
// -- the stiffness matrix:
if (!elem.assembleEllip(t,A,Jac,pattern)) missingMaterialTerm("elliptic",
t.Class());
for (i=1; i<=dim; ++i)
for (k=1; k<=i; ++k) A(i,k) = tau*A(i,k);
// -- source term and boundary conditions:
for (i=1; i<=dim; ++i) s[i] = 0.0;
Bool update;
update = elem.assembleSource(t,s,Jac,pattern,time);
if (t.onBoundary())
update = update || elem.assembleNeumannBCs(t,s,pattern,time);
if (update) FORALL(b,i) b[i] += tau*s[i];
if (t.onBoundary())
{
Matrix<Num> M(dim,dim);
for (i=1; i<=dim; ++i)
{
s[i] = 0.0;
for (k=1; k<=i; ++k) M(i,k) = 0.0;
}
if (elem.assembleCauchyBCs(t,M,s,pattern,time))
{
for (i=1; i<=dim; ++i)
{
b[i] += tau*s[i];
for (k=1; k<=i; ++k) A(i,k) += tau*M(i,k);
}
}
}
if (!errorEstimatorCall)
{
Vector<int> nodes(dim);
Vector<Real> LNorm(dim);
// -- area weights for non-linear contributions:
FORALL(LNorm,i) LNorm[i] = 0.0;
elem.assembleLNorm(t,LNorm,Jac,pattern);
interface->getGlobalNodes(&t,nodes);
nonLinearity->addAreaWeight(LNorm,nodes);
// -- the contribution of the previous step to the right-hand-side:
for (i=1; i<=dim; ++i)
{
node = nodes[i];
b[i] += LNorm[i] * nonLinearity->HValue(node,uPrevOnNewMesh[node]);
}
}
}
//-------------------------------------------------------------------------
Real TransientNonLinearProblem:: compUNorm(Vector<Num>& v, Vector<Num>* /*MDiag*/)
{
int i;
Real minU = ::real(v[1]);
FORALL(v,i) { if (::real(v[1]) < minU) minU = ::real(v[1]); }
FORALL(v,i) v[i] -= minU;
Real UNorm = 0.0;
UNorm = 2.0*EllipticNorm(v);
FORALL(v,i) v[i] += minU;
return sqrt(UNorm);
}
syntax highlighted by Code2HTML, v. 0.9.1