linearization.py 16 KB
 Martin Reinecke committed Jan 07, 2019 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ``````# This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Copyright(C) 2013-2019 Max-Planck-Society # # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik. `````` Martin Reinecke committed Jul 26, 2018 17 18 19 `````` import numpy as np `````` Martin Reinecke committed Mar 30, 2020 20 ``````from .operators.operator import Operator `````` Martin Reinecke committed Jul 26, 2018 21 ``````from .field import Field `````` Martin Reinecke committed Aug 05, 2018 22 ``````from .multi_field import MultiField `````` Martin Reinecke committed Jul 26, 2018 23 ``````from .sugar import makeOp `````` Martin Reinecke committed Jul 31, 2019 24 ``````from . import utilities `````` Martin Reinecke committed Jul 26, 2018 25 26 `````` `````` Martin Reinecke committed Mar 30, 2020 27 ``````class Linearization(Operator): `````` Martin Reinecke committed Jan 10, 2019 28 `````` """Let `A` be an operator and `x` a field. `Linearization` stores the value `````` Martin Reinecke committed Jan 08, 2019 29 30 31 32 33 `````` of the operator application (i.e. `A(x)`), the local Jacobian (i.e. `dA(x)/dx`) and, optionally, the local metric. Parameters ---------- `````` Philipp Arras committed Jan 13, 2019 34 35 `````` val : Field or MultiField The value of the operator application. `````` Martin Reinecke committed Jan 08, 2019 36 `````` jac : LinearOperator `````` Philipp Arras committed Jan 13, 2019 37 38 39 40 41 42 `````` The Jacobian. metric : LinearOperator or None The metric. Default: None. want_metric : bool If True, the metric will be computed for other Linearizations derived from this one. Default: False. `````` Martin Reinecke committed Jan 08, 2019 43 `````` """ `````` Martin Reinecke committed Aug 21, 2018 44 `````` def __init__(self, val, jac, metric=None, want_metric=False): `````` Martin Reinecke committed Jul 26, 2018 45 46 `````` self._val = val self._jac = jac `````` Martin Reinecke committed Aug 10, 2018 47 48 `````` if self._val.domain != self._jac.target: raise ValueError("domain mismatch") `````` Martin Reinecke committed Aug 21, 2018 49 `````` self._want_metric = want_metric `````` Martin Reinecke committed Jul 26, 2018 50 51 `````` self._metric = metric `````` Martin Reinecke committed Aug 21, 2018 52 `````` def new(self, val, jac, metric=None): `````` Martin Reinecke committed Jan 08, 2019 53 54 55 56 57 `````` """Create a new Linearization, taking the `want_metric` property from this one. Parameters ---------- `````` Philipp Arras committed Jan 13, 2019 58 `````` val : Field or MultiField `````` Martin Reinecke committed Jan 08, 2019 59 60 61 `````` the value of the operator application jac : LinearOperator the Jacobian `````` Philipp Arras committed Jan 13, 2019 62 63 `````` metric : LinearOperator or None The metric. Default: None. `````` Martin Reinecke committed Jan 08, 2019 64 `````` """ `````` Martin Reinecke committed Aug 21, 2018 65 66 `````` return Linearization(val, jac, metric, self._want_metric) `````` Philipp Arras committed Mar 11, 2020 67 68 69 `````` def trivial_jac(self): return Linearization.make_var(self._val, self._want_metric) `````` Philipp Arras committed Mar 11, 2020 70 71 72 73 74 75 76 `````` def prepend_jac(self, jac): metric = None if self._metric is not None: from .operators.sandwich_operator import SandwichOperator metric = None if self._metric is None else SandwichOperator.make(jac, self._metric) return self.new(self._val, self._jac @ jac, metric) `````` Martin Reinecke committed Jul 26, 2018 77 78 `````` @property def domain(self): `````` Philipp Arras committed Jan 13, 2019 79 `````` """DomainTuple or MultiDomain : the Jacobian's domain""" `````` Martin Reinecke committed Jul 26, 2018 80 81 82 83 `````` return self._jac.domain @property def target(self): `````` Philipp Arras committed Jan 13, 2019 84 `````` """DomainTuple or MultiDomain : the Jacobian's target (i.e. the value's domain)""" `````` Martin Reinecke committed Jul 26, 2018 85 86 87 88 `````` return self._jac.target @property def val(self): `````` Philipp Arras committed Jan 13, 2019 89 `````` """Field or MultiField : the value""" `````` Martin Reinecke committed Jul 26, 2018 90 91 92 93 `````` return self._val @property def jac(self): `````` Martin Reinecke committed Jan 08, 2019 94 `````` """LinearOperator : the Jacobian""" `````` Martin Reinecke committed Jul 26, 2018 95 96 `````` return self._jac `````` Martin Reinecke committed Jul 26, 2018 97 98 `````` @property def gradient(self): `````` Philipp Arras committed Jan 13, 2019 99 `````` """Field or MultiField : the gradient `````` Martin Reinecke committed Jan 08, 2019 100 101 102 103 104 `````` Notes ----- Only available if target is a scalar """ `````` Martin Reinecke committed Apr 03, 2020 105 `````` return self._jac.adjoint_times(Field.scalar(1.).mult) `````` Martin Reinecke committed Jul 26, 2018 106 `````` `````` Martin Reinecke committed Aug 21, 2018 107 108 `````` @property def want_metric(self): `````` Martin Reinecke committed Jan 11, 2019 109 `````` """bool : True iff the metric was requested in the constructor""" `````` Martin Reinecke committed Aug 21, 2018 110 111 `````` return self._want_metric `````` Martin Reinecke committed Jul 26, 2018 112 113 `````` @property def metric(self): `````` Martin Reinecke committed Jan 08, 2019 114 115 116 117 118 119 `````` """LinearOperator : the metric Notes ----- Only available if target is a scalar """ `````` Martin Reinecke committed Jul 26, 2018 120 121 `````` return self._metric `````` Martin Reinecke committed Mar 30, 2020 122 123 124 125 126 127 128 129 `````` def __call__(self, other): if (other.target == self.domain): return self raise ValueError("domain mismatch") def __matmul__(self, other): return self(other) `````` Martin Reinecke committed Jul 27, 2018 130 `````` def __getitem__(self, name): `````` Martin Reinecke committed Feb 05, 2019 131 `````` return self.new(self._val[name], self._jac.ducktape_left(name)) `````` Martin Reinecke committed Jul 27, 2018 132 `````` `````` Martin Reinecke committed Jul 26, 2018 133 `````` def __neg__(self): `````` Martin Reinecke committed Aug 21, 2018 134 135 `````` return self.new(-self._val, -self._jac, None if self._metric is None else -self._metric) `````` Martin Reinecke committed Jul 26, 2018 136 `````` `````` Martin Reinecke committed Aug 06, 2018 137 `````` def conjugate(self): `````` Martin Reinecke committed Aug 21, 2018 138 `````` return self.new( `````` Martin Reinecke committed Aug 06, 2018 139 140 141 142 143 `````` self._val.conjugate(), self._jac.conjugate(), None if self._metric is None else self._metric.conjugate()) @property def real(self): `````` Martin Reinecke committed Aug 21, 2018 144 `````` return self.new(self._val.real, self._jac.real) `````` Martin Reinecke committed Aug 06, 2018 145 `````` `````` Martin Reinecke committed Aug 12, 2018 146 `````` def _myadd(self, other, neg): `````` Martin Reinecke committed Jul 26, 2018 147 148 149 `````` if isinstance(other, Linearization): met = None if self._metric is not None and other._metric is not None: `````` Martin Reinecke committed Aug 12, 2018 150 `````` met = self._metric._myadd(other._metric, neg) `````` Martin Reinecke committed Aug 21, 2018 151 `````` return self.new( `````` Martin Reinecke committed Aug 12, 2018 152 153 `````` self._val.flexible_addsub(other._val, neg), self._jac._myadd(other._jac, neg), met) `````` Martin Reinecke committed Jul 26, 2018 154 `````` if isinstance(other, (int, float, complex, Field, MultiField)): `````` Martin Reinecke committed Aug 12, 2018 155 `````` if neg: `````` Martin Reinecke committed Aug 21, 2018 156 `````` return self.new(self._val-other, self._jac, self._metric) `````` Martin Reinecke committed Aug 12, 2018 157 `````` else: `````` Martin Reinecke committed Aug 21, 2018 158 `````` return self.new(self._val+other, self._jac, self._metric) `````` Martin Reinecke committed Apr 02, 2020 159 `````` raise RuntimeError("must not get here") `````` Martin Reinecke committed Aug 12, 2018 160 161 162 `````` def __add__(self, other): return self._myadd(other, False) `````` Martin Reinecke committed Jul 26, 2018 163 164 `````` def __radd__(self, other): `````` Martin Reinecke committed Aug 12, 2018 165 `````` return self._myadd(other, False) `````` Martin Reinecke committed Jul 26, 2018 166 167 `````` def __sub__(self, other): `````` Martin Reinecke committed Aug 12, 2018 168 `````` return self._myadd(other, True) `````` Martin Reinecke committed Jul 26, 2018 169 170 171 172 `````` def __rsub__(self, other): return (-self).__add__(other) `````` Martin Reinecke committed Sep 12, 2018 173 174 `````` def __truediv__(self, other): if isinstance(other, Linearization): `````` Philipp Frank committed Jan 09, 2019 175 `````` return self.__mul__(other.one_over()) `````` Martin Reinecke committed Sep 12, 2018 176 177 178 `````` return self.__mul__(1./other) def __rtruediv__(self, other): `````` Philipp Frank committed Jan 09, 2019 179 `````` return self.one_over().__mul__(other) `````` Martin Reinecke committed Sep 12, 2018 180 `````` `````` Martin Reinecke committed Sep 27, 2018 181 182 183 `````` def __pow__(self, power): if not np.isscalar(power): return NotImplemented `````` Martin Reinecke committed Oct 09, 2018 184 185 `````` return self.new(self._val**power, makeOp(self._val**(power-1)).scale(power)(self._jac)) `````` Martin Reinecke committed Sep 27, 2018 186 `````` `````` Martin Reinecke committed Jul 26, 2018 187 188 189 `````` def __mul__(self, other): from .sugar import makeOp if isinstance(other, Linearization): `````` Martin Reinecke committed Aug 10, 2018 190 191 `````` if self.target != other.target: raise ValueError("domain mismatch") `````` Martin Reinecke committed Aug 21, 2018 192 `````` return self.new( `````` Martin Reinecke committed Jul 28, 2018 193 `````` self._val*other._val, `````` Martin Reinecke committed Aug 10, 2018 194 195 `````` (makeOp(other._val)(self._jac))._myadd( makeOp(self._val)(other._jac), False)) `````` Martin Reinecke committed Aug 06, 2018 196 197 198 199 `````` if np.isscalar(other): if other == 1: return self met = None if self._metric is None else self._metric.scale(other) `````` Martin Reinecke committed Aug 21, 2018 200 `````` return self.new(self._val*other, self._jac.scale(other), met) `````` Martin Reinecke committed Jul 26, 2018 201 `````` if isinstance(other, (Field, MultiField)): `````` Martin Reinecke committed Aug 10, 2018 202 203 `````` if self.target != other.domain: raise ValueError("domain mismatch") `````` Martin Reinecke committed Aug 21, 2018 204 `````` return self.new(self._val*other, makeOp(other)(self._jac)) `````` Martin Reinecke committed Jul 26, 2018 205 206 `````` def __rmul__(self, other): `````` Martin Reinecke committed Aug 06, 2018 207 `````` return self.__mul__(other) `````` Martin Reinecke committed Jul 26, 2018 208 `````` `````` 209 `````` def outer(self, other): `````` Martin Reinecke committed Jan 16, 2019 210 211 212 213 214 215 216 217 218 219 220 221 `````` """Computes the outer product of this Linearization with a Field or another Linearization Parameters ---------- other : Field or MultiField or Linearization Returns ------- Linearization the outer product of self and other """ `````` 222 223 224 `````` from .operators.outer_product_operator import OuterProduct if isinstance(other, Linearization): return self.new( `````` Sebastian Hutschenreuter committed Sep 19, 2018 225 226 227 `````` OuterProduct(self._val, other.target)(other._val), OuterProduct(self._jac(self._val), other.target)._myadd( OuterProduct(self._val, other.target)(other._jac), False)) `````` 228 `````` if np.isscalar(other): `````` Martin Reinecke committed Sep 12, 2018 229 `````` return self.__mul__(other) `````` 230 `````` if isinstance(other, (Field, MultiField)): `````` Sebastian Hutschenreuter committed Sep 19, 2018 231 232 `````` return self.new(OuterProduct(self._val, other.domain)(other), OuterProduct(self._jac(self._val), other.domain)) `````` 233 `````` `````` Martin Reinecke committed Aug 03, 2018 234 `````` def vdot(self, other): `````` Martin Reinecke committed Jan 16, 2019 235 236 237 238 239 240 241 242 243 244 245 246 `````` """Computes the inner product of this Linearization with a Field or another Linearization Parameters ---------- other : Field or MultiField or Linearization Returns ------- Linearization the inner product of self and other """ `````` Martin Reinecke committed Aug 05, 2018 247 `````` from .operators.simple_linear_operators import VdotOperator `````` Martin Reinecke committed Aug 03, 2018 248 `````` if isinstance(other, (Field, MultiField)): `````` Martin Reinecke committed Aug 21, 2018 249 `````` return self.new( `````` Martin Reinecke committed Mar 11, 2020 250 `````` self._val.vdot(other), `````` Martin Reinecke committed Aug 05, 2018 251 `````` VdotOperator(other)(self._jac)) `````` Martin Reinecke committed Aug 21, 2018 252 `````` return self.new( `````` Martin Reinecke committed Mar 11, 2020 253 `````` self._val.vdot(other._val), `````` Martin Reinecke committed Aug 05, 2018 254 255 `````` VdotOperator(self._val)(other._jac) + VdotOperator(other._val)(self._jac)) `````` Martin Reinecke committed Aug 03, 2018 256 `````` `````` 257 `````` def sum(self, spaces=None): `````` Martin Reinecke committed Jan 16, 2019 258 259 260 261 262 263 264 265 266 267 268 269 270 `````` """Computes the (partial) sum over self Parameters ---------- spaces : None, int or list of int - if None, sum over the entire domain - else sum over the specified subspaces Returns ------- Linearization the (partial) sum """ `````` Martin Reinecke committed Sep 18, 2018 271 `````` from .operators.contraction_operator import ContractionOperator `````` Martin Reinecke committed Mar 11, 2020 272 273 274 `````` return self.new( self._val.sum(spaces), ContractionOperator(self._jac.target, spaces)(self._jac)) `````` 275 276 `````` def integrate(self, spaces=None): `````` Martin Reinecke committed Jan 16, 2019 277 278 279 280 281 282 283 284 285 286 287 288 289 `````` """Computes the (partial) integral over self Parameters ---------- spaces : None, int or list of int - if None, integrate over the entire domain - else integrate over the specified subspaces Returns ------- Linearization the (partial) integral """ `````` Martin Reinecke committed Sep 18, 2018 290 `````` from .operators.contraction_operator import ContractionOperator `````` Martin Reinecke committed Mar 11, 2020 291 292 293 `````` return self.new( self._val.integrate(spaces), ContractionOperator(self._jac.target, spaces, 1)(self._jac)) `````` Martin Reinecke committed Jul 26, 2018 294 295 296 `````` def exp(self): tmp = self._val.exp() `````` Martin Reinecke committed Aug 21, 2018 297 `````` return self.new(tmp, makeOp(tmp)(self._jac)) `````` Philipp Arras committed Oct 15, 2018 298 `````` `````` Martin Reinecke committed Dec 21, 2018 299 300 `````` def clip(self, min=None, max=None): tmp = self._val.clip(min, max) `````` Jakob Knollmueller committed Dec 21, 2018 301 `````` if (min is None) and (max is None): `````` Martin Reinecke committed Dec 21, 2018 302 `````` return self `````` Martin Reinecke committed Apr 03, 2020 303 304 305 306 307 308 309 `````` from .sugar import full mask = full(tmp._domain, 1.) if max is not None: mask = (tmp == max).where(0., mask) if min is not None: mask = (tmp == min).where(0., mask) return self.new(tmp, makeOp(mask)(self._jac)) `````` Jakob Knollmueller committed Dec 15, 2018 310 `````` `````` Philipp Arras committed Jul 31, 2019 311 `````` def sqrt(self): `````` Philipp Arras committed Jul 31, 2019 312 313 `````` tmp = self._val.sqrt() return self.new(tmp, makeOp(0.5/tmp)(self._jac)) `````` Philipp Arras committed Jul 31, 2019 314 `````` `````` Jakob Knollmueller committed Dec 15, 2018 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 `````` def sin(self): tmp = self._val.sin() tmp2 = self._val.cos() return self.new(tmp, makeOp(tmp2)(self._jac)) def cos(self): tmp = self._val.cos() tmp2 = - self._val.sin() return self.new(tmp, makeOp(tmp2)(self._jac)) def tan(self): tmp = self._val.tan() tmp2 = 1./(self._val.cos()**2) return self.new(tmp, makeOp(tmp2)(self._jac)) def sinc(self): tmp = self._val.sinc() `````` Philipp Arras committed Jul 31, 2019 332 `````` tmp2 = ((np.pi*self._val).cos()-tmp)/self._val `````` Martin Reinecke committed Apr 03, 2020 333 `````` tmp2 = (self._val == 0.).where(0., tmp2) `````` Jakob Knollmueller committed Dec 15, 2018 334 335 `````` return self.new(tmp, makeOp(tmp2)(self._jac)) `````` Martin Reinecke committed Jul 26, 2018 336 337 `````` def log(self): tmp = self._val.log() `````` Martin Reinecke committed Aug 21, 2018 338 `````` return self.new(tmp, makeOp(1./self._val)(self._jac)) `````` Martin Reinecke committed Jul 26, 2018 339 `````` `````` Lukas Platz committed Oct 29, 2019 340 341 342 343 344 `````` def log10(self): tmp = self._val.log10() tmp2 = 1. / (self._val * np.log(10)) return self.new(tmp, makeOp(tmp2)(self._jac)) `````` Reimar H Leike committed Nov 15, 2019 345 `````` def log1p(self): `````` Gordian Edenhofer committed Nov 18, 2019 346 347 348 `````` tmp = self._val.log1p() tmp2 = 1. / (1. + self._val) return self.new(tmp, makeOp(tmp2)(self.jac)) `````` Reimar H Leike committed Nov 15, 2019 349 `````` `````` Gordian Edenhofer committed Nov 18, 2019 350 351 352 353 354 `````` def expm1(self): tmp = self._val.expm1() tmp2 = self._val.exp() return self.new(tmp, makeOp(tmp2)(self.jac)) `````` Jakob Knollmueller committed Dec 15, 2018 355 356 357 358 359 360 361 362 363 364 `````` def sinh(self): tmp = self._val.sinh() tmp2 = self._val.cosh() return self.new(tmp, makeOp(tmp2)(self._jac)) def cosh(self): tmp = self._val.cosh() tmp2 = self._val.sinh() return self.new(tmp, makeOp(tmp2)(self._jac)) `````` Martin Reinecke committed Jul 27, 2018 365 366 `````` def tanh(self): tmp = self._val.tanh() `````` Martin Reinecke committed Aug 21, 2018 367 `````` return self.new(tmp, makeOp(1.-tmp**2)(self._jac)) `````` Martin Reinecke committed Jul 27, 2018 368 `````` `````` Jakob Knollmueller committed Dec 15, 2018 369 `````` def sigmoid(self): `````` Martin Reinecke committed Jul 27, 2018 370 371 `````` tmp = self._val.tanh() tmp2 = 0.5*(1.+tmp) `````` Martin Reinecke committed Aug 21, 2018 372 `````` return self.new(tmp2, makeOp(0.5*(1.-tmp**2))(self._jac)) `````` Martin Reinecke committed Jul 27, 2018 373 `````` `````` Jakob Knollmueller committed Dec 15, 2018 374 `````` def absolute(self): `````` Martin Reinecke committed Apr 03, 2020 375 376 377 ``````# FIXME # if utilities.iscomplextype(self._val.dtype): # raise TypeError("Argument must not be complex") `````` Jakob Knollmueller committed Dec 15, 2018 378 `````` tmp = self._val.absolute() `````` Martin Reinecke committed Apr 03, 2020 379 `````` tmp2 = (self._val == 0).where(np.nan, self._val.sign()) `````` Jakob Knollmueller committed Dec 15, 2018 380 381 382 383 384 385 386 `````` return self.new(tmp, makeOp(tmp2)(self._jac)) def one_over(self): tmp = 1./self._val tmp2 = - tmp/self._val return self.new(tmp, makeOp(tmp2)(self._jac)) `````` Martin Reinecke committed Jul 26, 2018 387 `````` def add_metric(self, metric): `````` Martin Reinecke committed Aug 21, 2018 388 `````` return self.new(self._val, self._jac, metric) `````` Martin Reinecke committed Jul 26, 2018 389 `````` `````` Martin Reinecke committed Aug 29, 2018 390 391 392 `````` def with_want_metric(self): return Linearization(self._val, self._jac, self._metric, True) `````` Martin Reinecke committed Jul 26, 2018 393 `````` @staticmethod `````` Martin Reinecke committed Aug 21, 2018 394 `````` def make_var(field, want_metric=False): `````` Martin Reinecke committed Jan 16, 2019 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 `````` """Converts a Field to a Linearization, with a unity Jacobian Parameters ---------- field : Field or Multifield the field to be converted want_metric : bool If True, the metric will be computed for other Linearizations derived from this one. Default: False. Returns ------- Linearization the requested Linearization """ `````` Martin Reinecke committed Jul 26, 2018 410 `````` from .operators.scaling_operator import ScalingOperator `````` Gordian Edenhofer committed Dec 05, 2019 411 `````` return Linearization(field, ScalingOperator(field.domain, 1.), `````` Martin Reinecke committed Aug 21, 2018 412 `````` want_metric=want_metric) `````` Martin Reinecke committed Jul 26, 2018 413 414 `````` @staticmethod `````` Martin Reinecke committed Aug 21, 2018 415 `````` def make_const(field, want_metric=False): `````` Martin Reinecke committed Jan 16, 2019 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 `````` """Converts a Field to a Linearization, with a zero Jacobian Parameters ---------- field : Field or Multifield the field to be converted want_metric : bool If True, the metric will be computed for other Linearizations derived from this one. Default: False. Returns ------- Linearization the requested Linearization Notes ----- The Jacobian is square and contains only zeroes. """ `````` Martin Reinecke committed Aug 05, 2018 435 `````` from .operators.simple_linear_operators import NullOperator `````` Martin Reinecke committed Aug 21, 2018 436 437 `````` return Linearization(field, NullOperator(field.domain, field.domain), want_metric=want_metric) `````` Martin Reinecke committed Aug 29, 2018 438 `````` `````` Martin Reinecke committed Sep 14, 2018 439 440 `````` @staticmethod def make_const_empty_input(field, want_metric=False): `````` Martin Reinecke committed Jan 16, 2019 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 `````` """Converts a Field to a Linearization, with a zero Jacobian Parameters ---------- field : Field or Multifield the field to be converted want_metric : bool If True, the metric will be computed for other Linearizations derived from this one. Default: False. Returns ------- Linearization the requested Linearization Notes ----- The Jacobian has an empty input domain, i.e. its matrix representation has 0 columns. """ `````` Martin Reinecke committed Sep 14, 2018 461 462 `````` from .operators.simple_linear_operators import NullOperator from .multi_domain import MultiDomain `````` Martin Reinecke committed Sep 18, 2018 463 464 465 `````` return Linearization( field, NullOperator(MultiDomain.make({}), field.domain), want_metric=want_metric) `````` Martin Reinecke committed Sep 14, 2018 466 `````` `````` Martin Reinecke committed Aug 29, 2018 467 468 `````` @staticmethod def make_partial_var(field, constants, want_metric=False): `````` Martin Reinecke committed Jan 16, 2019 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 `````` """Converts a MultiField to a Linearization, with a Jacobian that is unity for some MultiField components and a zero matrix for others. Parameters ---------- field : Multifield the field to be converted constants : list of string the MultiField components for which the Jacobian should be a zero matrix. want_metric : bool If True, the metric will be computed for other Linearizations derived from this one. Default: False. Returns ------- Linearization the requested Linearization Notes ----- The Jacobian is square. """ `````` Martin Reinecke committed Aug 29, 2018 492 `````` from .operators.scaling_operator import ScalingOperator `````` Philipp Arras committed Aug 31, 2018 493 `````` from .operators.block_diagonal_operator import BlockDiagonalOperator `````` Martin Reinecke committed Aug 29, 2018 494 495 496 `````` if len(constants) == 0: return Linearization.make_var(field, want_metric) else: `````` Gordian Edenhofer committed Dec 05, 2019 497 `````` ops = {key: ScalingOperator(dom, 0. if key in constants else 1.) `````` Martin Reinecke committed Jan 17, 2019 498 499 `````` for key, dom in field.domain.items()} bdop = BlockDiagonalOperator(field.domain, ops) `````` Martin Reinecke committed Aug 29, 2018 500 `` return Linearization(field, bdop, want_metric=want_metric)``