Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
adjoint_case.f90
Go to the documentation of this file.
1! Copyright (c) 2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32
33! Implements the `adjoint_case_t` type.
35 use num_types, only: rp, dp, sp
36 use case, only: case_t
42 use output_controller, only: output_controller_t
43 use file, only: file_t
44 use json_module, only: json_file
45 use json_utils, only: json_get, json_get_or_default
47 implicit none
48 private
50
55
56 class(adjoint_fluid_scheme_t), allocatable :: scheme
57 type(case_t), pointer :: case
58
59 ! Fields
60 real(kind=rp) :: tol
61 type(adjoint_output_t) :: f_out
62 type(output_controller_t) :: output_controller
63
64 logical :: have_scalar = .false.
65
66 end type adjoint_case_t
67
70 end interface adjoint_init
71
72contains
73
74 ! Constructor from json.
75 subroutine adjoint_init_from_json(this, neko_case)
76 class(adjoint_case_t), intent(inout) :: this
77 type(case_t), target, intent(inout) :: neko_case
78 real(kind=rp) :: tol
79
80 ! Read the tolerance
81 call json_get_or_default(neko_case%params, "tol", tol, 1.0e-6_rp)
82
83 call adjoint_init_from_attributes(this, neko_case, tol)
84
85 end subroutine adjoint_init_from_json
86
87 ! Constructor from attributes
88 subroutine adjoint_init_from_attributes(this, neko_case, tol)
89 class(adjoint_case_t), intent(inout) :: this
90 class(case_t), intent(inout), target :: neko_case
91 real(kind=rp), intent(in) :: tol
92
93 this%case => neko_case
94 this%tol = tol
95
96 ! Check if the scalar field is allocated
97 if (allocated(neko_case%scalar)) then
98 this%have_scalar = .true.
99 end if
100
101 call adjoint_case_init_common(this, neko_case)
102
103 end subroutine adjoint_init_from_attributes
104
106 subroutine adjoint_case_init_common(this, neko_case)
107 class(adjoint_case_t), intent(inout) :: this
108 type(case_t), intent(inout) :: neko_case
109 integer :: lx = 0
110 logical :: scalar = .false.
111 real(kind=rp) :: real_val
112 character(len=:), allocatable :: string_val
113 integer :: precision
114
115 ! extra things for json
116 type(json_file) :: ic_json
117 character(len=:), allocatable :: json_key
118 !
119 ! Setup fluid scheme
120 !
121 call json_get(neko_case%params, 'case.fluid.scheme', string_val)
122 call adjoint_fluid_scheme_factory(this%scheme, trim(string_val))
123
124 call json_get(neko_case%params, 'case.numerics.polynomial_order', lx)
125 lx = lx + 1 ! add 1 to get number of gll points
126 call this%scheme%init(neko_case%msh, lx, neko_case%params, neko_case%usr, &
127 neko_case%fluid%ext_bdf)
128
129 !
130 ! Setup scalar scheme
131 !
132 ! @todo Scalar adjoint is not implemented yet
133 ! if (neko_case%params%valid_path('case.scalar')) then
134 ! call json_get_or_default(neko_case%params, 'case.scalar.enabled', &
135 ! scalar, .true.)
136 ! end if
137
138 ! if (scalar) then
139 ! allocate(neko_case%scalar)
140 ! call neko_case%scalar%init(neko_case%msh, this%scheme%c_Xh, &
141 ! this%scheme%gs_Xh, neko_case%params, neko_case%usr,&
142 ! neko_case%material_properties)
143 ! call this%scheme%chkp%add_scalar(neko_case%scalar%output_controller)
144 ! this%scheme%chkp%abs1 => neko_case%scalar%abx1
145 ! this%scheme%chkp%abs2 => neko_case%scalar%abx2
146 ! this%scheme%chkp%slag => neko_case%scalar%slag
147 ! end if
148
149 !
150 ! Setup user defined conditions
151 !
152 ! if (neko_case%params%valid_path('case.fluid.inflow_condition')) then
153 ! call json_get(neko_case%params, 'case.fluid.inflow_condition.type', &
154 ! string_val)
155 ! if (trim(string_val) .eq. 'user') then
156 ! call neko_case%fluid%set_usr_inflow(neko_case%usr%fluid_user_if)
157 ! end if
158 ! end if
159
160 ! Setup user boundary conditions for the scalar.
161 ! if (scalar) then
162 ! call neko_case%scalar%set_user_bc(neko_case%usr%scalar_user_bc)
163 ! end if
164
165 !
166 ! Setup initial conditions
167 !
168 json_key = json_key_fallback(neko_case%params, &
169 'case.adjoint_fluid.initial_condition', 'case.fluid.initial_condition')
170
171 call json_get(neko_case%params, json_key//'.type', string_val)
172 call json_get_subdict(neko_case%params, json_key, ic_json)
173
174 if (trim(string_val) .ne. 'user') then
176 this%scheme%u_adj, this%scheme%v_adj, this%scheme%w_adj, &
177 this%scheme%p_adj, this%scheme%c_Xh, this%scheme%gs_Xh, &
178 string_val, ic_json)
179 else
181 this%scheme%u_adj, this%scheme%v_adj, this%scheme%w_adj, &
182 this%scheme%p_adj, this%scheme%c_Xh, this%scheme%gs_Xh, &
183 neko_case%usr%fluid_user_ic, ic_json)
184 end if
185
186 ! if (scalar) then
187 ! call json_get(neko_case%params, 'case.scalar.initial_condition.type', &
188 ! string_val)
189 ! if (trim(string_val) .ne. 'user') then
190 ! call set_scalar_ic(neko_case%scalar%output_controller, &
191 ! neko_case%scalar%c_Xh, neko_case%scalar%gs_Xh, string_val, &
192 ! neko_case%params)
193 ! else
194 ! call set_scalar_ic(neko_case%scalar%output_controller, &
195 ! neko_case%scalar%c_Xh, neko_case%scalar%gs_Xh, &
196 ! neko_case%usr%scalar_user_ic, neko_case%params)
197 ! end if
198 ! end if
199
200 ! Add initial conditions to BDF scheme (if present)
201 select type (f => this%scheme)
202 type is (adjoint_fluid_pnpn_t)
203 call f%ulag%set(f%u_adj)
204 call f%vlag%set(f%v_adj)
205 call f%wlag%set(f%w_adj)
206 end select
207
208 !
209 ! Validate that the neko_case is properly setup for time-stepping
210 !
211 call this%scheme%validate
212
213 ! if (scalar) then
214 ! call neko_case%scalar%slag%set(neko_case%scalar%output_controller)
215 ! call neko_case%scalar%validate
216 ! end if
217
218 !
219 ! Setup output precision of the field files
220 !
221 call json_get_or_default(neko_case%params, 'case.output_precision', &
222 string_val, 'single')
223
224 if (trim(string_val) .eq. 'double') then
225 precision = dp
226 else
227 precision = sp
228 end if
229
230 !
231 ! Setup output_controller
232 !
233 call this%output_controller%init(neko_case%end_time)
234 if (scalar) then
235 this%f_out = adjoint_output_t(precision, this%scheme, neko_case%scalar, &
236 path = trim(neko_case%output_directory))
237 else
238 this%f_out = adjoint_output_t(precision, this%scheme, &
239 path = trim(neko_case%output_directory))
240 end if
241
242 call json_get_or_default(neko_case%params, 'case.fluid.output_control',&
243 string_val, 'org')
244
245 if (trim(string_val) .eq. 'org') then
246 ! yes, it should be real_val below for type compatibility
247 call json_get(neko_case%params, 'case.nsamples', real_val)
248 call this%output_controller%add(this%f_out, real_val, 'nsamples')
249 else if (trim(string_val) .eq. 'never') then
250 ! Fix a dummy 0.0 output_value
251 call json_get_or_default(neko_case%params, 'case.fluid.output_value', &
252 real_val, 0.0_rp)
253 call this%output_controller%add(this%f_out, 0.0_rp, string_val)
254 else
255 call json_get(neko_case%params, 'case.fluid.output_value', real_val)
256 call this%output_controller%add(this%f_out, real_val, string_val)
257 end if
258
259 ! !
260 ! ! Save checkpoints (if nothing specified, default to saving at end of sim)
261 ! !
262 ! call json_get_or_default(neko_case%params, 'case.output_checkpoints',&
263 ! logical_val, .true.)
264 ! if (logical_val) then
265 ! call json_get_or_default(neko_case%params, 'case.checkpoint_format', &
266 ! string_val, "chkp")
267 ! neko_case%f_chkp = chkp_output_t(this%scheme%chkp, &
268 ! path = output_directory, &
269 ! ! fmt = trim(string_val))
270 ! call json_get_or_default(neko_case%params, 'case.checkpoint_control', &
271 ! string_val, "simulationtime")
272 ! call json_get_or_default(neko_case%params, 'case.checkpoint_value', &
273 ! real_val,&
274 ! 1e10_rp)
275 ! call this%output_controller%add(neko_case%f_chkp, real_val, string_val)
276 ! end if
277
278 end subroutine adjoint_case_init_common
279
280 ! Destructor.
281 subroutine adjoint_free(this)
282 class(adjoint_case_t), intent(inout) :: this
283
284 nullify(this%case)
285 call this%scheme%free()
286 call this%output_controller%free()
287
288 end subroutine adjoint_free
289
290end module adjoint_case
291
subroutine adjoint_init_from_json(this, neko_case)
subroutine, public adjoint_free(this)
subroutine adjoint_init_from_attributes(this, neko_case, tol)
subroutine adjoint_case_init_common(this, neko_case)
Initialize a neko_case from its (loaded) params object.
Factory for all adjoint fluid schemes.
subroutine, public adjoint_fluid_scheme_factory(object, type_name)
Initialise a adjoint fluid scheme.
Initial flow condition.
Adjoint Pn/Pn formulation.
Defines an output for a adjoint.
character(len=:) function, allocatable, public json_key_fallback(json, lookup, fallback)
Create a json_string based on fallback logic. If the lookup key is present in the json object,...
subroutine, public json_get_subdict(json, key, output)
Extract a sub-object from a json object.
Adjoint case type. Todo: This should Ideally be a subclass of case_t, however, that is not yet suppoe...