Skip to content

Model class

This is an abstract class for the problem equations.


Details

Bases: ABC

Base class for all user-defined models.

Attributes:

Name Type Description
dim int

Domain dimension.

domain Mesh

Problem domain.

space FunctionSpace

Space of functions for the solution and test functions.

path Path

Test path to save the results.

Methods:

Name Description
pde

Weak form of the partial differential equations.

adjoint

Weak form of the adjoint equations.

cost

Cost functional.

constraint

Constraint functions.

derivative

Derivative components.

bilinear_form

Bilinear form to compute the velocity field.

Source code in code/formopt.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
class Model(ABC):
    """
    Base class for all user-defined models.

    Attributes
    ----------
    dim : int
        Domain dimension.
    domain : Mesh
        Problem domain.
    space : FunctionSpace
        Space of functions for the solution and test functions.
    path : Path
        Test path to save the results.

    Methods
    -------
    pde(level_set_func: Function) -> List[Tuple[Expr, Sequence[DirichletBC]]] | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
        Weak form of the partial differential equations.
    adjoint(level_set_func: Function, states: List[Function]) -> List[Tuple[Expr, Sequence[DirichletBC]]] | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
        Weak form of the adjoint equations.
    cost(level_set_func: Function, states: List[Function]) -> Expr
        Cost functional.
    constraint(level_set_func: Function, states: List[Function]) -> List[Expr]
        Constraint functions.
    derivative(level_set_func: Function, states: List[Function], adjoints: List[Function]) -> Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]
        Derivative components.
    bilinear_form(velocity_func: Function | Argument, test_func: Function | Argument) -> Tuple[Expr, bool]
        Bilinear form to compute the velocity field.
    """

    @abstractmethod
    def __init__(self, dim: int, domain: Mesh, space: FunctionSpace, path: Path):
        """
        Initializes the model.

        Parameters
        ----------
        dim : int
            Domain dimension.
        domain : Mesh
            Problem domain.
        space : FunctionSpace
            Space of functions for the solution and test functions.
        path : Path
            Test path to save the results.
        """

    @abstractmethod
    def pde(
        self, level_set_func: Function
    ) -> (
        List[Tuple[Expr, Sequence[DirichletBC]]]
        | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
    ):
        """
        Weak form of the partial differential equations.

        Parameters
        ----------
        level_set_func : Function
            Level set function.

        Returns
        -------
        List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]
            List with elements of the form (`wk`, `bc`) or (`wk`, `bc`, `jac`, `unk`, `ini_func`),
            corresponding to linear or nonlinear problems, respectively, where

            - `wk` is the weak formulation of a state equation,
            - `bc` is a list with the dirichlet boundary conditions,
            - `jac` is the jacobian of `wk`,
            - `unk` is the unknown in the nonlinear equation,
            - `ini_func` is a callable function that defines the initial guess.
        """
        pass

    @abstractmethod
    def adjoint(
        self, level_set_func: Function, states: List[Function]
    ) -> (
        List[Tuple[Expr, Sequence[DirichletBC]]]
        | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
    ):
        """
        Weak form of the adjoint equations.

        Parameters
        ----------
        level_set_func : Function
            Level set function.
        states: List[Function]
            List of state solutions.

        Returns
        -------
        List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]
            List with elements of the form (`wk`, `bc`) or (`wk`, `bc`, `jac`, `unk`, `ini_func`),
            corresponding to linear or nonlinear problems, respectively, where

            - `wk` is the weak formulation of a adjoint equation,
            - `bc` is a list with the dirichlet boundary conditions,
            - `jac` is the jacobian of `wk`,
            - `unk` is the unknown in the nonlinear equation,
            - `ini_func` is a callable function that defines the initial guess.
        """
        pass

    @abstractmethod
    def cost(self, level_set_func: Function, states: List[Function]) -> Expr:
        """
        Cost functional `J`.

        Parameters
        ----------
        level_set_func : Function
            Level set function.
        states: List[Function]
            List of state solutions.

        Returns
        -------
        Expr
            UFL expresion of the cost functional.
        """
        pass

    @abstractmethod
    def constraint(
        self, level_set_func: Function, states: List[Function]
    ) -> List[Expr]:
        """
        Constraint functions `C = [C0, C1, ...]`.

        Parameters
        ----------
        level_set_func : Function
            Level set function.
        states: List[Function]
            List of state solutions.

        Returns
        -------
        List[Expr]
            List with the UFL expressions of the constraint functions.
        """
        pass

    @abstractmethod
    def derivative(
        self, level_set_func: Function, states: List[Function], adjoints: List[Function]
    ) -> Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]:
        """
        Derivative components of the cost functional `J` and
        the constraint functions `C = [C0, C1, ...]`.

        Parameters
        ----------
        level_set_func : Function
            Level set function.
        states : List[Function]
            List of state solutions.
        adjoints : List[Function]
            List of adjoint solutions.

        Returns
        -------
        Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]
            Two tuples

            (S0_J, [S0_C0, S0_C1, ...]), (S1_J, [S1_C0, S1_C1, ...])

            where

            `S0_J`, `S1_J` are the UFL expressions
            of the derivative components of `J`;

            `S0_Ci`, `S1_Ci` are the UFL expressions
            of the derivative components of `Ci`.
        """
        pass

    @abstractmethod
    def bilinear_form(
        self, velocity_func: Function | Argument, test_func: Function | Argument
    ) -> Tuple[Expr, bool]:
        """
        Bilinear form `B` to compute the velocity field.

        Parameters
        ----------
        velocity_func : Function | TrialFunction
            The trial-like function used in the bilinear form.
        test_func : Function | TestFunction
            The test-like function used in the bilinear form.

        Returns
        -------
        b : Expr
            The UFL expression representing the bilinear form.
        flag : bool
            Whether a homogeneous Dirichlet boundary condition
            should be applied (True) or not (False).
        """
        pass

    def __verification(self, required_attrs: List[str]) -> None:
        for attr in required_attrs:
            if not hasattr(self, attr):
                raise NotImplementedError(f"Models must define the '{attr}' attribute.")

    @final
    def set_initial_level(self, func: Function) -> None:
        """
        Set a initial level set function as initial guess.
        """
        func_class = ObjFunc(func)
        self.ini_lvl = func_class

    @final
    def create_initial_level(
        self,
        centers: npt.NDArray[np.float64],
        radii: npt.NDArray[np.float64],
        factor: float = 1.0,
        ord: int = 2,
    ) -> None:
        """
        Creates a level set funtion to be used as initial guess,
        with ball shaped holes determined by centers and radii.

        Parameters
        ----------
        centers : npt.NDArray[np.float64]
            Array of center coordinates
            of shape (N, 2) or (N, 3).
        radii : npt.NDArray[np.float64]
            Array of radii of shape (N,).
        factor : float, default=1.0
            Scaling factor, positive or negative.
            The default is 1.0, which implies a domain with holes.
        ord : int, default=2
            Order of norm. Positive integer
            grater than 1 or infinity `np.inf`
            The dafault is 2, which implies Euclidean norm.
        """

        self.ini_lvl = InitialLevel(centers, radii, factor, ord)

    @final
    def save_initial_level(self, comm: MPI.Comm) -> None:
        """
        Saves the initial level set function is a xdmf file.

        Parameters
        ----------
        comm : MPI.Comm
            Communicator.
        """

        self.__verification(["domain", "path"])
        self.ini_lvl.save(comm, self.domain, self.path)

    @final
    def _get_initial_level(self):
        """
        Return the callable initial level set function.
        """
        return self.ini_lvl.func

    @final
    def runDP(
        self,
        niter: int = 100,
        dfactor: float = 1e-2,
        lv_time: Tuple[float, float] = (1e-3, 1e-1),
        lv_iter: Tuple[int, int] = (8, 16),
        smooth: bool = False,
        reinit_step: int | bool = False,
        reinit_pars: Tuple[int, float] = (8, 1e-1),
        start_to_check: int = 30,
        ctrn_tol: float = 1e-2,
        lgrn_tol: float = 1e-2,
        cost_tol: float = 1e-2,
        prev: int = 10,
        random_pars: Tuple[int, float] = (1, 0.05),
    ) -> None:
        """
        This method implements Data Parallelism.

        Parameters
        ----------
        niter : int, default=100
            The number of iterations.
        dfactor : float, default=1e-2
            A positive scaling factor applied to the inverse of
            the derivative norm to estimate the final integration
            time of the level set equation.
            Values <= 1 are recommended.
        lv_time : Tuple[float, float], default=(1e-3, 1e-1)
            A tuple with the minimum and maximum time allowed
            for the integration of the level set equation.
        lv_iter : Tuple[int, int], default=(8, 16)
            A tuple with the minimum and maximum number of
            iterations allowed for the integration of the level
            set equation.
        smooth : bool, default=False
            If True, a diffusion term is added to the level set
            equation; if False, the equation is solved without
            diffusion.
        reinit_step : int or bool, default=False
            A positive integer to apply the reinitialization
            method when the condition
                iter>start_to_check and reinit_step%iter == 0
            holds. If False, no reinitialization is applied.
        reinit_pars : Tuple[int, float], default=(8, 1e-1)
            A tuple with the number of iterations and the final
            time for the integration of the reinitialization
            equation. The argument reinit_step must be a
            positive integer.
        start_to_check : int, default=30,
            A positive integer to verify the stopping condition
            when current iteration > start_to_check.
        ctrn_tol : float, default=1e-2,
            Tolerance for the error constraint.
        lgrn_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous Lagrangian values.
        cost_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous cost values.
        prev : int, default=10,
            Number of previous values to verify the tolerance
            of the Lagrangian and cost functionals.
        random_pars : Tuple[int, float], default=(1, 0.05)
            Seed and noise level in the line search method.
        """

        self.__verification(["dim", "domain", "space", "path"])

        self.phi = runDP(
            self,
            niter,
            reinit_step,
            reinit_pars,
            dfactor,
            lv_time,
            lv_iter,
            smooth,
            start_to_check,
            ctrn_tol,
            lgrn_tol,
            cost_tol,
            prev,
            random_pars,
        )

    @final
    def runTP(
        self,
        niter: int = 100,
        dfactor: float = 1e-2,
        lv_time: Tuple[float, float] = (1e-3, 1e-1),
        lv_iter: Tuple[int, int] = (8, 16),
        smooth: bool = False,
        reinit_step: int | bool = False,
        reinit_pars: Tuple[int, float] = (8, 1e-1),
        start_to_check: int = 30,
        ctrn_tol: float = 1e-2,
        lgrn_tol: float = 1e-2,
        cost_tol: float = 1e-2,
        prev: int = 10,
        random_pars: Tuple[int, float] = (1, 0.05),
    ) -> None:
        """
        This method implements Data Parallelism.

        Parameters
        ----------
        niter : int, default=100
            The number of iterations.
        dfactor : float, default=1e-2
            A positive scaling factor applied to the inverse of
            the derivative norm to estimate the final integration
            time of the level set equation.
            Values <= 1 are recommended.
        lv_time : Tuple[float, float], default=(1e-3, 1e-1)
            A tuple with the minimum and maximum time allowed
            for the integration of the level set equation.
        lv_iter : Tuple[int, int], default=(8, 16)
            A tuple with the minimum and maximum number of
            iterations allowed for the integration of the level
            set equation.
        smooth : bool, default=False
            If True, a diffusion term is added to the level set
            equation; if False, the equation is solved without
            diffusion.
        reinit_step : int or bool, default=False
            A positive integer to apply the reinitialization
            method when the condition
                iter>start_to_check and reinit_step%iter == 0
            holds. If False, no reinitialization is applied.
        reinit_pars : Tuple[int, float], default=(8, 1e-1)
            A tuple with the number of iterations and the final
            time for the integration of the reinitialization
            equation. The argument reinit_step must be a
            positive integer.
        start_to_check : int, default=30,
            A positive integer to verify the stopping condition
            when current iteration > start_to_check.
        ctrn_tol : float, default=1e-2,
            Tolerance for the error constraint.
        lgrn_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous Lagrangian values.
        cost_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous cost values.
        prev : int, default=10,
            Number of previous values to verify the tolerance
            of the Lagrangian and cost functionals.
        random_pars : Tuple[int, float], default=(1, 0.05)
            Seed and noise level in the line search method.
        """

        self.__verification(["dim", "domain", "space", "path"])

        self.phi = runTP(
            self,
            niter,
            reinit_step,
            reinit_pars,
            dfactor,
            lv_time,
            lv_iter,
            smooth,
            start_to_check,
            ctrn_tol,
            lgrn_tol,
            cost_tol,
            prev,
            random_pars,
        )

    @final
    def runMP(
        self,
        sub_comm: MPI.Comm,
        niter: int = 100,
        dfactor: float = 1e-2,
        lv_time: Tuple[float, float] = (1e-3, 1e-1),
        lv_iter: Tuple[int, int] = (8, 16),
        smooth: bool = False,
        reinit_step: int | bool = False,
        reinit_pars: Tuple[int, float] = (8, 1e-1),
        start_to_check: int = 30,
        ctrn_tol: float = 1e-2,
        lgrn_tol: float = 1e-2,
        cost_tol: float = 1e-2,
        prev: int = 10,
        random_pars: Tuple[int, float] = (1, 0.05),
    ) -> None:
        """
        This method implements Mixed Parallelism.

        Parameters
        ----------
        niter : int, default=100
            The number of iterations.
        dfactor : float, default=1e-2
            A positive scaling factor applied to the inverse of
            the derivative norm to estimate the final integration
            time of the level set equation.
            Values <= 1 are recommended.
        lv_time : Tuple[float, float], default=(1e-3, 1e-1)
            A tuple with the minimum and maximum times allowed
            for the integration of the level set equation.
        lv_iter : Tuple[int, int], default=(8, 16)
            A tuple with the minimum and maximum number of
            iterations allowed for the integration of the level
            set equation.
        smooth : bool, default=False
            If True, a diffusion term is added to the level set
            equation; if False, the equation is solved without
            diffusion.
        reinit_step : int or bool, default=False
            A positive integer to apply the reinitialization
            method when the condition
                iter>start_to_check and reinit_step%iter == 0
            holds. If False, no reinitialization is applied.
        reinit_pars : Tuple[int, float], default=(8, 1e-1)
            A tuple with the number of iterations and the final
            time for the integration of the reinitialization
            equation. The argument reinit_step must be a
            positive integer.
        start_to_check : int, default=30,
            A positive integer to verify the stopping condition
            when current iteration > start_to_check.
        ctrn_tol : float, default=1e-2,
            Tolerance for the error constraint.
        lgrn_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous Lagrangian values.
        cost_tol : float, default=1e-2,
            Tolerance for the relative difference
            of the <prev>-th previous cost values.
        prev : int, default=10,
            Number of previous values to verify the tolerance
            of the Lagrangian and cost functionals.
        random_pars : Tuple[int, float], default=(1, 0.05)
            Seed and noise level in the line search method.
        """

        self.__verification(["dim", "domain", "space", "path"])

        self.phi = runMP(
            sub_comm,
            self,
            niter,
            reinit_step,
            reinit_pars,
            dfactor,
            lv_time,
            lv_iter,
            smooth,
            start_to_check,
            ctrn_tol,
            lgrn_tol,
            cost_tol,
            prev,
            random_pars,
        )

__init__(dim, domain, space, path) abstractmethod

Initializes the model.

Parameters:

Name Type Description Default
dim int

Domain dimension.

required
domain Mesh

Problem domain.

required
space FunctionSpace

Space of functions for the solution and test functions.

required
path Path

Test path to save the results.

required
Source code in code/formopt.py
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
@abstractmethod
def __init__(self, dim: int, domain: Mesh, space: FunctionSpace, path: Path):
    """
    Initializes the model.

    Parameters
    ----------
    dim : int
        Domain dimension.
    domain : Mesh
        Problem domain.
    space : FunctionSpace
        Space of functions for the solution and test functions.
    path : Path
        Test path to save the results.
    """

adjoint(level_set_func, states) abstractmethod

Weak form of the adjoint equations.

Parameters:

Name Type Description Default
level_set_func Function

Level set function.

required
states List[Function]

List of state solutions.

required

Returns:

Type Description
List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]

List with elements of the form (wk, bc) or (wk, bc, jac, unk, ini_func), corresponding to linear or nonlinear problems, respectively, where

  • wk is the weak formulation of a adjoint equation,
  • bc is a list with the dirichlet boundary conditions,
  • jac is the jacobian of wk,
  • unk is the unknown in the nonlinear equation,
  • ini_func is a callable function that defines the initial guess.
Source code in code/formopt.py
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
@abstractmethod
def adjoint(
    self, level_set_func: Function, states: List[Function]
) -> (
    List[Tuple[Expr, Sequence[DirichletBC]]]
    | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
):
    """
    Weak form of the adjoint equations.

    Parameters
    ----------
    level_set_func : Function
        Level set function.
    states: List[Function]
        List of state solutions.

    Returns
    -------
    List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]
        List with elements of the form (`wk`, `bc`) or (`wk`, `bc`, `jac`, `unk`, `ini_func`),
        corresponding to linear or nonlinear problems, respectively, where

        - `wk` is the weak formulation of a adjoint equation,
        - `bc` is a list with the dirichlet boundary conditions,
        - `jac` is the jacobian of `wk`,
        - `unk` is the unknown in the nonlinear equation,
        - `ini_func` is a callable function that defines the initial guess.
    """
    pass

bilinear_form(velocity_func, test_func) abstractmethod

Bilinear form B to compute the velocity field.

Parameters:

Name Type Description Default
velocity_func Function | TrialFunction

The trial-like function used in the bilinear form.

required
test_func Function | TestFunction

The test-like function used in the bilinear form.

required

Returns:

Name Type Description
b Expr

The UFL expression representing the bilinear form.

flag bool

Whether a homogeneous Dirichlet boundary condition should be applied (True) or not (False).

Source code in code/formopt.py
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
@abstractmethod
def bilinear_form(
    self, velocity_func: Function | Argument, test_func: Function | Argument
) -> Tuple[Expr, bool]:
    """
    Bilinear form `B` to compute the velocity field.

    Parameters
    ----------
    velocity_func : Function | TrialFunction
        The trial-like function used in the bilinear form.
    test_func : Function | TestFunction
        The test-like function used in the bilinear form.

    Returns
    -------
    b : Expr
        The UFL expression representing the bilinear form.
    flag : bool
        Whether a homogeneous Dirichlet boundary condition
        should be applied (True) or not (False).
    """
    pass

constraint(level_set_func, states) abstractmethod

Constraint functions C = [C0, C1, ...].

Parameters:

Name Type Description Default
level_set_func Function

Level set function.

required
states List[Function]

List of state solutions.

required

Returns:

Type Description
List[Expr]

List with the UFL expressions of the constraint functions.

Source code in code/formopt.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
@abstractmethod
def constraint(
    self, level_set_func: Function, states: List[Function]
) -> List[Expr]:
    """
    Constraint functions `C = [C0, C1, ...]`.

    Parameters
    ----------
    level_set_func : Function
        Level set function.
    states: List[Function]
        List of state solutions.

    Returns
    -------
    List[Expr]
        List with the UFL expressions of the constraint functions.
    """
    pass

cost(level_set_func, states) abstractmethod

Cost functional J.

Parameters:

Name Type Description Default
level_set_func Function

Level set function.

required
states List[Function]

List of state solutions.

required

Returns:

Type Description
Expr

UFL expresion of the cost functional.

Source code in code/formopt.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
@abstractmethod
def cost(self, level_set_func: Function, states: List[Function]) -> Expr:
    """
    Cost functional `J`.

    Parameters
    ----------
    level_set_func : Function
        Level set function.
    states: List[Function]
        List of state solutions.

    Returns
    -------
    Expr
        UFL expresion of the cost functional.
    """
    pass

create_initial_level(centers, radii, factor=1.0, ord=2)

Creates a level set funtion to be used as initial guess, with ball shaped holes determined by centers and radii.

Parameters:

Name Type Description Default
centers NDArray[float64]

Array of center coordinates of shape (N, 2) or (N, 3).

required
radii NDArray[float64]

Array of radii of shape (N,).

required
factor float

Scaling factor, positive or negative. The default is 1.0, which implies a domain with holes.

1.0
ord int

Order of norm. Positive integer grater than 1 or infinity np.inf The dafault is 2, which implies Euclidean norm.

2
Source code in code/formopt.py
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
@final
def create_initial_level(
    self,
    centers: npt.NDArray[np.float64],
    radii: npt.NDArray[np.float64],
    factor: float = 1.0,
    ord: int = 2,
) -> None:
    """
    Creates a level set funtion to be used as initial guess,
    with ball shaped holes determined by centers and radii.

    Parameters
    ----------
    centers : npt.NDArray[np.float64]
        Array of center coordinates
        of shape (N, 2) or (N, 3).
    radii : npt.NDArray[np.float64]
        Array of radii of shape (N,).
    factor : float, default=1.0
        Scaling factor, positive or negative.
        The default is 1.0, which implies a domain with holes.
    ord : int, default=2
        Order of norm. Positive integer
        grater than 1 or infinity `np.inf`
        The dafault is 2, which implies Euclidean norm.
    """

    self.ini_lvl = InitialLevel(centers, radii, factor, ord)

derivative(level_set_func, states, adjoints) abstractmethod

Derivative components of the cost functional J and the constraint functions C = [C0, C1, ...].

Parameters:

Name Type Description Default
level_set_func Function

Level set function.

required
states List[Function]

List of state solutions.

required
adjoints List[Function]

List of adjoint solutions.

required

Returns:

Type Description
Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]

Two tuples

(S0_J, [S0_C0, S0_C1, ...]), (S1_J, [S1_C0, S1_C1, ...])

where

S0_J, S1_J are the UFL expressions of the derivative components of J;

S0_Ci, S1_Ci are the UFL expressions of the derivative components of Ci.

Source code in code/formopt.py
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
@abstractmethod
def derivative(
    self, level_set_func: Function, states: List[Function], adjoints: List[Function]
) -> Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]:
    """
    Derivative components of the cost functional `J` and
    the constraint functions `C = [C0, C1, ...]`.

    Parameters
    ----------
    level_set_func : Function
        Level set function.
    states : List[Function]
        List of state solutions.
    adjoints : List[Function]
        List of adjoint solutions.

    Returns
    -------
    Tuple[Tuple[Expr, List[Expr]], Tuple[Expr, List[Expr]]]
        Two tuples

        (S0_J, [S0_C0, S0_C1, ...]), (S1_J, [S1_C0, S1_C1, ...])

        where

        `S0_J`, `S1_J` are the UFL expressions
        of the derivative components of `J`;

        `S0_Ci`, `S1_Ci` are the UFL expressions
        of the derivative components of `Ci`.
    """
    pass

pde(level_set_func) abstractmethod

Weak form of the partial differential equations.

Parameters:

Name Type Description Default
level_set_func Function

Level set function.

required

Returns:

Type Description
List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]

List with elements of the form (wk, bc) or (wk, bc, jac, unk, ini_func), corresponding to linear or nonlinear problems, respectively, where

  • wk is the weak formulation of a state equation,
  • bc is a list with the dirichlet boundary conditions,
  • jac is the jacobian of wk,
  • unk is the unknown in the nonlinear equation,
  • ini_func is a callable function that defines the initial guess.
Source code in code/formopt.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
@abstractmethod
def pde(
    self, level_set_func: Function
) -> (
    List[Tuple[Expr, Sequence[DirichletBC]]]
    | List[Tuple[Expr, Sequence[DirichletBC], Expr, Coefficient, GenericFunc]]
):
    """
    Weak form of the partial differential equations.

    Parameters
    ----------
    level_set_func : Function
        Level set function.

    Returns
    -------
    List[Tuple[Expr, List[DirichletBC]]] | List[Tuple[Expr, List[DirichletBC], Expr, Coefficient, GenericFunc]]
        List with elements of the form (`wk`, `bc`) or (`wk`, `bc`, `jac`, `unk`, `ini_func`),
        corresponding to linear or nonlinear problems, respectively, where

        - `wk` is the weak formulation of a state equation,
        - `bc` is a list with the dirichlet boundary conditions,
        - `jac` is the jacobian of `wk`,
        - `unk` is the unknown in the nonlinear equation,
        - `ini_func` is a callable function that defines the initial guess.
    """
    pass

runDP(niter=100, dfactor=0.01, lv_time=(0.001, 0.1), lv_iter=(8, 16), smooth=False, reinit_step=False, reinit_pars=(8, 0.1), start_to_check=30, ctrn_tol=0.01, lgrn_tol=0.01, cost_tol=0.01, prev=10, random_pars=(1, 0.05))

This method implements Data Parallelism.

Parameters:

Name Type Description Default
niter int

The number of iterations.

100
dfactor float

A positive scaling factor applied to the inverse of the derivative norm to estimate the final integration time of the level set equation. Values <= 1 are recommended.

1e-2
lv_time Tuple[float, float]

A tuple with the minimum and maximum time allowed for the integration of the level set equation.

(1e-3, 1e-1)
lv_iter Tuple[int, int]

A tuple with the minimum and maximum number of iterations allowed for the integration of the level set equation.

(8, 16)
smooth bool

If True, a diffusion term is added to the level set equation; if False, the equation is solved without diffusion.

False
reinit_step int or bool

A positive integer to apply the reinitialization method when the condition iter>start_to_check and reinit_step%iter == 0 holds. If False, no reinitialization is applied.

False
reinit_pars Tuple[int, float]

A tuple with the number of iterations and the final time for the integration of the reinitialization equation. The argument reinit_step must be a positive integer.

(8, 1e-1)
start_to_check int

A positive integer to verify the stopping condition when current iteration > start_to_check.

30,
ctrn_tol float

Tolerance for the error constraint.

1e-2,
lgrn_tol float

Tolerance for the relative difference of the -th previous Lagrangian values.

1e-2,
cost_tol float

Tolerance for the relative difference of the -th previous cost values.

1e-2,
prev int

Number of previous values to verify the tolerance of the Lagrangian and cost functionals.

10,
random_pars Tuple[int, float]

Seed and noise level in the line search method.

(1, 0.05)
Source code in code/formopt.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
@final
def runDP(
    self,
    niter: int = 100,
    dfactor: float = 1e-2,
    lv_time: Tuple[float, float] = (1e-3, 1e-1),
    lv_iter: Tuple[int, int] = (8, 16),
    smooth: bool = False,
    reinit_step: int | bool = False,
    reinit_pars: Tuple[int, float] = (8, 1e-1),
    start_to_check: int = 30,
    ctrn_tol: float = 1e-2,
    lgrn_tol: float = 1e-2,
    cost_tol: float = 1e-2,
    prev: int = 10,
    random_pars: Tuple[int, float] = (1, 0.05),
) -> None:
    """
    This method implements Data Parallelism.

    Parameters
    ----------
    niter : int, default=100
        The number of iterations.
    dfactor : float, default=1e-2
        A positive scaling factor applied to the inverse of
        the derivative norm to estimate the final integration
        time of the level set equation.
        Values <= 1 are recommended.
    lv_time : Tuple[float, float], default=(1e-3, 1e-1)
        A tuple with the minimum and maximum time allowed
        for the integration of the level set equation.
    lv_iter : Tuple[int, int], default=(8, 16)
        A tuple with the minimum and maximum number of
        iterations allowed for the integration of the level
        set equation.
    smooth : bool, default=False
        If True, a diffusion term is added to the level set
        equation; if False, the equation is solved without
        diffusion.
    reinit_step : int or bool, default=False
        A positive integer to apply the reinitialization
        method when the condition
            iter>start_to_check and reinit_step%iter == 0
        holds. If False, no reinitialization is applied.
    reinit_pars : Tuple[int, float], default=(8, 1e-1)
        A tuple with the number of iterations and the final
        time for the integration of the reinitialization
        equation. The argument reinit_step must be a
        positive integer.
    start_to_check : int, default=30,
        A positive integer to verify the stopping condition
        when current iteration > start_to_check.
    ctrn_tol : float, default=1e-2,
        Tolerance for the error constraint.
    lgrn_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous Lagrangian values.
    cost_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous cost values.
    prev : int, default=10,
        Number of previous values to verify the tolerance
        of the Lagrangian and cost functionals.
    random_pars : Tuple[int, float], default=(1, 0.05)
        Seed and noise level in the line search method.
    """

    self.__verification(["dim", "domain", "space", "path"])

    self.phi = runDP(
        self,
        niter,
        reinit_step,
        reinit_pars,
        dfactor,
        lv_time,
        lv_iter,
        smooth,
        start_to_check,
        ctrn_tol,
        lgrn_tol,
        cost_tol,
        prev,
        random_pars,
    )

runMP(sub_comm, niter=100, dfactor=0.01, lv_time=(0.001, 0.1), lv_iter=(8, 16), smooth=False, reinit_step=False, reinit_pars=(8, 0.1), start_to_check=30, ctrn_tol=0.01, lgrn_tol=0.01, cost_tol=0.01, prev=10, random_pars=(1, 0.05))

This method implements Mixed Parallelism.

Parameters:

Name Type Description Default
niter int

The number of iterations.

100
dfactor float

A positive scaling factor applied to the inverse of the derivative norm to estimate the final integration time of the level set equation. Values <= 1 are recommended.

1e-2
lv_time Tuple[float, float]

A tuple with the minimum and maximum times allowed for the integration of the level set equation.

(1e-3, 1e-1)
lv_iter Tuple[int, int]

A tuple with the minimum and maximum number of iterations allowed for the integration of the level set equation.

(8, 16)
smooth bool

If True, a diffusion term is added to the level set equation; if False, the equation is solved without diffusion.

False
reinit_step int or bool

A positive integer to apply the reinitialization method when the condition iter>start_to_check and reinit_step%iter == 0 holds. If False, no reinitialization is applied.

False
reinit_pars Tuple[int, float]

A tuple with the number of iterations and the final time for the integration of the reinitialization equation. The argument reinit_step must be a positive integer.

(8, 1e-1)
start_to_check int

A positive integer to verify the stopping condition when current iteration > start_to_check.

30,
ctrn_tol float

Tolerance for the error constraint.

1e-2,
lgrn_tol float

Tolerance for the relative difference of the -th previous Lagrangian values.

1e-2,
cost_tol float

Tolerance for the relative difference of the -th previous cost values.

1e-2,
prev int

Number of previous values to verify the tolerance of the Lagrangian and cost functionals.

10,
random_pars Tuple[int, float]

Seed and noise level in the line search method.

(1, 0.05)
Source code in code/formopt.py
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
@final
def runMP(
    self,
    sub_comm: MPI.Comm,
    niter: int = 100,
    dfactor: float = 1e-2,
    lv_time: Tuple[float, float] = (1e-3, 1e-1),
    lv_iter: Tuple[int, int] = (8, 16),
    smooth: bool = False,
    reinit_step: int | bool = False,
    reinit_pars: Tuple[int, float] = (8, 1e-1),
    start_to_check: int = 30,
    ctrn_tol: float = 1e-2,
    lgrn_tol: float = 1e-2,
    cost_tol: float = 1e-2,
    prev: int = 10,
    random_pars: Tuple[int, float] = (1, 0.05),
) -> None:
    """
    This method implements Mixed Parallelism.

    Parameters
    ----------
    niter : int, default=100
        The number of iterations.
    dfactor : float, default=1e-2
        A positive scaling factor applied to the inverse of
        the derivative norm to estimate the final integration
        time of the level set equation.
        Values <= 1 are recommended.
    lv_time : Tuple[float, float], default=(1e-3, 1e-1)
        A tuple with the minimum and maximum times allowed
        for the integration of the level set equation.
    lv_iter : Tuple[int, int], default=(8, 16)
        A tuple with the minimum and maximum number of
        iterations allowed for the integration of the level
        set equation.
    smooth : bool, default=False
        If True, a diffusion term is added to the level set
        equation; if False, the equation is solved without
        diffusion.
    reinit_step : int or bool, default=False
        A positive integer to apply the reinitialization
        method when the condition
            iter>start_to_check and reinit_step%iter == 0
        holds. If False, no reinitialization is applied.
    reinit_pars : Tuple[int, float], default=(8, 1e-1)
        A tuple with the number of iterations and the final
        time for the integration of the reinitialization
        equation. The argument reinit_step must be a
        positive integer.
    start_to_check : int, default=30,
        A positive integer to verify the stopping condition
        when current iteration > start_to_check.
    ctrn_tol : float, default=1e-2,
        Tolerance for the error constraint.
    lgrn_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous Lagrangian values.
    cost_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous cost values.
    prev : int, default=10,
        Number of previous values to verify the tolerance
        of the Lagrangian and cost functionals.
    random_pars : Tuple[int, float], default=(1, 0.05)
        Seed and noise level in the line search method.
    """

    self.__verification(["dim", "domain", "space", "path"])

    self.phi = runMP(
        sub_comm,
        self,
        niter,
        reinit_step,
        reinit_pars,
        dfactor,
        lv_time,
        lv_iter,
        smooth,
        start_to_check,
        ctrn_tol,
        lgrn_tol,
        cost_tol,
        prev,
        random_pars,
    )

runTP(niter=100, dfactor=0.01, lv_time=(0.001, 0.1), lv_iter=(8, 16), smooth=False, reinit_step=False, reinit_pars=(8, 0.1), start_to_check=30, ctrn_tol=0.01, lgrn_tol=0.01, cost_tol=0.01, prev=10, random_pars=(1, 0.05))

This method implements Data Parallelism.

Parameters:

Name Type Description Default
niter int

The number of iterations.

100
dfactor float

A positive scaling factor applied to the inverse of the derivative norm to estimate the final integration time of the level set equation. Values <= 1 are recommended.

1e-2
lv_time Tuple[float, float]

A tuple with the minimum and maximum time allowed for the integration of the level set equation.

(1e-3, 1e-1)
lv_iter Tuple[int, int]

A tuple with the minimum and maximum number of iterations allowed for the integration of the level set equation.

(8, 16)
smooth bool

If True, a diffusion term is added to the level set equation; if False, the equation is solved without diffusion.

False
reinit_step int or bool

A positive integer to apply the reinitialization method when the condition iter>start_to_check and reinit_step%iter == 0 holds. If False, no reinitialization is applied.

False
reinit_pars Tuple[int, float]

A tuple with the number of iterations and the final time for the integration of the reinitialization equation. The argument reinit_step must be a positive integer.

(8, 1e-1)
start_to_check int

A positive integer to verify the stopping condition when current iteration > start_to_check.

30,
ctrn_tol float

Tolerance for the error constraint.

1e-2,
lgrn_tol float

Tolerance for the relative difference of the -th previous Lagrangian values.

1e-2,
cost_tol float

Tolerance for the relative difference of the -th previous cost values.

1e-2,
prev int

Number of previous values to verify the tolerance of the Lagrangian and cost functionals.

10,
random_pars Tuple[int, float]

Seed and noise level in the line search method.

(1, 0.05)
Source code in code/formopt.py
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
@final
def runTP(
    self,
    niter: int = 100,
    dfactor: float = 1e-2,
    lv_time: Tuple[float, float] = (1e-3, 1e-1),
    lv_iter: Tuple[int, int] = (8, 16),
    smooth: bool = False,
    reinit_step: int | bool = False,
    reinit_pars: Tuple[int, float] = (8, 1e-1),
    start_to_check: int = 30,
    ctrn_tol: float = 1e-2,
    lgrn_tol: float = 1e-2,
    cost_tol: float = 1e-2,
    prev: int = 10,
    random_pars: Tuple[int, float] = (1, 0.05),
) -> None:
    """
    This method implements Data Parallelism.

    Parameters
    ----------
    niter : int, default=100
        The number of iterations.
    dfactor : float, default=1e-2
        A positive scaling factor applied to the inverse of
        the derivative norm to estimate the final integration
        time of the level set equation.
        Values <= 1 are recommended.
    lv_time : Tuple[float, float], default=(1e-3, 1e-1)
        A tuple with the minimum and maximum time allowed
        for the integration of the level set equation.
    lv_iter : Tuple[int, int], default=(8, 16)
        A tuple with the minimum and maximum number of
        iterations allowed for the integration of the level
        set equation.
    smooth : bool, default=False
        If True, a diffusion term is added to the level set
        equation; if False, the equation is solved without
        diffusion.
    reinit_step : int or bool, default=False
        A positive integer to apply the reinitialization
        method when the condition
            iter>start_to_check and reinit_step%iter == 0
        holds. If False, no reinitialization is applied.
    reinit_pars : Tuple[int, float], default=(8, 1e-1)
        A tuple with the number of iterations and the final
        time for the integration of the reinitialization
        equation. The argument reinit_step must be a
        positive integer.
    start_to_check : int, default=30,
        A positive integer to verify the stopping condition
        when current iteration > start_to_check.
    ctrn_tol : float, default=1e-2,
        Tolerance for the error constraint.
    lgrn_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous Lagrangian values.
    cost_tol : float, default=1e-2,
        Tolerance for the relative difference
        of the <prev>-th previous cost values.
    prev : int, default=10,
        Number of previous values to verify the tolerance
        of the Lagrangian and cost functionals.
    random_pars : Tuple[int, float], default=(1, 0.05)
        Seed and noise level in the line search method.
    """

    self.__verification(["dim", "domain", "space", "path"])

    self.phi = runTP(
        self,
        niter,
        reinit_step,
        reinit_pars,
        dfactor,
        lv_time,
        lv_iter,
        smooth,
        start_to_check,
        ctrn_tol,
        lgrn_tol,
        cost_tol,
        prev,
        random_pars,
    )

save_initial_level(comm)

Saves the initial level set function is a xdmf file.

Parameters:

Name Type Description Default
comm Comm

Communicator.

required
Source code in code/formopt.py
367
368
369
370
371
372
373
374
375
376
377
378
379
@final
def save_initial_level(self, comm: MPI.Comm) -> None:
    """
    Saves the initial level set function is a xdmf file.

    Parameters
    ----------
    comm : MPI.Comm
        Communicator.
    """

    self.__verification(["domain", "path"])
    self.ini_lvl.save(comm, self.domain, self.path)

set_initial_level(func)

Set a initial level set function as initial guess.

Source code in code/formopt.py
329
330
331
332
333
334
335
@final
def set_initial_level(self, func: Function) -> None:
    """
    Set a initial level set function as initial guess.
    """
    func_class = ObjFunc(func)
    self.ini_lvl = func_class