Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.1-cd005eec8 committed by Constantine Khrulev on 2025-03-07
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IPLogRelativeFunctional.cc
Go to the documentation of this file.
1// Copyright (C) 2012, 2014, 2015, 2016, 2017, 2020, 2022, 2023 David Maxwell
2//
3// This file is part of PISM.
4//
5// PISM is free software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the Free Software
7// Foundation; either version 3 of the License, or (at your option) any later
8// version.
9//
10// PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13// details.
14//
15// You should have received a copy of the GNU General Public License
16// along with PISM; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19#include "pism/inverse/functional/IPLogRelativeFunctional.hh"
20#include "pism/util/Grid.hh"
21#include "pism/util/array/Vector.hh"
22#include "pism/util/array/Scalar.hh"
23#include "pism/util/pism_utilities.hh"
24
25namespace pism {
26namespace inverse {
27
28//! Determine the normalization constant for the functional.
29/*! Sets the normalization constant \f$c_N\f$ so that
30\f[
31J(x)=1
32\f]
33if \f$|x| = \mathtt{scale}\f$ everywhere.
34*/
36
37 // The local value of the weights
38 double value = 0;
39
40 double scale_sq = scale*scale;
41
42 double w = 1.;
43
45
46 if (m_weights) {
47 list.add(*m_weights);
48 }
49
50 for (auto p = m_grid->points(); p; p.next()) {
51 const int i = p.i(), j = p.j();
52
53 Vector2d &u_obs_ij = m_u_observed(i, j);
54 if (m_weights) {
55 w = (*m_weights)(i, j);
56 }
57 double obsMagSq = (u_obs_ij.u*u_obs_ij.u + u_obs_ij.v*u_obs_ij.v) + m_eps*m_eps;
58 value += log(1 + w*scale_sq/obsMagSq);
59 }
60
61 m_normalization = GlobalSum(m_grid->com, value);
62}
63
65
66 // The value of the objective
67 double value = 0;
68
69 double w = 1;
70
72 if (m_weights) {
73 list.add(*m_weights);
74 }
75
76 for (auto p = m_grid->points(); p; p.next()) {
77 const int i = p.i(), j = p.j();
78
79 Vector2d &x_ij = x(i, j);
80 Vector2d &u_obs_ij = m_u_observed(i, j);
81 if (m_weights) {
82 w = (*m_weights)(i, j);
83 }
84 double obsMagSq = (u_obs_ij.u*u_obs_ij.u + u_obs_ij.v*u_obs_ij.v) + m_eps*m_eps;
85 value += log(1 + w*(x_ij.u*x_ij.u + x_ij.v*x_ij.v)/obsMagSq);
86 }
87
88 value /= m_normalization;
89
90 GlobalSum(m_grid->com, &value, OUTPUT, 1);
91}
92
94 gradient.set(0);
95
96 double w = 1;
97
98 array::AccessScope list{&x, &gradient, &m_u_observed};
99 if (m_weights) {
100 list.add(*m_weights);
101 }
102
103 for (auto p = m_grid->points(); p; p.next()) {
104 const int i = p.i(), j = p.j();
105
106 Vector2d &x_ij = x(i, j);
107 Vector2d &u_obs_ij = m_u_observed(i, j);
108 if (m_weights) {
109 w = (*m_weights)(i, j);
110 }
111 double obsMagSq = u_obs_ij.u*u_obs_ij.u + u_obs_ij.v*u_obs_ij.v + m_eps*m_eps;
112 double dJdxsq = w/(obsMagSq + w*(x_ij.u*x_ij.u + x_ij.v*x_ij.v));
113
114 gradient(i, j).u = dJdxsq*2*x_ij.u/m_normalization;
115 gradient(i, j).v = dJdxsq*2*x_ij.v/m_normalization;
116 }
117}
118
119} // end of namespace inverse
120} // end of namespace pism
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
Definition Vector2d.hh:29
void add(const PetscAccessible &v)
Definition Array.cc:896
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:65
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:629
std::shared_ptr< const Grid > m_grid
virtual void normalize(double scale)
Determine the normalization constant for the functional.
virtual void valueAt(array::Vector &x, double *OUTPUT)
Computes the value of the functional at the vector x.
virtual void gradientAt(array::Vector &x, array::Vector &gradient)
Computes the gradient of the functional at the vector x.
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)