1
+ # This file is part of the dino package
2
+ #
3
+ # dino is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Lesser General Public License as published by
5
+ # the Free Software Foundation, either version 2 of the License, or any later version.
6
+ #
7
+ # dino is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public License
13
+ # If not, see <http://www.gnu.org/licenses/>.
14
+ #
15
+ # Author: Tom O'Leary-Roseberry
16
+
17
+
18
+ import dolfin as dl
19
+ import numpy as np
20
+ import ufl
21
+
22
+ path_to_hippylib = '../../hippylib/'
23
+ import sys , os
24
+ sys .path .append ( os .environ .get ('HIPPYLIB_PATH' ,path_to_hippylib ))
25
+ from hippylib import *
26
+
27
+ sys .path .append ( os .environ .get ('HIPPYFLOW_PATH' ))
28
+ from hippyflow import LinearStateObservable
29
+
30
+ def confusion_linear_observable (mesh ,nx_targets = 10 , ny_targets = 5 ,use_krylov = False ,output_folder = 'poisson_setup/' ,\
31
+ verbose = False ,seed = 0 ):
32
+ class confusion_varf :
33
+ def __init__ (self ,Vh ,save_fields = False ,output_folder = 'confusion_setup/' ):
34
+ '''
35
+
36
+ '''
37
+ self .Vh = Vh
38
+ # Gaussian blob for the right hand side
39
+ self .f = dl .interpolate ( dl .Expression ('max(0.5,exp(-25*(pow(x[0]-0.7,2) + pow(x[1]-0.7,2))))' ,degree = 5 ), Vh [STATE ])
40
+ # Compute velocity field
41
+ self .v = self .computeVelocityField (Vh [STATE ].mesh ())
42
+ if save_fields :
43
+ if not os .path .isdir (output_folder ):
44
+ os .mkdir (output_folder )
45
+ f_pvd = dl .File (output_folder + 'f_blob.pvd' )
46
+ f_pvd << self .f
47
+ v_pvd = dl .File (output_folder + 'v_sol.pvd' )
48
+ v_pvd << self .v
49
+ # Constant coefficients for the PDE
50
+ self .c = dl .Constant (1.0 )
51
+ self .k = dl .Constant (0.01 )
52
+
53
+
54
+ def computeVelocityField (self ,mesh ):
55
+ def v_boundary (x ,on_boundary ):
56
+ return on_boundary
57
+
58
+ def q_boundary (x ,on_boundary ):
59
+ return x [0 ] < dl .DOLFIN_EPS and x [1 ] < dl .DOLFIN_EPS
60
+
61
+ Xh = dl .VectorFunctionSpace (mesh ,'Lagrange' , 2 )
62
+ Wh = dl .FunctionSpace (mesh , 'Lagrange' , 1 )
63
+ mixed_element = ufl .MixedElement ([Xh .ufl_element (), Wh .ufl_element ()])
64
+ XW = dl .FunctionSpace (mesh , mixed_element )
65
+
66
+ Re = dl .Constant (1e2 )
67
+
68
+ g = dl .Expression (('0.0' ,'(x[0] < 1e-14) - (x[0] > 1 - 1e-14)' ), degree = 1 )
69
+ bc1 = dl .DirichletBC (XW .sub (0 ), g , v_boundary )
70
+ bc2 = dl .DirichletBC (XW .sub (1 ), dl .Constant (0 ), q_boundary , 'pointwise' )
71
+ bcs = [bc1 , bc2 ]
72
+
73
+ vq = dl .Function (XW )
74
+ (v ,q ) = ufl .split (vq )
75
+ (v_test , q_test ) = dl .TestFunctions (XW )
76
+
77
+ def strain (v ):
78
+ return ufl .sym (ufl .grad (v ))
79
+
80
+ F = ( (2. / Re )* ufl .inner (strain (v ),strain (v_test ))+ ufl .inner (ufl .nabla_grad (v )* v , v_test )
81
+ - (q * ufl .div (v_test )) + ( ufl .div (v ) * q_test ) ) * ufl .dx
82
+
83
+ dl .solve (F == 0 , vq , bcs , solver_parameters = {"newton_solver" :
84
+ {"relative_tolerance" :1e-4 , "maximum_iterations" :150 }})
85
+ return vq .split ()[0 ]
86
+
87
+
88
+ def __call__ (self ,u ,m ,p ):
89
+ '''
90
+ Return the variational form of the PDE
91
+ Inputs
92
+ -u: state variable
93
+ -m: model parameter
94
+ -p: adjoint variable
95
+ Outputs:
96
+ Variational form of the PDE
97
+ '''
98
+ h = dl .CellDiameter (Vh [STATE ].mesh ())
99
+ v_norm = dl .sqrt ( dl .dot (self .v ,self .v ) + 1e-6 )
100
+
101
+ return (h / v_norm )* dl .dot ( self .v , dl .nabla_grad (u )) * dl .dot ( self .v , dl .nabla_grad (p )) * dl .dx \
102
+ + self .k * dl .inner (dl .nabla_grad (u ), dl .nabla_grad (p ))* dl .dx \
103
+ + dl .inner (dl .nabla_grad (u ), self .v * p )* dl .dx \
104
+ + self .c * dl .exp (m )* u * u * u * p * dl .dx \
105
+ - self .f * p * dl .dx
106
+
107
+
108
+
109
+ def u_boundary (x , on_boundary ):
110
+ return on_boundary
111
+
112
+ ########################################################################
113
+
114
+ # Construct the linear observable
115
+
116
+ # Define the function spaces
117
+ Vh1 = dl .FunctionSpace (mesh , 'Lagrange' , 1 )
118
+ Vh = [Vh1 , Vh1 , Vh1 ]
119
+ if verbose :
120
+ print ( "Number of dofs: STATE={0}, PARAMETER={1}, ADJOINT={2}" .format (Vh [STATE ].dim (), Vh [PARAMETER ].dim (), Vh [ADJOINT ].dim ()) )
121
+
122
+ ########################################################################
123
+ # Construct the linear observable
124
+ # Targets only on the bottom
125
+ #Targets only on the bottom
126
+ x_targets = np .linspace (0.1 ,0.9 ,nx_targets )
127
+ y_targets = np .linspace (0.1 ,0.5 ,ny_targets )
128
+ targets = []
129
+ for xi in x_targets :
130
+ for yi in y_targets :
131
+ targets .append ((xi ,yi ))
132
+ targets = np .array (targets )
133
+ ntargets = targets .shape [0 ]
134
+
135
+ if verbose :
136
+ print ( "Number of observation points: {0}" .format (targets .shape [0 ]) )
137
+
138
+ # Define Dirichp.et boundary conditions
139
+ u_bdr = dl .Constant (0.0 )
140
+ u_bdr0 = dl .Constant (0.0 )
141
+ bc = dl .DirichletBC (Vh [STATE ], u_bdr , u_boundary )
142
+ bc0 = dl .DirichletBC (Vh [STATE ], u_bdr0 , u_boundary )
143
+
144
+
145
+ m0 = dl .interpolate (dl .Constant (0.0 ), Vh [PARAMETER ]).vector ()
146
+ param_dimension = m0 .get_local ().shape [0 ]
147
+ m0 .set_local (np .random .randn (param_dimension ))
148
+
149
+ varf_handler = confusion_varf (Vh , output_folder = output_folder )
150
+
151
+ pde = PDEVariationalProblem (Vh , varf_handler , bc , bc0 , is_fwd_linear = False )
152
+ if use_krylov :
153
+ pde .solver = PETScKrylovSolver (mesh .mpi_comm (), "gmres" , amg_method ())
154
+ pde .solver_fwd_inc = PETScKrylovSolver (mesh .mpi_comm (), "gmres" , amg_method ())
155
+ pde .solver_adj_inc = PETScKrylovSolver (mesh .mpi_comm (), "gmres" , amg_method ())
156
+ pde .solver .parameters ["relative_tolerance" ] = 1e-6
157
+ pde .solver .parameters ["absolute_tolerance" ] = 1e-8
158
+ pde .solver .parameters ["maximum_iterations" ] = 500
159
+ pde .solver_fwd_inc .parameters = pde .solver .parameters
160
+ pde .solver_fwd_inc .parameters ["relative_tolerance" ] = 1e-2
161
+ pde .solver_adj_inc .parameters = pde .solver .parameters
162
+ pde .solver_adj_inc .parameters ["relative_tolerance" ] = 1e-2
163
+
164
+ B = assemblePointwiseObservation (Vh [STATE ], targets )
165
+
166
+ observable = LinearStateObservable (pde ,B )
167
+
168
+ observable ._targets_ = targets
169
+
170
+ return observable
171
+
172
+
0 commit comments