Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
force_torque.f90
Go to the documentation of this file.
1! Copyright (c) 2023, 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!
35
37 use num_types, only : rp, dp, sp
39 use json_module, only : json_file
41 use registry, only : neko_registry
43 use time_state, only : time_state_t
44 use field, only : field_t
45 use operators, only : curl
46 use case, only : case_t
49 use coefs, only : coef_t
50 use operators, only : strain_rate
51 use vector, only : vector_t
52 use dirichlet, only : dirichlet_t
55 use logger, only : log_size, neko_log
60 use mpi_f08, only : mpi_integer, mpi_sum, mpi_allreduce
61 use comm, only : neko_comm
63 use ale_manager, only : neko_ale
65 use utils, only : neko_error
66
67 implicit none
68 private
69
72 type, public, extends(simulation_component_t) :: force_torque_t
74 type(field_t), pointer :: u => null()
76 type(field_t), pointer :: v => null()
78 type(field_t), pointer :: w => null()
80 type(field_t), pointer :: p => null()
82 type(field_t), pointer :: mu => null()
83
84 ! Masked working arrays
85 type(vector_t) :: n1, n2, n3
86 type(vector_t) :: r1, r2, r3
87 type(vector_t) :: force1, force2, force3
88 type(vector_t) :: force4, force5, force6
89 type(vector_t) :: pmsk
90 type(vector_t) :: mu_msk
91 type(vector_t) :: s11msk, s22msk, s33msk, s12msk, s13msk, s23msk
92 real(kind=rp) :: center(3) = 0.0_rp
93 real(kind=rp) :: scale
94 integer :: zone_id
95 character(len=20) :: zone_name
96 type(coef_t), pointer :: coef => null()
97 type(dirichlet_t) :: bc
98 character(len=80) :: print_format
99 ! Pointer to the live pivot state inside ale_manager
100 type(pivot_state_t), pointer :: pivot_link => null()
101 logical :: moving_center = .false.
102 logical :: update_normals = .false.
103 character(len=64) :: linked_body_name = 'NOT_LINKED'
104 ! Stores the Time=0 offset from the initial pivot
105 real(kind=rp) :: local_offset(3) = 0.0_rp
106 ! Current Pivot Position
107 real(kind=rp), pointer :: body_p(:) => null()
108 ! Current Rotation Matrix
109 real(kind=rp), pointer :: body_r(:,:) => null()
110
111 contains
113 procedure, pass(this) :: init => force_torque_init_from_json
115 procedure, private, pass(this) :: init_common => force_torque_init_common
117 generic :: init_from_components => &
118 init_from_controllers, init_from_controllers_properties
120 procedure, pass(this) :: init_from_controllers => &
124 procedure, pass(this) :: init_from_controllers_properties => &
127 procedure, pass(this) :: free => force_torque_free
129 procedure, pass(this) :: compute_ => force_torque_compute
131 procedure, private, pass(this) :: ale_link => setup_ale_link
132 end type force_torque_t
133
134contains
135
137 subroutine force_torque_init_from_json(this, json, case)
138 class(force_torque_t), intent(inout), target :: this
139 type(json_file), intent(inout) :: json
140 class(case_t), intent(inout), target :: case
141 integer :: zone_id
142 real(kind=rp), allocatable :: center(:)
143 character(len=:), allocatable :: zone_name, fluid_name, center_type
144 character(len=:), allocatable :: name
145 real(kind=rp) :: scale
146 logical :: long_print
147
148 call json_get_or_default(json, "name", name, "force_torque")
149 call this%init_base(json, case)
150
151 call json_get_or_default(json, 'fluid_name', fluid_name, 'fluid')
152 call json_get_or_lookup(json, 'zone_id', zone_id)
153 call json_get_or_default(json, 'zone_name', zone_name, ' ')
154 call json_get_or_lookup_or_default(json, 'scale', scale, 1.0_rp)
155 call json_get_or_default(json, 'long_print', long_print, .false.)
156 call json_get_or_lookup(json, 'center', center)
157 call json_get_or_default(json, 'center_type', center_type, 'fixed')
158 if (trim(center_type) /= 'fixed' .and. &
159 trim(center_type) /= 'pivot' .and. &
160 trim(center_type) /= 'body_attached') then
161 call neko_error("force_torque: center_type must be 'fixed'"// &
162 ", 'pivot', or 'body_attached'.")
163 end if
164
165 if (allocated(center)) this%center = center
166
167 call this%init_common(name, fluid_name, zone_id, zone_name, this%center, &
168 scale, case%fluid%c_xh, long_print, center_type = center_type)
169 end subroutine force_torque_init_from_json
170
185 subroutine force_torque_init_from_controllers(this, name, case, order, &
186 preprocess_controller, compute_controller, output_controller, &
187 fluid_name, zone_id, zone_name, center, scale, coef, long_print)
188 class(force_torque_t), intent(inout) :: this
189 character(len=*), intent(in) :: name
190 class(case_t), intent(inout), target :: case
191 integer :: order
192 type(time_based_controller_t), intent(in) :: preprocess_controller
193 type(time_based_controller_t), intent(in) :: compute_controller
194 type(time_based_controller_t), intent(in) :: output_controller
195 character(len=*), intent(in) :: fluid_name
196 character(len=*), intent(in) :: zone_name
197 integer, intent(in) :: zone_id
198 real(kind=rp), intent(in) :: center(3)
199 real(kind=rp), intent(in) :: scale
200 type(coef_t), target, intent(in) :: coef
201 logical, intent(in) :: long_print
202
203 call this%init_base_from_components(case, order, preprocess_controller, &
204 compute_controller, output_controller)
205 call this%init_common(name, fluid_name, zone_id, zone_name, center, scale, &
206 coef, long_print)
207
209
229 case, order, preprocess_control, preprocess_value, compute_control, &
230 compute_value, output_control, output_value, fluid_name, zone_name, &
231 zone_id, center, scale, coef, long_print)
232 class(force_torque_t), intent(inout) :: this
233 character(len=*), intent(in) :: name
234 class(case_t), intent(inout), target :: case
235 integer :: order
236 character(len=*), intent(in) :: preprocess_control
237 real(kind=rp), intent(in) :: preprocess_value
238 character(len=*), intent(in) :: compute_control
239 real(kind=rp), intent(in) :: compute_value
240 character(len=*), intent(in) :: output_control
241 real(kind=rp), intent(in) :: output_value
242 character(len=*), intent(in) :: fluid_name
243 character(len=*), intent(in) :: zone_name
244 integer, intent(in) :: zone_id
245 real(kind=rp), intent(in) :: center(3)
246 real(kind=rp), intent(in) :: scale
247 type(coef_t), target, intent(in) :: coef
248 logical, intent(in) :: long_print
249
250 call this%init_base_from_components(case, order, preprocess_control, &
251 preprocess_value, compute_control, compute_value, output_control, &
252 output_value)
253 call this%init_common(name, fluid_name, zone_id, zone_name, center, scale, &
254 coef, long_print)
255
257
268 subroutine force_torque_init_common(this, name, fluid_name, zone_id, &
269 zone_name, center, scale, coef, long_print, center_type)
270 class(force_torque_t), intent(inout) :: this
271 character(len=*), intent(in) :: name
272 real(kind=rp), intent(in) :: center(3)
273 real(kind=rp), intent(in) :: scale
274 character(len=*), intent(in) :: fluid_name
275 character(len=*), intent(in) :: zone_name
276 integer, intent(in) :: zone_id
277 type(coef_t), target, intent(in) :: coef
278 logical, intent(in) :: long_print
279 character(len=*), intent(in), optional :: center_type
280 character(len=:), allocatable :: ctype_str
281 integer :: n_pts, glb_n_pts, ierr
282 real(kind=rp) :: avg_r(3)
283 character(len=1000) :: log_buf
284 this%name = name
285 this%coef => coef
286 this%zone_id = zone_id
287 this%scale = scale
288 this%zone_name = zone_name
289
290 if (present(center_type)) then
291 ctype_str = center_type
292 else
293 ctype_str = 'fixed' ! Default behavior
294 end if
295
296 call this%ale_link(zone_id, ctype_str, center)
297
298 if (ctype_str /= 'fixed' .and. .not. this%moving_center) then
299 ctype_str = 'fixed (reverted from ' // ctype_str // ')'
300 end if
301
302 ! Set fixed center if not linked to an ALE body
303 if (.not. this%moving_center) then
304 this%center = center
305 end if
306
307
308 if (long_print) then
309 this%print_format = '(I7,E20.10,E20.10,E20.10,E20.10,A)'
310 else
311 this%print_format = '(I7,E13.5,E13.5,E13.5,E13.5,A)'
312 end if
313
314 this%u => neko_registry%get_field_by_name("u")
315 this%v => neko_registry%get_field_by_name("v")
316 this%w => neko_registry%get_field_by_name("w")
317 this%p => neko_registry%get_field_by_name("p")
318 this%mu => neko_registry%get_field_by_name(fluid_name // '_mu_tot')
319
320
321 call this%bc%init_base(this%coef)
322 call this%bc%mark_zone(this%case%msh%labeled_zones(this%zone_id))
323 call this%bc%finalize()
324 n_pts = this%bc%msk(0)
325 if (n_pts .gt. 0) then
326 call this%n1%init(n_pts)
327 call this%n2%init(n_pts)
328 call this%n3%init(n_pts)
329 call this%r1%init(n_pts)
330 call this%r2%init(n_pts)
331 call this%r3%init(n_pts)
332 call this%force1%init(n_pts)
333 call this%force2%init(n_pts)
334 call this%force3%init(n_pts)
335 call this%force4%init(n_pts)
336 call this%force5%init(n_pts)
337 call this%force6%init(n_pts)
338 call this%s11msk%init(n_pts)
339 call this%s22msk%init(n_pts)
340 call this%s33msk%init(n_pts)
341 call this%s12msk%init(n_pts)
342 call this%s13msk%init(n_pts)
343 call this%s23msk%init(n_pts)
344 call this%pmsk%init(n_pts)
345 call this%mu_msk%init(n_pts)
346 end if
347
348 call setup_normals(this%coef, this%bc%msk, this%bc%facet, &
349 this%n1, this%n2, this%n3, n_pts)
350 call masked_gather_copy_0(this%r1%x, this%coef%dof%x, this%bc%msk, &
351 this%u%size(), n_pts)
352 call masked_gather_copy_0(this%r2%x, this%coef%dof%y, this%bc%msk, &
353 this%u%size(), n_pts)
354 call masked_gather_copy_0(this%r3%x, this%coef%dof%z, this%bc%msk, &
355 this%u%size(), n_pts)
356
357 call mpi_allreduce(n_pts, glb_n_pts, 1, &
358 mpi_integer, mpi_sum, neko_comm, ierr)
359 ! Calculating avg pos here
360 avg_r(1) = glsum(this%r1%x, n_pts)/glb_n_pts
361 avg_r(2) = glsum(this%r2%x, n_pts)/glb_n_pts
362 avg_r(3) = glsum(this%r3%x, n_pts)/glb_n_pts
363 ! Print some information
364 call neko_log%section('Force/torque calculation')
365 write(log_buf, '(A,I4,A,A)') 'Zone ', zone_id, ' ', trim(zone_name)
366 call neko_log%message(log_buf)
367
368 write(log_buf, '(A,I6, I6)') 'Global number of GLL points in zone: ', &
369 glb_n_pts
370 call neko_log%message(log_buf)
371
372 write(log_buf, '(A,A)') 'Center Type: ', trim(ctype_str)
373 call neko_log%message(log_buf)
374
375 if (trim(ctype_str) == 'pivot' .or. &
376 trim(ctype_str) == 'body_attached') then
377 write(log_buf, '(A,A)') 'Linked to ALE Body movement: ', &
378 trim(this%linked_body_name)
379 call neko_log%message(log_buf)
380 write(log_buf, '(A,E15.7,E15.7,E15.7)') &
381 'Initial center for torque calculation: ', this%center
382 call neko_log%message(log_buf)
383 else
384 write(log_buf, '(A,E15.7,E15.7,E15.7)') &
385 'Fixed center for torque calculation: ', this%center
386 call neko_log%message(log_buf)
387 end if
388
389 write(log_buf, '(A,E15.7,E15.7,E15.7)') &
390 'Average of zone''s coordinates: ', avg_r
391 call neko_log%message(log_buf)
392
393 write(log_buf, '(A,E15.7)') 'Scale: ', scale
394 call neko_log%message(log_buf)
395 call neko_log%end_section()
396
397
398 call cadd(this%r1%x, -this%center(1), n_pts)
399 call cadd(this%r2%x, -this%center(2), n_pts)
400 call cadd(this%r3%x, -this%center(3), n_pts)
401 if (neko_bcknd_device .eq. 1 .and. n_pts .gt. 0) then
402 call device_memcpy(this%r1%x, this%r1%x_d, n_pts, host_to_device, &
403 .false.)
404 call device_memcpy(this%r2%x, this%r2%x_d, n_pts, host_to_device, &
405 .false.)
406 call device_memcpy(this%r3%x, this%r3%x_d, n_pts, host_to_device, &
407 .true.)
408 end if
409
410 end subroutine force_torque_init_common
411
413 subroutine force_torque_free(this)
414 class(force_torque_t), intent(inout) :: this
415 call this%free_base()
416
417 call this%n1%free()
418 call this%n2%free()
419 call this%n3%free()
420
421 call this%r1%free()
422 call this%r2%free()
423 call this%r3%free()
424
425 call this%force1%free()
426 call this%force2%free()
427 call this%force3%free()
428
429 call this%force4%free()
430 call this%force5%free()
431 call this%force6%free()
432
433 call this%pmsk%free()
434 call this%mu_msk%free()
435 call this%s11msk%free()
436 call this%s22msk%free()
437 call this%s33msk%free()
438 call this%s12msk%free()
439 call this%s13msk%free()
440 call this%s23msk%free()
441
442 nullify(this%u)
443 nullify(this%v)
444 nullify(this%w)
445 nullify(this%p)
446 nullify(this%coef)
447 nullify(this%mu)
448 nullify(this%pivot_link)
449 end subroutine force_torque_free
450
453 subroutine force_torque_compute(this, time)
454 class(force_torque_t), intent(inout) :: this
455 type(time_state_t), intent(in) :: time
456
457 real(kind=rp) :: dgtq(12) = 0.0_rp
458 integer :: n_pts, temp_indices(6)
459 type(field_t), pointer :: s11, s22, s33, s12, s13, s23
460 character(len=1000) :: log_buf
461 real(kind=rp) :: rot_offset(3)
462 n_pts = this%bc%msk(0)
463
464
465 ! body_attached
466 if (this%moving_center .and. associated(this%body_P)) then
467 if (associated(this%body_R)) then
468 ! R * Offset
469 rot_offset(1) = this%body_R(1,1)*this%local_offset(1) + &
470 this%body_R(1,2)*this%local_offset(2) + &
471 this%body_R(1,3)*this%local_offset(3)
472 rot_offset(2) = this%body_R(2,1)*this%local_offset(1) + &
473 this%body_R(2,2)*this%local_offset(2) + &
474 this%body_R(2,3)*this%local_offset(3)
475 rot_offset(3) = this%body_R(3,1)*this%local_offset(1) + &
476 this%body_R(3,2)*this%local_offset(2) + &
477 this%body_R(3,3)*this%local_offset(3)
478
479 this%center = this%body_P + rot_offset
480 end if
481 end if
482
483 if (this%update_normals) then
484
485 call setup_normals(this%coef, this%bc%msk, this%bc%facet, &
486 this%n1, this%n2, this%n3, n_pts)
487
488 call masked_gather_copy_0(this%r1%x, this%coef%dof%x, this%bc%msk, &
489 this%u%size(), n_pts)
490 call masked_gather_copy_0(this%r2%x, this%coef%dof%y, this%bc%msk, &
491 this%u%size(), n_pts)
492 call masked_gather_copy_0(this%r3%x, this%coef%dof%z, this%bc%msk, &
493 this%u%size(), n_pts)
494
495 call cadd(this%r1%x, -this%center(1), n_pts)
496 call cadd(this%r2%x, -this%center(2), n_pts)
497 call cadd(this%r3%x, -this%center(3), n_pts)
498
499 if (neko_bcknd_device .eq. 1 .and. n_pts .gt. 0) then
500 call device_memcpy(this%r1%x, this%r1%x_d, n_pts, &
501 host_to_device, .false.)
502 call device_memcpy(this%r2%x, this%r2%x_d, n_pts, &
503 host_to_device, .false.)
504 call device_memcpy(this%r3%x, this%r3%x_d, n_pts, &
505 host_to_device, .true.)
506 end if
507 end if
508
509 call neko_scratch_registry%request_field(s11, temp_indices(1), .false.)
510 call neko_scratch_registry%request_field(s12, temp_indices(2), .false.)
511 call neko_scratch_registry%request_field(s13, temp_indices(3), .false.)
512 call neko_scratch_registry%request_field(s22, temp_indices(4), .false.)
513 call neko_scratch_registry%request_field(s23, temp_indices(5), .false.)
514 call neko_scratch_registry%request_field(s33, temp_indices(6), .false.)
515
516 call strain_rate(s11, s22, s33, s12, s13, s23, &
517 this%u, this%v, this%w, this%coef)
518
519 ! On the CPU we can actually just use the original subroutines...
520 if (neko_bcknd_device .eq. 0) then
521 call masked_gather_copy_0(this%s11msk%x, s11%x, this%bc%msk, &
522 this%u%size(), n_pts)
523 call masked_gather_copy_0(this%s22msk%x, s22%x, this%bc%msk, &
524 this%u%size(), n_pts)
525 call masked_gather_copy_0(this%s33msk%x, s33%x, this%bc%msk, &
526 this%u%size(), n_pts)
527 call masked_gather_copy_0(this%s12msk%x, s12%x, this%bc%msk, &
528 this%u%size(), n_pts)
529 call masked_gather_copy_0(this%s13msk%x, s13%x, this%bc%msk, &
530 this%u%size(), n_pts)
531 call masked_gather_copy_0(this%s23msk%x, s23%x, this%bc%msk, &
532 this%u%size(), n_pts)
533 call masked_gather_copy_0(this%pmsk%x, this%p%x, this%bc%msk, &
534 this%u%size(), n_pts)
535 call masked_gather_copy_0(this%mu_msk%x, this%mu%x, this%bc%msk, &
536 this%u%size(), n_pts)
537 call calc_force_array(this%force1%x, this%force2%x, this%force3%x, &
538 this%force4%x, this%force5%x, this%force6%x, &
539 this%s11msk%x, &
540 this%s22msk%x, &
541 this%s33msk%x, &
542 this%s12msk%x, &
543 this%s13msk%x, &
544 this%s23msk%x, &
545 this%pmsk%x, &
546 this%n1%x, &
547 this%n2%x, &
548 this%n3%x, &
549 this%mu_msk%x, &
550 n_pts)
551 dgtq(1) = glsum(this%force1%x, n_pts)
552 dgtq(2) = glsum(this%force2%x, n_pts)
553 dgtq(3) = glsum(this%force3%x, n_pts)
554 dgtq(4) = glsum(this%force4%x, n_pts)
555 dgtq(5) = glsum(this%force5%x, n_pts)
556 dgtq(6) = glsum(this%force6%x, n_pts)
557 call vcross(this%s11msk%x, this%s22msk%x, this%s33msk%x, &
558 this%r1%x, this%r2%x, this%r3%x, &
559 this%force1%x, this%force2%x, this%force3%x, n_pts)
560
561 dgtq(7) = glsum(this%s11msk%x, n_pts)
562 dgtq(8) = glsum(this%s22msk%x, n_pts)
563 dgtq(9) = glsum(this%s33msk%x, n_pts)
564 call vcross(this%s11msk%x, this%s22msk%x, this%s33msk%x, &
565 this%r1%x, this%r2%x, this%r3%x, &
566 this%force4%x, this%force5%x, this%force6%x, n_pts)
567 dgtq(10) = glsum(this%s11msk%x, n_pts)
568 dgtq(11) = glsum(this%s22msk%x, n_pts)
569 dgtq(12) = glsum(this%s33msk%x, n_pts)
570 else
571 if (n_pts .gt. 0) then
572 call device_masked_gather_copy_0(this%s11msk%x_d, s11%x_d, &
573 this%bc%msk_d, this%u%size(), n_pts)
574 call device_masked_gather_copy_0(this%s22msk%x_d, s22%x_d, &
575 this%bc%msk_d, this%u%size(), n_pts)
576 call device_masked_gather_copy_0(this%s33msk%x_d, s33%x_d, &
577 this%bc%msk_d, this%u%size(), n_pts)
578 call device_masked_gather_copy_0(this%s12msk%x_d, s12%x_d, &
579 this%bc%msk_d, this%u%size(), n_pts)
580 call device_masked_gather_copy_0(this%s13msk%x_d, s13%x_d, &
581 this%bc%msk_d, this%u%size(), n_pts)
582 call device_masked_gather_copy_0(this%s23msk%x_d, s23%x_d, &
583 this%bc%msk_d, this%u%size(), n_pts)
584 call device_masked_gather_copy_0(this%pmsk%x_d, this%p%x_d, &
585 this%bc%msk_d, this%u%size(), n_pts)
586 call device_masked_gather_copy_0(this%mu_msk%x_d, this%mu%x_d, &
587 this%bc%msk_d, this%u%size(), n_pts)
588
589 call device_calc_force_array(this%force1%x_d, this%force2%x_d, &
590 this%force3%x_d, &
591 this%force4%x_d, &
592 this%force5%x_d, &
593 this%force6%x_d, &
594 this%s11msk%x_d, &
595 this%s22msk%x_d, &
596 this%s33msk%x_d, &
597 this%s12msk%x_d, &
598 this%s13msk%x_d, &
599 this%s23msk%x_d, &
600 this%pmsk%x_d, &
601 this%n1%x_d, &
602 this%n2%x_d, &
603 this%n3%x_d, &
604 this%mu_msk%x_d, &
605 n_pts)
606 ! Overwriting masked s11, s22, s33 as they are no longer needed
607 call device_vcross(this%s11msk%x_d, this%s22msk%x_d, &
608 this%s33msk%x_d, &
609 this%r1%x_d, this%r2%x_d, this%r3%x_d, &
610 this%force1%x_d, this%force2%x_d, &
611 this%force3%x_d, n_pts)
612 call device_vcross(this%s12msk%x_d, this%s13msk%x_d, this%s23msk%x_d,&
613 this%r1%x_d, this%r2%x_d, this%r3%x_d, &
614 this%force4%x_d, this%force5%x_d, this%force6%x_d, n_pts)
615 end if
616 dgtq(1) = device_glsum(this%force1%x_d, n_pts)
617 dgtq(2) = device_glsum(this%force2%x_d, n_pts)
618 dgtq(3) = device_glsum(this%force3%x_d, n_pts)
619 dgtq(4) = device_glsum(this%force4%x_d, n_pts)
620 dgtq(5) = device_glsum(this%force5%x_d, n_pts)
621 dgtq(6) = device_glsum(this%force6%x_d, n_pts)
622 dgtq(7) = device_glsum(this%s11msk%x_d, n_pts)
623 dgtq(8) = device_glsum(this%s22msk%x_d, n_pts)
624 dgtq(9) = device_glsum(this%s33msk%x_d, n_pts)
625 dgtq(10) = device_glsum(this%s12msk%x_d, n_pts)
626 dgtq(11) = device_glsum(this%s13msk%x_d, n_pts)
627 dgtq(12) = device_glsum(this%s23msk%x_d, n_pts)
628 end if
629 dgtq = this%scale*dgtq
630 write(log_buf, '(A, I4, A, A)') 'Force and torque on zone ', &
631 this%zone_id, ' ', this%zone_name
632 call neko_log%message(log_buf)
633 write(log_buf, '(A)') &
634 'Time step, time, total force/torque, pressure, viscous, direction'
635 call neko_log%message(log_buf)
636 write(log_buf, this%print_format) &
637 time%tstep, time%t, dgtq(1) + dgtq(4), dgtq(1), dgtq(4), ', forcex'
638 call neko_log%message(log_buf)
639 write(log_buf, this%print_format) &
640 time%tstep, time%t, dgtq(2) + dgtq(5), dgtq(2), dgtq(5), ', forcey'
641 call neko_log%message(log_buf)
642 write(log_buf, this%print_format) &
643 time%tstep, time%t, dgtq(3) + dgtq(6), dgtq(3), dgtq(6), ', forcez'
644 call neko_log%message(log_buf)
645 write(log_buf, this%print_format) &
646 time%tstep, time%t, dgtq(7) + dgtq(10), dgtq(7), dgtq(10), ', torquex'
647 call neko_log%message(log_buf)
648 write(log_buf, this%print_format) &
649 time%tstep, time%t, dgtq(8) + dgtq(11), dgtq(8), dgtq(11), ', torquey'
650 call neko_log%message(log_buf)
651 write(log_buf, this%print_format) &
652 time%tstep, time%t, dgtq(9) + dgtq(12), dgtq(9), dgtq(12), ', torquez'
653 call neko_log%message(log_buf)
654 call neko_scratch_registry%relinquish_field(temp_indices)
655
656 end subroutine force_torque_compute
657
659 subroutine setup_ale_link(this, zone_id, center_type, center_in)
660 class(force_torque_t), intent(inout) :: this
661 integer, intent(in) :: zone_id
662 character(len=*), intent(in) :: center_type
663 real(kind=rp), intent(in) :: center_in(3)
664
665 character(len=128) :: log_buf
666 integer :: i, j, nbodies, nindices
667 logical :: body_found
668 logical :: ale_active
669
670 ale_active = .false.
671 this%moving_center = .false.
672 this%update_normals = .false.
673 this%local_offset = 0.0_rp
674 nullify(this%body_P)
675 nullify(this%body_R)
676
677 ! Check Global Pointer for ALE
678 if (associated(neko_ale)) then
679 if (neko_ale%active) then
680 ale_active = .true.
681 this%update_normals = .true.
682
683 if (trim(center_type) == 'pivot' .or. &
684 trim(center_type) == 'body_attached') then
685
686 body_found = .false.
687 nbodies = neko_ale%config%nbodies
688 i = 1
689 do while (i <= nbodies .and. .not. body_found)
690 if (allocated(neko_ale%config%bodies(i)%zone_indices)) then
691 nindices = size(neko_ale%config%bodies(i)%zone_indices)
692 j = 1
693 do while (j <= nindices .and. .not. body_found)
694 if (neko_ale%config%bodies(i)%zone_indices(j) &
695 == zone_id) then
696
697 ! Body found
698 this%moving_center = .true.
699 this%pivot_link => neko_ale%ale_pivot(i)
700 this%linked_body_name = neko_ale%config%bodies(i)%name
701 ! body_id = neko_ale%config%bodies(i)%id
702 body_found = .true.
703
704 ! Point to Live Data
705 this%body_P => neko_ale%ale_pivot(i)%pos
706 this%body_R => neko_ale%body_rot_matrices(:, :, i)
707
708 ! Calculate local offset (Using Time=0 data)
709 if (trim(center_type) == 'pivot') then
710 ! Attached to center -> Offset is 0
711 this%local_offset = 0.0_rp
712 this%center = this%body_P ! Initial Position
713 else
714 ! Detached from pivot -->
715 ! offset = JSON_Input - Initial_Pivot
716 ! Note: we assume center_in is the Time=0 global coord
717 this%local_offset = center_in - &
718 neko_ale%config%bodies(i)%rot_center
719 ! Set initial position for init_common
720 this%center = center_in
721 end if
722
723 end if
724 j = j + 1
725 end do
726 end if
727 i = i + 1
728 end do
729
730 if (.not. body_found) then
731 call neko_log%message(' ')
732 write(log_buf, '(A,I0,A)') 'Warning: Zone ', zone_id, &
733 ' requested "' // trim(center_type) // &
734 '" center, but is not registered as an ALE body.'
735
736 call neko_log%message(log_buf)
737
738 call neko_log%message('Reverting to FIXED center ' // &
739 'using JSON coordinates.')
740
741 this%moving_center = .false.
742 end if
743
744 end if
745 end if
746 end if
747
748 if ((.not. ale_active) .and. (trim(center_type) == 'pivot' .or. &
749 trim(center_type) == 'body_attached')) then
750
751 call neko_log%message(' ')
752
753 write(log_buf, '(A,I0,A)') "Warning: Zone ", zone_id, &
754 " requested '" // trim(center_type) // "' center, " // &
755 "but ALE is not active."
756 call neko_log%message(log_buf)
757
758 call neko_log%message("pivot and body_attached work " // &
759 "only for ALE simulations.")
760
761 call neko_log%message("Reverting to 'fixed' center " // &
762 "using JSON coordinates.")
763
764 end if
765
766 end subroutine setup_ale_link
767
768end module force_torque
Copy data between host and device (or device and device)
Definition device.F90:72
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Compute the strain rate tensor of a vector field.
ALE Manager: Handles Mesh Motion.
type(ale_manager_t), pointer, public neko_ale
Defines data structures and algorithms for configuring, calculating, and time-integrating the rigid-b...
Defines a boundary condition.
Definition bc.f90:34
Defines a simulation case.
Definition case.f90:34
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:45
real(kind=rp) function, public device_glsum(a_d, n, strm)
Sum a vector of length n.
subroutine, public device_vcross(u1_d, u2_d, u3_d, v1_d, v2_d, v3_d, w1_d, w2_d, w3_d, n, strm)
Compute a cross product (3-d version) assuming vector components etc.
subroutine, public device_masked_gather_copy_0(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
Defines a dirichlet boundary condition.
Definition dirichlet.f90:34
subroutine, public setup_normals(coef, mask, facets, n1, n2, n3, n_pts)
Computes the normals for a given set of boundary points accessed by the mask.
subroutine, public calc_force_array(force1, force2, force3, force4, force5, force6, s11, s22, s33, s12, s13, s23, p, n1, n2, n3, mu, n_pts)
Calculate drag and torque from array of points.
subroutine, public device_calc_force_array(force1, force2, force3, force4, force5, force6, s11, s22, s33, s12, s13, s23, p, n1, n2, n3, mu, n_pts)
Calculate drag and torque from array of points.
Defines a field.
Definition field.f90:34
Implements the force_torque_t type.
subroutine force_torque_compute(this, time)
Compute the force_torque field.
subroutine force_torque_init_from_controllers_properties(this, name, case, order, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value, fluid_name, zone_name, zone_id, center, scale, coef, long_print)
Constructor from components, passing properties to the time_based_controller` components in the base ...
subroutine force_torque_free(this)
Destructor.
subroutine setup_ale_link(this, zone_id, center_type, center_in)
Routine to configure ALE connectivity for force/torque module.
subroutine force_torque_init_from_controllers(this, name, case, order, preprocess_controller, compute_controller, output_controller, fluid_name, zone_id, zone_name, center, scale, coef, long_print)
Constructor from components, passing controllers.
subroutine force_torque_init_common(this, name, fluid_name, zone_id, zone_name, center, scale, coef, long_print, center_type)
Common part of constructors.
subroutine force_torque_init_from_json(this, json, case)
Constructor from json.
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public cadd(a, s, n)
Add a scalar to vector .
Definition math.f90:564
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:627
subroutine, public masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:358
subroutine, public vcross(u1, u2, u3, v1, v2, v3, w1, w2, w3, n)
Compute a cross product assuming vector components etc.
Definition math.f90:814
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Operators.
Definition operators.f90:34
subroutine, public curl(w1, w2, w3, u1, u2, u3, work1, work2, coef, event)
Implements output_controller_t
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:144
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Simulation components are objects that encapsulate functionality that can be fit to a particular comp...
subroutine compute_(this, time)
Dummy compute function.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Defines a vector.
Definition vector.f90:34
State history for time-integration of pivots.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
Generic Dirichlet boundary condition on .
Definition dirichlet.f90:49
A simulation component that computes the force and torque on a given boundary zone.
Base abstract class for simulation components.
A utility type for determining whether an action should be executed based on the current time value....
A struct that contains all info about the time, expand as needed.