fvbasefdlocallinearizer.hh
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2008-2013 by Andreas Lauser
5  Copyright (C) 2011-2012 by Bernd Flemisch
6  Copyright (C) 2011 by Klaus Mosthaf
7 
8  This file is part of the Open Porous Media project (OPM).
9 
10  OPM is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 2 of the License, or
13  (at your option) any later version.
14 
15  OPM is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with OPM. If not, see <http://www.gnu.org/licenses/>.
22 */
28 #ifndef EWOMS_FV_BASE_FD_LOCAL_LINEARIZER_HH
29 #define EWOMS_FV_BASE_FD_LOCAL_LINEARIZER_HH
30 
33 
34 #include <opm/material/common/MathToolbox.hpp>
35 #include <opm/material/common/Valgrind.hpp>
36 
37 #include <dune/istl/bvector.hh>
38 #include <dune/istl/matrix.hh>
39 
40 #include <dune/common/fvector.hh>
41 #include <dune/common/fmatrix.hh>
42 
43 namespace Ewoms {
44 // forward declaration
45 template<class TypeTag>
47 
48 namespace Properties {
49 // declare the property tags required for the finite differences local linearizer
50 NEW_TYPE_TAG(FiniteDifferenceLocalLinearizer);
51 
52 NEW_PROP_TAG(LocalLinearizer);
53 NEW_PROP_TAG(Evaluation);
54 NEW_PROP_TAG(NumericDifferenceMethod);
55 NEW_PROP_TAG(BaseEpsilon);
56 
57 NEW_PROP_TAG(LocalResidual);
59 NEW_PROP_TAG(Problem);
60 NEW_PROP_TAG(Model);
61 NEW_PROP_TAG(PrimaryVariables);
62 NEW_PROP_TAG(ElementContext);
63 NEW_PROP_TAG(Scalar);
64 NEW_PROP_TAG(Evaluation);
65 NEW_PROP_TAG(GridView);
66 NEW_PROP_TAG(NumEq);
67 
68 // set the properties to be spliced in
69 SET_TYPE_PROP(FiniteDifferenceLocalLinearizer, LocalLinearizer,
71 
72 SET_TYPE_PROP(FiniteDifferenceLocalLinearizer, Evaluation,
73  typename GET_PROP_TYPE(TypeTag, Scalar));
74 
82 SET_INT_PROP(FiniteDifferenceLocalLinearizer, NumericDifferenceMethod, +1);
83 
85 SET_SCALAR_PROP(FiniteDifferenceLocalLinearizer, BaseEpsilon, 0.9123e-10);
86 }
87 
124 template<class TypeTag>
126 {
127 private:
128  typedef typename GET_PROP_TYPE(TypeTag, LocalLinearizer) Implementation;
129  typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) LocalResidual;
130  typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
131  typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
132  typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
133  typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
134  typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
135  typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
136  typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
137  typedef typename GridView::template Codim<0>::Entity Element;
138 
139  enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
140  typedef Dune::FieldMatrix<Scalar, numEq, numEq> MatrixBlock;
141  typedef Dune::Matrix<MatrixBlock> LocalBlockMatrix;
142 
143  typedef Dune::FieldVector<Scalar, numEq> VectorBlock;
144  typedef Dune::BlockVector<VectorBlock> LocalBlockVector;
145  typedef Dune::BlockVector<MatrixBlock> LocalStorageMatrix;
146 
147 #if __GNUC__ == 4 && __GNUC_MINOR__ <= 6
148 public:
149  // make older GCCs happy by providing a public copy constructor (this is necessary
150  // for their implementation of std::vector, although the method is never called...)
153  {}
154 
155 #else
156  // copying local residual objects around is a very bad idea, so we explicitly prevent
157  // it...
159 #endif
160 public:
163  { }
164 
166  { delete internalElemContext_; }
167 
171  static void registerParameters()
172  {
173  EWOMS_REGISTER_PARAM(TypeTag, int, NumericDifferenceMethod,
174  "The method used for numeric differentiation (-1: backward "
175  "differences, 0: central differences, 1: forward differences)");
176  }
177 
186  void init(Simulator &simulator)
187  {
188  simulatorPtr_ = &simulator;
189  delete internalElemContext_;
190  internalElemContext_ = new ElementContext(simulator);
191  }
192 
204  void linearize(const Element &element)
205  {
206  internalElemContext_->updateAll(element);
207 
209  }
210 
225  void linearize(ElementContext &elemCtx)
226  {
227  // update the weights of the primary variables for the context
228  model_().updatePVWeights(elemCtx);
229 
230  resize_(elemCtx);
231  reset_(elemCtx);
232 
233  // calculate the local residual
234  localResidual_.eval(residual_, residualStorage_, elemCtx);
235 
236  // calculate the local jacobian matrix
237  int numPrimaryDof = elemCtx.numPrimaryDof(/*timeIdx=*/0);
238  for (int dofIdx = 0; dofIdx < numPrimaryDof; dofIdx++) {
239  for (int pvIdx = 0; pvIdx < numEq; pvIdx++) {
240  asImp_().evalPartialDerivative_(elemCtx, dofIdx, pvIdx);
241 
242  // incorporate the partial derivatives into the local Jacobian matrix
243  updateLocalLinearizer_(elemCtx, dofIdx, pvIdx);
244  }
245  }
246  }
247 
252  static Scalar baseEpsilon()
253  { return GET_PROP_VALUE(TypeTag, BaseEpsilon); }
254 
266  Scalar numericEpsilon(const ElementContext &elemCtx,
267  int dofIdx,
268  int pvIdx) const
269  {
270  int globalIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
271  Scalar pvWeight = elemCtx.model().primaryVarWeight(globalIdx, pvIdx);
272  assert(pvWeight > 0 && std::isfinite(pvWeight));
273  Valgrind::CheckDefined(pvWeight);
274 
275  return baseEpsilon()/pvWeight;
276  }
277 
281  LocalResidual &localResidual()
282  { return localResidual_; }
283 
287  const LocalResidual &localResidual() const
288  { return localResidual_; }
289 
298  const MatrixBlock &jacobian(int domainScvIdx, int rangeScvIdx) const
299  { return jacobian_[domainScvIdx][rangeScvIdx]; }
300 
306  const MatrixBlock &jacobianStorage(int dofIdx) const
307  { return jacobianStorage_[dofIdx]; }
308 
314  const VectorBlock &residual(int dofIdx) const
315  { return residual_[dofIdx]; }
316 
322  const VectorBlock &residualStorage(int dofIdx) const
323  { return residualStorage_[dofIdx]; }
324 
325 protected:
326  Implementation &asImp_()
327  { return *static_cast<Implementation*>(this); }
328  const Implementation &asImp_() const
329  { return *static_cast<const Implementation*>(this); }
330 
331  const Simulator &simulator_() const
332  { return *simulatorPtr_; }
333  const Problem &problem_() const
334  { return simulatorPtr_->problem(); }
335  const Model &model_() const
336  { return simulatorPtr_->model(); }
337 
342  { return EWOMS_GET_PARAM(TypeTag, int, NumericDifferenceMethod); }
343 
348  void resize_(const ElementContext &elemCtx)
349  {
350  int numDof = elemCtx.numDof(/*timeIdx=*/0);
351  int numPrimaryDof = elemCtx.numPrimaryDof(/*timeIdx=*/0);
352 
353  jacobian_.setSize(numDof, numPrimaryDof);
354  jacobianStorage_.resize(numPrimaryDof);
355 
356  residual_.resize(numDof);
357  residualStorage_.resize(numPrimaryDof);
358 
359  derivResidual_.resize(numDof);
360  derivStorage_.resize(numPrimaryDof);
361  }
362 
366  void reset_(const ElementContext &elemCtx)
367  {
368  int numDof = elemCtx.numDof(/*timeIdx=*/0);
369  int numPrimaryDof = elemCtx.numPrimaryDof(/*timeIdx=*/0);
370  for (int primaryDofIdx = 0; primaryDofIdx < numPrimaryDof; ++ primaryDofIdx) {
371  residualStorage_[primaryDofIdx] = 0.0;
372 
373  jacobianStorage_[primaryDofIdx] = 0.0;
374  for (int dof2Idx = 0; dof2Idx < numDof; ++ dof2Idx) {
375  jacobian_[dof2Idx][primaryDofIdx] = 0.0;
376  }
377  }
378 
379  for (int primaryDofIdx = 0; primaryDofIdx < numDof; ++ primaryDofIdx)
380  residual_[primaryDofIdx] = 0.0;
381  }
382 
425  void evalPartialDerivative_(ElementContext &elemCtx,
426  int dofIdx,
427  int pvIdx)
428  {
429  // save all quantities which depend on the specified primary
430  // variable at the given sub control volume
431  elemCtx.saveIntensiveQuantities(dofIdx);
432 
433  PrimaryVariables priVars(elemCtx.primaryVars(dofIdx, /*timeIdx=*/0));
434  Scalar eps = asImp_().numericEpsilon(elemCtx, dofIdx, pvIdx);
435  Scalar delta = 0;
436 
437  if (numericDifferenceMethod_() >= 0) {
438  // we are not using backward differences, i.e. we need to
439  // calculate f(x + \epsilon)
440 
441  // deflect primary variables
442  priVars[pvIdx] += eps;
443  delta += eps;
444 
445  // calculate the residual
446  elemCtx.updateIntensiveQuantities(priVars, dofIdx, /*timeIdx=*/0);
447  elemCtx.updateAllExtensiveQuantities();
449  }
450  else {
451  // we are using backward differences, i.e. we don't need
452  // to calculate f(x + \epsilon) and we can recycle the
453  // (already calculated) residual f(x)
456  }
457 
458  if (numericDifferenceMethod_() <= 0) {
459  // we are not using forward differences, i.e. we don't
460  // need to calculate f(x - \epsilon)
461 
462  // deflect the primary variables
463  priVars[pvIdx] -= delta + eps;
464  delta += eps;
465 
466  // calculate residual again, this time we use the local
467  // residual's internal storage.
468  elemCtx.updateIntensiveQuantities(priVars, dofIdx, /*timeIdx=*/0);
469  elemCtx.updateAllExtensiveQuantities();
470  localResidual_.eval(elemCtx);
471 
472  derivResidual_ -= localResidual_.residual();
473  derivStorage_ -= localResidual_.storageTerm();
474  }
475  else {
476  // we are using forward differences, i.e. we don't need to
477  // calculate f(x - \epsilon) and we can recycle the
478  // (already calculated) residual f(x)
481  }
482 
483  assert(delta > 0);
484 
485  // divide difference in residuals by the magnitude of the
486  // deflections between the two function evaluation
487  derivResidual_ /= delta;
488  derivStorage_ /= delta;
489 
490  // restore the original state of the element's volume
491  // variables
492  elemCtx.restoreIntensiveQuantities(dofIdx);
493 
494 #ifndef NDEBUG
495  for (unsigned i = 0; i < derivResidual_.size(); ++i)
496  Valgrind::CheckDefined(derivResidual_[i]);
497 #endif
498  }
499 
505  void updateLocalLinearizer_(const ElementContext &elemCtx,
506  int primaryDofIdx,
507  int pvIdx)
508  {
509  // store the derivative of the storage term
510  for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
511  jacobianStorage_[primaryDofIdx][eqIdx][pvIdx] = derivStorage_[primaryDofIdx][eqIdx];
512 
513  int numDof = elemCtx.numDof(/*timeIdx=*/0);
514  for (int dofIdx = 0; dofIdx < numDof; dofIdx++)
515  {
516  for (int eqIdx = 0; eqIdx < numEq; eqIdx++) {
517  // A[dofIdx][primaryDofIdx][eqIdx][pvIdx] is the partial derivative of
518  // the residual function 'eqIdx' for the degree of freedom 'dofIdx' with
519  // regard to the primary variable 'pvIdx' of the degree of freedom
520  // 'primaryDofIdx'
521  jacobian_[dofIdx][primaryDofIdx][eqIdx][pvIdx] = derivResidual_[dofIdx][eqIdx];
522  Valgrind::CheckDefined(jacobian_[dofIdx][primaryDofIdx][eqIdx][pvIdx]);
523  }
524  }
525  }
526 
528  Model *modelPtr_;
529 
530  ElementContext *internalElemContext_;
531 
532  LocalBlockMatrix jacobian_;
533  LocalStorageMatrix jacobianStorage_;
534 
535  LocalBlockVector residual_;
536  LocalBlockVector residualStorage_;
537 
538  LocalBlockVector derivResidual_;
539  LocalBlockVector derivStorage_;
540 
541  LocalResidual localResidual_;
542 };
543 
544 } // namespace Ewoms
545 
546 #endif
void updateLocalLinearizer_(const ElementContext &elemCtx, int primaryDofIdx, int pvIdx)
Updates the current local Jacobian matrix with the partial derivatives of all equations in regard to ...
Definition: fvbasefdlocallinearizer.hh:505
const MatrixBlock & jacobianStorage(int dofIdx) const
Returns the local Jacobian matrix the storage term of a sub-control volume.
Definition: fvbasefdlocallinearizer.hh:306
const VectorBlock & residualStorage(int dofIdx) const
Returns the local storage term of a sub-control volume.
Definition: fvbasefdlocallinearizer.hh:322
const Model & model_() const
Definition: fvbasefdlocallinearizer.hh:335
LocalBlockVector residual_
Definition: fvbasefdlocallinearizer.hh:535
const Problem & problem_() const
Definition: fvbasefdlocallinearizer.hh:333
FvBaseFdLocalLinearizer()
Definition: fvbasefdlocallinearizer.hh:161
Implementation & asImp_()
Definition: fvbasefdlocallinearizer.hh:326
SET_SCALAR_PROP(NumericModel, EndTime,-1e100)
The default value for the simulation's end time.
Problem & problem()
Return the object which specifies the pysical setup of the simulation.
Definition: simulator.hh:189
void resize_(const ElementContext &elemCtx)
Resize all internal attributes to the size of the element.
Definition: fvbasefdlocallinearizer.hh:348
LocalBlockVector residualStorage_
Definition: fvbasefdlocallinearizer.hh:536
#define GET_PROP_VALUE(TypeTag, PropTagName)
Access the value attribute of a property for a type tag.
Definition: propertysystem.hh:468
Model * modelPtr_
Definition: fvbasefdlocallinearizer.hh:528
static Scalar baseEpsilon()
Returns the unweighted epsilon value used to calculate the local derivatives.
Definition: fvbasefdlocallinearizer.hh:252
LocalResidual localResidual_
Definition: fvbasefdlocallinearizer.hh:541
#define GET_PROP_TYPE(TypeTag, PropTagName)
Access the type attribute of a property for a type tag.
Definition: propertysystem.hh:485
LocalBlockVector derivStorage_
Definition: fvbasefdlocallinearizer.hh:539
void linearize(const Element &element)
Compute an element's local Jacobian matrix and evaluate its residual.
Definition: fvbasefdlocallinearizer.hh:204
SET_INT_PROP(NumericModel, GridGlobalRefinements, 0)
const MatrixBlock & jacobian(int domainScvIdx, int rangeScvIdx) const
Returns the local Jacobian matrix of the residual of a sub-control volume.
Definition: fvbasefdlocallinearizer.hh:298
const VectorBlock & residual(int dofIdx) const
Returns the local residual of a sub-control volume.
Definition: fvbasefdlocallinearizer.hh:314
NEW_PROP_TAG(Grid)
The type of the DUNE grid.
This file provides the infrastructure to retrieve run-time parameters.
LocalResidual & localResidual()
Return reference to the local residual.
Definition: fvbasefdlocallinearizer.hh:281
SET_TYPE_PROP(NumericModel, Scalar, double)
Set the default type of scalar values to double.
Calculates the Jacobian of the local residual for finite volume spatial discretizations using a finit...
Definition: fvbasefdlocallinearizer.hh:46
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:73
ElementContext * internalElemContext_
Definition: fvbasefdlocallinearizer.hh:530
Definition: baseauxiliarymodule.hh:35
const LocalResidual & localResidual() const
Return reference to the local residual.
Definition: fvbasefdlocallinearizer.hh:287
const Simulator & simulator_() const
Definition: fvbasefdlocallinearizer.hh:331
static int numericDifferenceMethod_()
Returns the numeric difference method which is applied.
Definition: fvbasefdlocallinearizer.hh:341
#define EWOMS_REGISTER_PARAM(TypeTag, ParamType, ParamName, Description)
Register a run-time parameter.
Definition: parametersystem.hh:64
LocalBlockMatrix jacobian_
Definition: fvbasefdlocallinearizer.hh:532
void reset_(const ElementContext &elemCtx)
Reset the all relevant internal attributes to 0.
Definition: fvbasefdlocallinearizer.hh:366
Scalar numericEpsilon(const ElementContext &elemCtx, int dofIdx, int pvIdx) const
Returns the epsilon value which is added and removed from the current solution.
Definition: fvbasefdlocallinearizer.hh:266
void evalPartialDerivative_(ElementContext &elemCtx, int dofIdx, int pvIdx)
Compute the partial derivatives of a context's residual functions.
Definition: fvbasefdlocallinearizer.hh:425
LocalStorageMatrix jacobianStorage_
Definition: fvbasefdlocallinearizer.hh:533
Model & model()
Return the physical model used in the simulation.
Definition: simulator.hh:176
static void registerParameters()
Register all run-time parameters for the local jacobian.
Definition: fvbasefdlocallinearizer.hh:171
Simulator * simulatorPtr_
Definition: fvbasefdlocallinearizer.hh:527
NEW_TYPE_TAG(AuxModule)
Provides the magic behind the eWoms property system.
void init(Simulator &simulator)
Initialize the local Jacobian object.
Definition: fvbasefdlocallinearizer.hh:186
void linearize(ElementContext &elemCtx)
Compute an element's local Jacobian matrix and evaluate its residual.
Definition: fvbasefdlocallinearizer.hh:225
const Implementation & asImp_() const
Definition: fvbasefdlocallinearizer.hh:328
~FvBaseFdLocalLinearizer()
Definition: fvbasefdlocallinearizer.hh:165
#define EWOMS_GET_PARAM(TypeTag, ParamType, ParamName)
Retrieve a runtime parameter.
Definition: parametersystem.hh:95
LocalBlockVector derivResidual_
Definition: fvbasefdlocallinearizer.hh:538