/* $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& A, Vector& b, const Matrix* 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 LNorm(dim); Vector 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& A, Vector& b, const Matrix* pattern, Bool errorEstimatorCall) { int i, k, node; const int dim = elem.NoOfNodes(); Vector 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 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 nodes(dim); Vector 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& v, Vector* /*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); }