Skip to content
Snippets Groups Projects
Commit 99a07e46 authored by Elias Pipping's avatar Elias Pipping Committed by Elias Pipping
Browse files

Move nonlinearity-related code to the nonlinearity class

parent f5f7bb37
No related branches found
No related tags found
No related merge requests found
...@@ -22,10 +22,12 @@ class MyNonlinearity { ...@@ -22,10 +22,12 @@ class MyNonlinearity {
typedef SmallVector VectorType; typedef SmallVector VectorType;
typedef SmallMatrix MatrixType; typedef SmallMatrix MatrixType;
double operator()(VectorType const x) const { return func_(x.two_norm()); }
// directional subdifferential: at u on the line u + t*v // directional subdifferential: at u on the line u + t*v
// u and v are assumed to be non-zero // u and v are assumed to be non-zero
void directionalSubDiff(VectorType const u, VectorType const v, void directionalSubDiff(VectorType const u, VectorType const v,
Interval<double>& D) const { Interval<double> &D) const {
if (u == SmallVector(0.0)) { if (u == SmallVector(0.0)) {
D[0] = D[1] = func_.rightDifferential(0); D[0] = D[1] = func_.rightDifferential(0);
return; return;
...@@ -42,8 +44,18 @@ class MyNonlinearity { ...@@ -42,8 +44,18 @@ class MyNonlinearity {
} }
} }
void directionalDomain(const VectorType&, const VectorType&, void upperGradient(const SmallVector x, SmallVector &ret) const {
Interval<double>& dom) const { ret = x;
ret *= func_.rightDifferential(x.two_norm()) / x.two_norm();
}
void lowerGradient(const SmallVector x, SmallVector &ret) const {
ret = x;
ret *= func_.leftDifferential(x.two_norm()) / x.two_norm();
}
void directionalDomain(const VectorType &, const VectorType &,
Interval<double> &dom) const {
dom[0] = std::numeric_limits<double>::min(); dom[0] = std::numeric_limits<double>::min();
dom[1] = std::numeric_limits<double>::max(); dom[1] = std::numeric_limits<double>::max();
} }
......
...@@ -21,25 +21,28 @@ class SampleFunctional { ...@@ -21,25 +21,28 @@ class SampleFunctional {
typedef Dune::FieldMatrix<double, dimension, dimension> SmallMatrix; typedef Dune::FieldMatrix<double, dimension, dimension> SmallMatrix;
typedef Function FunctionType; typedef Function FunctionType;
SampleFunctional(SmallMatrix _A, SmallVector _b) : A(_A), b(_b), func_() {} typedef MyNonlinearity<dimension, Function> NonlinearityType;
SampleFunctional(SmallMatrix _A, SmallVector _b) : A(_A), b(_b) {}
double operator()(const SmallVector v) const { double operator()(const SmallVector v) const {
SmallVector y; SmallVector y;
A.mv(v, y); // y = Av A.mv(v, y); // y = Av
y /= 2; // y = 1/2 Av y /= 2; // y = 1/2 Av
y -= b; // y = 1/2 Av - b y -= b; // y = 1/2 Av - b
return y * v + func_(v.two_norm()); // <1/2 Av - b,v> + H(|v|) return y * v + phi_(v); // <1/2 Av - b,v> + H(|v|)
} }
void descentDirection(const SmallVector x, SmallVector &ret) const { void descentDirection(const SmallVector x, SmallVector &ret) const {
if (x == SmallVector(0.0)) { if (x == SmallVector(0.0)) {
// If there is a direction of descent, this is it
SmallVector const d = smoothGradient(x); SmallVector const d = smoothGradient(x);
// Decline of the smooth part in the negative gradient direction Interval<double> D;
double smoothDecline = -(d * d); phi_.directionalSubDiff(x, d, D);
double nonlinearDecline = double const nonlinearDecline = D[1];
func_.rightDifferential(0.0) * d.two_norm(); // TODO: is this correct? double const smoothDecline = -(d * d);
double combinedDecline = smoothDecline + nonlinearDecline; double const combinedDecline = smoothDecline + nonlinearDecline;
if (combinedDecline < 0) { if (combinedDecline < 0) {
ret = d; ret = d;
...@@ -82,7 +85,7 @@ class SampleFunctional { ...@@ -82,7 +85,7 @@ class SampleFunctional {
SmallVector b; SmallVector b;
private: private:
Function func_; NonlinearityType phi_;
// Gradient of the smooth part // Gradient of the smooth part
SmallVector smoothGradient(const SmallVector x) const { SmallVector smoothGradient(const SmallVector x) const {
...@@ -93,14 +96,16 @@ class SampleFunctional { ...@@ -93,14 +96,16 @@ class SampleFunctional {
} }
SmallVector upperGradient(const SmallVector x) const { SmallVector upperGradient(const SmallVector x) const {
SmallVector y = smoothGradient(x); SmallVector y;
y.axpy(func_.rightDifferential(x.two_norm()) / x.two_norm(), x); phi_.upperGradient(x, y);
y += smoothGradient(x);
return y; return y;
} }
SmallVector lowerGradient(const SmallVector x) const { SmallVector lowerGradient(const SmallVector x) const {
SmallVector y = smoothGradient(x); SmallVector y;
y.axpy(func_.leftDifferential(x.two_norm()) / x.two_norm(), x); phi_.lowerGradient(x, y);
y += smoothGradient(x);
return y; return y;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment