30 use,
intrinsic :: iso_fortran_env
54 type(stencil_t),
intent(inout) :: this
55 integer,
intent(in) :: dim
56 class(coordinate_system_t),
intent(in) :: coord_system
58 real(real64) :: theta(dim), basis_vectors(dim, dim)
63 integer,
allocatable :: cand_vecs(:,:), idx(:)
64 real(real64),
allocatable :: cand_norms(:)
65 integer :: n_cand, max_cand
69 integer :: v1_xy, v1_xz, v1_yz
70 integer :: v2_xy, v2_xz, v2_yz
71 integer :: v3_xy, v3_xz, v3_yz
72 integer :: i1, i2, i3, i, j, k
78 this%stargeneral%narms = 0
79 this%stargeneral%arms = 0
87 select type (coord_system)
89 basis_vectors = coord_system%basis%vectors
91 message(1) =
"Stencil stargeneral can currently only be used with affine coordinate systems."
97 theta(1) =
acos(dot_product(basis_vectors(:, 1), basis_vectors(:, 2)))
100 this%stargeneral%narms = this%stargeneral%narms + 1
102 this%stargeneral%arms(this%stargeneral%narms, 1:dim) = arm
104 this%stargeneral%narms = this%stargeneral%narms + 1
106 this%stargeneral%arms(this%stargeneral%narms, 1:dim) = arm
117 theta(1) =
acos(dot_product(basis_vectors(:, 1), basis_vectors(:, 2)))
118 if (abs(theta(1) -
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
120 theta(2) =
acos(dot_product(basis_vectors(:, 2), basis_vectors(:, 3)))
121 if (abs(theta(2)-
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
123 theta(3) =
acos(dot_product(basis_vectors(:, 3), basis_vectors(:, 1)))
124 if (abs(theta(3) -
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
128 if (this%stargeneral%narms == 0)
then
145 safe_allocate(cand_vecs(3, max_cand))
146 safe_allocate(cand_norms(max_cand))
147 safe_allocate(idx(max_cand))
154 if (ii == 0 .and. jj == 0 .and. kk == 0) cycle
157 if (ii /= 0 .and. jj == 0 .and. kk == 0) cycle
158 if (ii == 0 .and. jj /= 0 .and. kk == 0) cycle
159 if (ii == 0 .and. jj == 0 .and. kk /= 0) cycle
162 if (.not. active(1) .and. kk == 0) cycle
163 if (.not. active(3) .and. ii == 0) cycle
164 if (.not. active(2) .and. jj == 0) cycle
169 if (ii == 0 .and. jj > 0) cycle
170 if (ii == 0 .and. jj == 0 .and. kk > 0) cycle
172 norm = sum((ii*basis_vectors(:, 1) + jj*basis_vectors(:, 2) + kk*basis_vectors(:, 3))**2)
175 cand_vecs(1, n_cand) = ii
176 cand_vecs(2, n_cand) = jj
177 cand_vecs(3, n_cand) = kk
178 cand_norms(n_cand) = norm
193 if (this%stargeneral%narms == 1)
then
197 if (active(1) .and. cand_vecs(1,i1)*cand_vecs(2,i1) /= 0) n_found = 1
198 if (active(2) .and. cand_vecs(1,i1)*cand_vecs(3,i1) /= 0) n_found = 1
199 if (active(3) .and. cand_vecs(2,i1)*cand_vecs(3,i1) /= 0) n_found = 1
201 if (n_found == 1)
then
202 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
211 if (this%stargeneral%narms == 2)
then
218 if ( (cand_vecs(2, i1) * cand_vecs(3, i2) - cand_vecs(3, i1) * cand_vecs(2, i2)) /= 0 .or. &
219 (cand_vecs(3, i1) * cand_vecs(1, i2) - cand_vecs(1, i1) * cand_vecs(3, i2)) /= 0 .or. &
220 (cand_vecs(1, i1) * cand_vecs(2, i2) - cand_vecs(2, i1) * cand_vecs(1, i2)) /= 0 )
then
222 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
223 this%stargeneral%arms(2, 1:3) = cand_vecs(:, i2)
228 if (n_found == 2)
exit
233 if (this%stargeneral%narms == 3)
then
250 v1_xy = cand_vecs(1, i1) * cand_vecs(2, i1)
251 v1_xz = cand_vecs(1, i1) * cand_vecs(3, i1)
252 v1_yz = cand_vecs(2, i1) * cand_vecs(3, i1)
254 v2_xy = cand_vecs(1, i2) * cand_vecs(2, i2)
255 v2_xz = cand_vecs(1, i2) * cand_vecs(3, i2)
256 v2_yz = cand_vecs(2, i2) * cand_vecs(3, i2)
258 v3_xy = cand_vecs(1, i3) * cand_vecs(2, i3)
259 v3_xz = cand_vecs(1, i3) * cand_vecs(3, i3)
260 v3_yz = cand_vecs(2, i3) * cand_vecs(3, i3)
262 det = v1_xy * ( v2_xz * v3_yz - v3_xz * v2_yz ) &
263 - v1_xz * ( v2_xy * v3_yz - v3_xy * v2_yz ) &
264 + v1_yz * ( v2_xy * v3_xz - v3_xy * v2_xz )
267 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
268 this%stargeneral%arms(2, 1:3) = cand_vecs(:, i2)
269 this%stargeneral%arms(3, 1:3) = cand_vecs(:, i3)
274 if (n_found == 3)
exit
276 if (n_found == 3)
exit
280 if (n_found < this%stargeneral%narms)
then
281 write(
message(1),
'(a, i0, a, i0)')
'Stencil stargeneral could not find enough independent arms. Found ', &
282 n_found,
' needed ', this%stargeneral%narms
286 safe_deallocate_a(cand_vecs)
287 safe_deallocate_a(cand_norms)
288 safe_deallocate_a(idx)
297 integer,
intent(in) :: dim
298 integer,
intent(in) :: order
306 n = n + 2 * order * this%stargeneral%narms
317 integer,
intent(in) :: dir
318 integer,
intent(in) :: order
325 if (dir >= 1 .or. dir <= 3)
then
342 integer,
intent(in) :: dim
343 integer,
intent(in) :: order
346 logical :: got_center
360 this%points(i, n) = j
369 this%points(i, n) = j
375 do i = 1, this%stargeneral%narms
377 this%points(1:2, n) = this%stargeneral%arms(i, 1:2)*j
398 this%points(i, n) = j
404 do i = 1, this%stargeneral%narms
406 this%points(1:3, n) = this%stargeneral%arms(i, 1:3)*j
423 integer,
intent(in) :: dim
424 integer,
intent(in) :: order
425 integer,
intent(out) :: pol(:,:)
427 integer :: i, j, n, j1
428 logical :: zeros_treated(dim)
454 do i = 1, this%stargeneral%narms
456 if (sum(this%stargeneral%arms(i,1:dim)) == 0)
then
457 pol(1:2, n) = (/j,1/)
459 pol(1:2, n) = (/1,j/)
476 zeros_treated = .false.
477 do i = 1, this%stargeneral%narms
478 if (this%stargeneral%arms(i, 1) == 0)
then
481 pol(1:3, n) = (/0, 1, j1/)
483 zeros_treated(1) = .
true.
484 else if (this%stargeneral%arms(i, 2) == 0)
then
487 pol(1:3, n) = (/j1, 0, 1/)
489 zeros_treated(2) = .
true.
490 else if (this%stargeneral%arms(i, 3) == 0)
then
493 pol(1:3, n) = (/1, j1, 0/)
495 zeros_treated(3) = .
true.
499 do i = 1, this%stargeneral%narms - count(zeros_treated)
500 if (.not. zeros_treated(1))
then
503 pol(1:3, n) = (/0, 1, j1/)
505 zeros_treated(1) = .
true.
506 else if (.not. zeros_treated(2))
then
509 pol(1:3, n) = (/j1, 0, 1/)
511 zeros_treated(2) = .
true.
512 else if (.not. zeros_treated(3))
then
515 pol(1:3, n) = (/1, j1, 0/)
517 zeros_treated(3) = .
true.
double acos(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_pi
some mathematical constants
real(real64), parameter, public m_half
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
This module is intended to contain "only mathematical" functions and procedures.
This module defines stencils used in Octopus.
subroutine, public stencil_allocate(this, dim, size)
subroutine, public stencil_init_center(this)
This module defines routines, generating operators for a generalized star stencil.
subroutine, public stencil_stargeneral_get_arms(this, dim, coord_system)
Finds the direction of the arms of the star-general stencil as described in Natan et al....
subroutine, public stencil_stargeneral_pol_lapl(this, dim, order, pol)
integer function, public stencil_stargeneral_extent(dir, order)
Returns maximum extension of the stencil in spatial direction dir = 1, 2, 3 for a given discretizatio...
subroutine, public stencil_stargeneral_get_lapl(this, dim, order)
integer function, public stencil_stargeneral_size_lapl(this, dim, order)
The class representing the stencil, which is used for non-local mesh operations.