Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
NonLinLaplace_def.hpp
1#ifndef NonLinLaplace_def_hpp
2#define NonLinLaplace_def_hpp
3#include "NonLinLaplace_decl.hpp"
12
13namespace FEDD {
14template <class SC, class LO, class GO, class NO>
15NonLinLaplace<SC, LO, GO, NO>::NonLinLaplace(
16 const DomainConstPtr_Type &domain, std::string FEType,
17 ParameterListPtr_Type parameterList)
18 : NonLinearProblem<SC, LO, GO, NO>(parameterList, domain->getComm()),
19 u_rep_() {
20 this->nonLinearTolerance_ =
21 this->parameterList_->sublist("Parameter").get("relNonLinTol", 1.0e-6);
22 this->initNOXParameters();
23 this->addVariable(domain, FEType, "u", 1);
24 this->dim_ = this->getDomain(0)->getDimension();
25 u_rep_ = Teuchos::rcp(
26 new MultiVector_Type(this->getDomain(0)->getMapRepeated()));
27}
28
29template <class SC, class LO, class GO, class NO>
30NonLinLaplace<SC, LO, GO, NO>::~NonLinLaplace() {}
31
32template <class SC, class LO, class GO, class NO>
33void NonLinLaplace<SC, LO, GO, NO>::info() {
34 this->infoProblem();
35 this->infoNonlinProblem();
36}
37
38/*
39 * General assemble function that is called whenever assembly of any kind is
40 * required type specifies whether the residual or the Jacobian is needed
41 */
42template <class SC, class LO, class GO, class NO>
43void NonLinLaplace<SC, LO, GO, NO>::assemble(std::string type) const {
44 if (type == "") {
45 if (this->verbose_) {
46 std::cout << "-- Assembly nonlinear laplace ... " << std::flush;
47 }
48 this->initAssemble();
49 } else {
50 this->reAssemble(type);
51 }
52 if (this->verbose_) {
53 std::cout << "done -- " << std::endl;
54 }
55}
56
57/*
58 * Initial assembly of the system matrix (Jacobian)
59 */
60template <class SC, class LO, class GO, class NO>
61void NonLinLaplace<SC, LO, GO, NO>::initAssemble() const {
62
63 if (this->verbose_) {
64 std::cout << "-- Initial assembly " << std::flush;
65 }
66
67 if (this->system_.is_null())
68 this->system_.reset(new BlockMatrix_Type(1));
69
70 if (this->residualVec_.is_null())
71 this->residualVec_.reset(new BlockMultiVector_Type(1));
72
73 this->feFactory_->assemblyNonlinearLaplace(
74 this->dim_, this->getDomain(0)->getFEType(), 2, this->u_rep_,
75 this->system_, this->residualVec_, this->parameterList_, "Jacobian");
76
77 // Initialise solution to 1 everywhere
78 this->solution_->putScalar(1.);
79
80 if (this->verbose_) {
81 std::cout << "done -- " << std::endl;
82 }
83}
84
85/*
86 * Reassembly of the residual or Jacobian
87 * Required by the nonlinear solver
88 */
89template <class SC, class LO, class GO, class NO>
90void NonLinLaplace<SC, LO, GO, NO>::reAssemble(std::string type) const {
91
92 if (this->verbose_)
93 std::cout << "-- Reassembly nonlinear laplace"
94 << " (" << type << ") ... " << std::flush;
95 // Update the locally stored solution to the problem
96 MultiVectorConstPtr_Type u = this->solution_->getBlock(0);
97 this->u_rep_->importFromVector(u, true);
98
99 if (type == "Rhs") {
100
101 this->feFactory_->assemblyNonlinearLaplace(
102 this->dim_, this->getDomain(0)->getFEType(), 2, this->u_rep_,
103 this->system_, this->residualVec_, this->parameterList_, "Rhs");
104
105 } else if (type == "Newton") {
106
107 this->feFactory_->assemblyNonlinearLaplace(
108 this->dim_, this->getDomain(0)->getFEType(), 2, this->u_rep_,
109 this->system_, this->residualVec_, this->parameterList_,
110 "Jacobian");
111 }
112 if (this->verbose_)
113 std::cout << "done -- " << std::endl;
114}
115
116template <class SC, class LO, class GO, class NO>
117void NonLinLaplace<SC, LO, GO, NO>::reAssembleExtrapolation(
118 BlockMultiVectorPtrArray_Type previousSolutions) {
119
120 TEUCHOS_TEST_FOR_EXCEPTION(
121 true, std::logic_error,
122 "Only Newton/NOX implemented for nonlinear Laplace!");
123}
124
125/*
126 * Evaluation routine required by NOX
127 * Not tested for nonlinear Laplace
128 */
129template <class SC, class LO, class GO, class NO>
130void NonLinLaplace<SC, LO, GO, NO>::evalModelImpl(
131 const Thyra::ModelEvaluatorBase::InArgs<SC> &inArgs,
132 const Thyra::ModelEvaluatorBase::OutArgs<SC> &outArgs) const {
133 using Teuchos::Array;
134 using Teuchos::ArrayView;
135 using Teuchos::RCP;
136 using Teuchos::rcp;
137 using Teuchos::rcp_const_cast;
138 using Teuchos::rcp_dynamic_cast;
139
140 TEUCHOS_TEST_FOR_EXCEPTION(
141 this->solution_->getBlock(0)->getMap()->getUnderlyingLib() != "Tpetra",
142 std::runtime_error,
143 "Use of NOX only supports Tpetra. Epetra support must be implemented.");
144 RCP<Teuchos::FancyOStream> fancy =
145 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
146 TEUCHOS_TEST_FOR_EXCEPTION(inArgs.get_x().is_null(), std::logic_error,
147 "inArgs.get_x() is null.");
148
149 RCP<const Thyra::VectorBase<SC>> vecThyra = inArgs.get_x();
150 RCP<Teuchos::FancyOStream> out =
151 Teuchos::VerboseObjectBase::getDefaultOStream();
152
153 RCP<Thyra::VectorBase<SC>> vecThyraNonConst =
154 rcp_const_cast<Thyra::VectorBase<SC>>(vecThyra);
155
156 this->solution_->fromThyraMultiVector(vecThyraNonConst);
157
158 const RCP<Thyra::MultiVectorBase<SC>> f_out = outArgs.get_f();
159 const RCP<Thyra::LinearOpBase<SC>> W_out = outArgs.get_W_op();
160 const RCP<Thyra::PreconditionerBase<SC>> W_prec_out = outArgs.get_W_prec();
161
162 typedef Thyra::TpetraOperatorVectorExtraction<SC,LO,GO,NO> tpetra_extract;
163 typedef Tpetra::CrsMatrix<SC,LO,GO,NO> TpetraMatrix_Type;
164 typedef RCP<TpetraMatrix_Type> TpetraMatrixPtr_Type;
165 typedef RCP<const TpetraMatrix_Type> TpetraMatrixConstPtr_Type;
166
167 const bool fill_f = nonnull(f_out);
168 const bool fill_W = nonnull(W_out);
169 const bool fill_W_prec = nonnull(W_prec_out);
170
171 if (fill_f || fill_W || fill_W_prec) {
172
173 // ****************
174 // Get the underlying xpetra objects
175 // ****************
176 if (fill_f) {
177
178 this->calculateNonLinResidualVec("standard");
179
180 RCP<Thyra::MultiVectorBase<SC>> f_thyra =
181 this->getResidualVector()->getThyraMultiVector();
182 f_out->assign(*f_thyra);
183 }
184
185 TpetraMatrixPtr_Type W;
186 if (fill_W) {
187
188 this->reAssemble("Newton");
189
190 this->setBoundariesSystem();
191
192 Teuchos::RCP<TpetraOp_Type> W_tpetra = tpetra_extract::getTpetraOperator(W_out);
193 Teuchos::RCP<TpetraMatrix_Type> W_tpetraMat = Teuchos::rcp_dynamic_cast<TpetraMatrix_Type>(W_tpetra);
194
195 TpetraMatrixConstPtr_Type W_systemTpetra = this->getSystem()->getMergedMatrix()->getTpetraMatrix();
196 TpetraMatrixPtr_Type W_systemTpetraNonConst = rcp_const_cast<TpetraMatrix_Type>(W_systemTpetra);
197
198 //Tpetra::CrsMatrixWrap<SC,LO,GO,NO>& crsOp = dynamic_cast<Xpetra::CrsMatrixWrap<SC,LO,GO,NO>&>(*W_systemXpetraNonConst);
199 //Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>& xTpetraMat = dynamic_cast<Xpetra::TpetraCrsMatrix<SC,LO,GO,NO>&>(*crsOp.getCrsMatrix());
200
201 Teuchos::RCP<TpetraMatrix_Type> tpetraMatTpetra = W_systemTpetraNonConst; //xTpetraMat.getTpetra_CrsMatrixNonConst();
202
203 W_tpetraMat->resumeFill();
204
205 for (auto i=0; i<tpetraMatTpetra->getMap()->getLocalNumElements(); i++) {
206 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::local_inds_host_view_type indices; //ArrayView< const LO > indices
207 typename Tpetra::CrsMatrix<SC,LO,GO,NO>::values_host_view_type values;
208 tpetraMatTpetra->getLocalRowView( i, indices, values);
209 W_tpetraMat->replaceLocalValues( i, indices, values);
210 }
211 W_tpetraMat->fillComplete();
212 }
213
214 if (fill_W_prec) {
215 this->setupPreconditioner("Monolithic");
216
217 // ch 26.04.19: After each setup of the preconditioner we check if
218 // we use a two-level precondtioner with multiplicative combination
219 // between the levels. If this is the case, we need to pre apply the
220 // coarse level to the residual(f_out).
221
222 std::string levelCombination =
223 this->parameterList_->sublist("ThyraPreconditioner")
224 .sublist("Preconditioner Types")
225 .sublist("FROSch")
226 .get("Level Combination", "Additive");
227 if (!levelCombination.compare("Multiplicative")) {
228 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
229 "Multiplicative Level Combination "
230 "is not supported for NOX. In "
231 "general we need to pre-apply the "
232 "coarse problem. This must be "
233 "implemented here.");
234 }
235 }
236 }
237}
238
239/*
240 * Required by NOX
241 * Not tested for nonlinear Laplace
242 */
243template <class SC, class LO, class GO, class NO>
244Teuchos::RCP<Thyra::LinearOpBase<SC>>
245NonLinLaplace<SC, LO, GO, NO>::create_W_op() const {
246
247 Teuchos::RCP<const Thyra::LinearOpBase<SC>> W_opConst =
248 this->system_->getThyraLinOp();
249 Teuchos::RCP<Thyra::LinearOpBase<SC>> W_op =
250 Teuchos::rcp_const_cast<Thyra::LinearOpBase<SC>>(W_opConst);
251 return W_op;
252}
253
254/*
255 * Required by NOX
256 * Not tested for nonlinear Laplace
257 */
258template <class SC, class LO, class GO, class NO>
259Teuchos::RCP<Thyra::PreconditionerBase<SC>>
260NonLinLaplace<SC, LO, GO, NO>::create_W_prec() const {
261 this->initializeSolverBuilder();
262 this->initializePreconditioner();
263
264 Teuchos::RCP<const Thyra::PreconditionerBase<SC>> thyraPrec =
265 this->getPreconditionerConst()->getThyraPrecConst();
266 Teuchos::RCP<Thyra::PreconditionerBase<SC>> thyraPrecNonConst =
267 Teuchos::rcp_const_cast<Thyra::PreconditionerBase<SC>>(thyraPrec);
268
269 return thyraPrecNonConst;
270}
271
272/*
273 * Updates the residual vector by reassembling and applying boundary conditions
274 */
275template <class SC, class LO, class GO, class NO>
276void NonLinLaplace<SC, LO, GO, NO>::calculateNonLinResidualVec(
277 std::string type, double time) const {
278
279 this->reAssemble("Rhs");
280 // rhs_ contains the dirichlet boundary conditions
281 // Apparently so does bcFactory_. Not sure why both do.
282 if (!type.compare("standard")) {
283 // this = 1*this - 1*rhs
284 this->residualVec_->update(-1., *this->rhs_, 1.);
285 this->bcFactory_->setVectorMinusBC(this->residualVec_, this->solution_,
286 time);
287 } else if (!type.compare("reverse")) {
288 // this = -1*this + 1*rhs
289
290 this->residualVec_->update(1., *this->rhs_, -1.);
291
292 // Sets the residualVec_ at the boundary = boundary condition - solution
293 // Necessary since reAssemble("Rhs") only assembles the residual on
294 // internal nodes
295 this->bcFactory_->setBCMinusVector(this->residualVec_, this->solution_,
296 time);
297 } else {
298 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
299 "Unknown type for residual computation.");
300 }
301}
302} // namespace FEDD
303#endif
Definition NonLinearProblem_decl.hpp:24
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement.cpp:5