PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
IPMeanSquareFunctional.cc
Go to the documentation of this file.
1// Copyright (C) 2012, 2014, 2015, 2016, 2017, 2020, 2022, 2023, 2025 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/IPMeanSquareFunctional.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//! Implicitly set the normalization constant for the functional.
29/*! The normalization constant is selected so that if an input
30array::Vector has component vectors all of length \a scale, then the funtional value will be 1. I.e.
31\f[
32c_N^{-1} = \sum_{i} w_i {\tt scale}^2.
33\f]*/
35
36 // The local value of the weights
37 double value = 0;
38
39 if (m_weights != nullptr) {
41
42 for (auto p : m_grid->points()) {
43 const int i = p.i(), j = p.j();
44
45 value += (*m_weights)(i, j);
46 }
47 } else {
48 for (auto p : m_grid->points()) {
49 (void) p;
50 value += 1;
51 }
52 }
53
54 m_normalization = GlobalSum(m_grid->com, value);
55 m_normalization *= (scale*scale);
56}
57
59
60 // The value of the objective
61 double value = 0;
62
63 array::AccessScope list{&x};
64
65 if (m_weights != nullptr) {
66 list.add(*m_weights);
67 for (auto p : m_grid->points()) {
68 const int i = p.i(), j = p.j();
69
70 Vector2d &x_ij = x(i, j);
71 value += (x_ij.u*x_ij.u + x_ij.v*x_ij.v)*(*m_weights)(i, j);
72 }
73 } else {
74 for (auto p : m_grid->points()) {
75 const int i = p.i(), j = p.j();
76
77 Vector2d &x_ij = x(i, j);
78 value += (x_ij.u*x_ij.u + x_ij.v*x_ij.v);
79 }
80 }
81 value /= m_normalization;
82
83 GlobalSum( m_grid->com, &value, OUTPUT, 1);
84}
85
87
88 // The value of the objective
89 double value = 0;
90
91 array::AccessScope list{&a, &b};
92
93 if (m_weights) {
94 list.add(*m_weights);
95 for (auto p : m_grid->points()) {
96 const int i = p.i(), j = p.j();
97
98 Vector2d &a_ij = a(i, j);
99 Vector2d &b_ij = b(i, j);
100 value += (a_ij.u*b_ij.u + a_ij.v*b_ij.v)*(*m_weights)(i, j);
101 }
102 } else {
103 for (auto p : m_grid->points()) {
104 const int i = p.i(), j = p.j();
105
106 Vector2d &a_ij = a(i, j);
107 Vector2d &b_ij = b(i, j);
108 value += (a_ij.u*b_ij.u + a_ij.v*b_ij.v);
109 }
110 }
111 value /= m_normalization;
112
113 GlobalSum( m_grid->com, &value, OUTPUT, 1);
114}
115
117 gradient.set(0);
118
119 array::AccessScope list{&x, &gradient};
120
121 if (m_weights) {
122 list.add(*m_weights);
123 for (auto p : m_grid->points()) {
124 const int i = p.i(), j = p.j();
125
126 gradient(i, j).u = 2*x(i, j).u*(*m_weights)(i, j) / m_normalization;
127 gradient(i, j).v = 2*x(i, j).v*(*m_weights)(i, j) / m_normalization;
128 }
129 } else {
130 for (auto p : m_grid->points()) {
131 const int i = p.i(), j = p.j();
132
133 gradient(i, j).u = 2*x(i, j).u / m_normalization;
134 gradient(i, j).v = 2*x(i, j).v / m_normalization;
135 }
136 }
137}
138
139//! Implicitly set the normalization constant for the functional.
140/*! The normalization constant is selected so that if an input
141array::Scalar has entries all equal to \a scale, then the funtional value will be 1. I.e.
142\f[
143c_N^{-1} = \sum_{i} w_i {\tt scale}^2.
144\f]*/
146
147 // The local value of the weights
148 double value = 0;
149
150 if (m_weights != nullptr) {
152 for (auto p : m_grid->points()) {
153 const int i = p.i(), j = p.j();
154
155 value += (*m_weights)(i, j);
156 }
157 } else {
158 for (auto p : m_grid->points()) {
159 (void) p;
160 value += 1;
161 }
162 }
163
164 m_normalization = GlobalSum(m_grid->com, value);
165 m_normalization *= (scale*scale);
166}
167
169
170 // The value of the objective
171 double value = 0;
172
173 array::AccessScope list(x);
174
175 if (m_weights != nullptr) {
176 list.add(*m_weights);
177 for (auto p : m_grid->points()) {
178 const int i = p.i(), j = p.j();
179
180 double &x_ij = x(i, j);
181 value += x_ij*x_ij*(*m_weights)(i, j);
182 }
183 } else {
184 for (auto p : m_grid->points()) {
185 const int i = p.i(), j = p.j();
186
187 double &x_ij = x(i, j);
188 value += x_ij*x_ij;
189 }
190 }
191 value /= m_normalization;
192
193 GlobalSum(m_grid->com, &value, OUTPUT, 1);
194}
195
197
198 // The value of the objective
199 double value = 0;
200
201 array::AccessScope list{&a, &b};
202
203 if (m_weights) {
204 list.add(*m_weights);
205 for (auto p : m_grid->points()) {
206 const int i = p.i(), j = p.j();
207
208 value += (a(i, j)*b(i, j))*(*m_weights)(i, j);
209 }
210 } else {
211 for (auto p : m_grid->points()) {
212 const int i = p.i(), j = p.j();
213
214 value += (a(i, j)*b(i, j));
215 }
216 }
217 value /= m_normalization;
218
219 GlobalSum(m_grid->com, &value, OUTPUT, 1);
220}
221
222
224 gradient.set(0);
225
226 array::AccessScope list{&x, &gradient};
227
228 if (m_weights) {
229 list.add(*m_weights);
230 for (auto p : m_grid->points()) {
231 const int i = p.i(), j = p.j();
232
233 gradient(i, j) = 2*x(i, j)*(*m_weights)(i, j) / m_normalization;
234 }
235 } else {
236 for (auto p : m_grid->points()) {
237 const int i = p.i(), j = p.j();
238
239 gradient(i, j) = 2*x(i, j) / m_normalization;
240 }
241 }
242}
243
244} // end of namespace inverse
245} // 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:917
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:93
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:659
std::shared_ptr< const Grid > m_grid
virtual void normalize(double scale)
Implicitly set the normalization constant for the functional.
virtual void dot(array::Scalar &a, array::Scalar &b, double *OUTPUT)
Computes the inner product .
virtual void valueAt(array::Scalar &x, double *OUTPUT)
virtual void gradientAt(array::Scalar &x, array::Scalar &gradient)
virtual void gradientAt(array::Vector &x, array::Vector &gradient)
virtual void dot(array::Vector &a, array::Vector &b, double *OUTPUT)
Computes the inner product .
virtual void valueAt(array::Vector &x, double *OUTPUT)
virtual void normalize(double scale)
Implicitly set the normalization constant for the functional.
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)