30 use,
intrinsic :: iso_fortran_env
55 type(stencil_t),
intent(inout) :: this
56 integer,
intent(in) :: dim
57 class(coordinate_system_t),
intent(in) :: coord_system
59 real(real64) :: theta(dim), basis_vectors(dim, dim)
64 integer,
allocatable :: cand_vecs(:,:), idx(:)
65 real(real64),
allocatable :: cand_norms(:)
66 integer :: n_cand, max_cand
70 integer :: v1_xy, v1_xz, v1_yz
71 integer :: v2_xy, v2_xz, v2_yz
72 integer :: v3_xy, v3_xz, v3_yz
73 integer :: i1, i2, i3, i, j, k
79 this%stargeneral%narms = 0
80 this%stargeneral%arms = 0
88 select type (coord_system)
90 basis_vectors = coord_system%basis%vectors
92 message(1) =
"Stencil stargeneral can currently only be used with affine coordinate systems."
98 theta(1) =
acos(dot_product(basis_vectors(:, 1), basis_vectors(:, 2)))
101 this%stargeneral%narms = this%stargeneral%narms + 1
103 this%stargeneral%arms(this%stargeneral%narms, 1:dim) = arm
105 this%stargeneral%narms = this%stargeneral%narms + 1
107 this%stargeneral%arms(this%stargeneral%narms, 1:dim) = arm
118 theta(1) =
acos(dot_product(basis_vectors(:, 1), basis_vectors(:, 2)))
119 if (abs(theta(1) -
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
121 theta(2) =
acos(dot_product(basis_vectors(:, 2), basis_vectors(:, 3)))
122 if (abs(theta(2)-
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
124 theta(3) =
acos(dot_product(basis_vectors(:, 3), basis_vectors(:, 1)))
125 if (abs(theta(3) -
m_pi*
m_half) > 1e-8_real64) this%stargeneral%narms = this%stargeneral%narms + 1
129 if (this%stargeneral%narms == 0)
then
146 safe_allocate(cand_vecs(3, max_cand))
147 safe_allocate(cand_norms(max_cand))
148 safe_allocate(idx(max_cand))
155 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
160 if (ii == 0 .and. jj == 0 .and. kk /= 0) cycle
163 if (.not. active(1) .and. kk == 0) cycle
164 if (.not. active(3) .and. ii == 0) cycle
165 if (.not. active(2) .and. jj == 0) cycle
170 if (ii == 0 .and. jj > 0) cycle
171 if (ii == 0 .and. jj == 0 .and. kk > 0) cycle
173 norm = sum((ii*basis_vectors(:, 1) + jj*basis_vectors(:, 2) + kk*basis_vectors(:, 3))**2)
176 cand_vecs(1, n_cand) = ii
177 cand_vecs(2, n_cand) = jj
178 cand_vecs(3, n_cand) = kk
179 cand_norms(n_cand) = norm
194 if (this%stargeneral%narms == 1)
then
198 if (active(1) .and. cand_vecs(1,i1)*cand_vecs(2,i1) /= 0) n_found = 1
199 if (active(2) .and. cand_vecs(1,i1)*cand_vecs(3,i1) /= 0) n_found = 1
200 if (active(3) .and. cand_vecs(2,i1)*cand_vecs(3,i1) /= 0) n_found = 1
202 if (n_found == 1)
then
203 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
212 if (this%stargeneral%narms == 2)
then
219 if ( (cand_vecs(2, i1) * cand_vecs(3, i2) - cand_vecs(3, i1) * cand_vecs(2, i2)) /= 0 .or. &
220 (cand_vecs(3, i1) * cand_vecs(1, i2) - cand_vecs(1, i1) * cand_vecs(3, i2)) /= 0 .or. &
221 (cand_vecs(1, i1) * cand_vecs(2, i2) - cand_vecs(2, i1) * cand_vecs(1, i2)) /= 0 )
then
223 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
224 this%stargeneral%arms(2, 1:3) = cand_vecs(:, i2)
229 if (n_found == 2)
exit
234 if (this%stargeneral%narms == 3)
then
251 v1_xy = cand_vecs(1, i1) * cand_vecs(2, i1)
252 v1_xz = cand_vecs(1, i1) * cand_vecs(3, i1)
253 v1_yz = cand_vecs(2, i1) * cand_vecs(3, i1)
255 v2_xy = cand_vecs(1, i2) * cand_vecs(2, i2)
256 v2_xz = cand_vecs(1, i2) * cand_vecs(3, i2)
257 v2_yz = cand_vecs(2, i2) * cand_vecs(3, i2)
259 v3_xy = cand_vecs(1, i3) * cand_vecs(2, i3)
260 v3_xz = cand_vecs(1, i3) * cand_vecs(3, i3)
261 v3_yz = cand_vecs(2, i3) * cand_vecs(3, i3)
263 det = v1_xy * ( v2_xz * v3_yz - v3_xz * v2_yz ) &
264 - v1_xz * ( v2_xy * v3_yz - v3_xy * v2_yz ) &
265 + v1_yz * ( v2_xy * v3_xz - v3_xy * v2_xz )
268 this%stargeneral%arms(1, 1:3) = cand_vecs(:, i1)
269 this%stargeneral%arms(2, 1:3) = cand_vecs(:, i2)
270 this%stargeneral%arms(3, 1:3) = cand_vecs(:, i3)
275 if (n_found == 3)
exit
277 if (n_found == 3)
exit
281 if (n_found < this%stargeneral%narms)
then
282 write(
message(1),
'(a, i0, a, i0)')
'Stencil stargeneral could not find enough independent arms. Found ', &
283 n_found,
' needed ', this%stargeneral%narms
287 safe_deallocate_a(cand_vecs)
288 safe_deallocate_a(cand_norms)
289 safe_deallocate_a(idx)
298 integer,
intent(in) :: dim
299 integer,
intent(in) :: order
307 n = n + 2 * order * this%stargeneral%narms
318 integer,
intent(in) :: dir
319 integer,
intent(in) :: order
326 if (dir >= 1 .and. dir <= 3)
then
343 integer,
intent(in) :: dim
344 integer,
intent(in) :: order
347 logical :: got_center
361 this%points(i, n) = j
370 this%points(i, n) = j
376 do i = 1, this%stargeneral%narms
378 this%points(1:2, n) = this%stargeneral%arms(i, 1:2)*j
399 this%points(i, n) = j
405 do i = 1, this%stargeneral%narms
407 this%points(1:3, n) = this%stargeneral%arms(i, 1:3)*j
424 integer,
intent(in) :: dim
425 integer,
intent(in) :: order
426 integer,
intent(out) :: pol(:,:)
428 integer :: i, j, n, j1
429 logical :: zeros_treated(dim)
455 do i = 1, this%stargeneral%narms
457 if (sum(this%stargeneral%arms(i,1:dim)) == 0)
then
458 pol(1:2, n) = (/j,1/)
460 pol(1:2, n) = (/1,j/)
477 zeros_treated = .false.
478 do i = 1, this%stargeneral%narms
479 if (this%stargeneral%arms(i, 1) == 0)
then
482 pol(1:3, n) = (/0, 1, j1/)
484 zeros_treated(1) = .
true.
485 else if (this%stargeneral%arms(i, 2) == 0)
then
488 pol(1:3, n) = (/j1, 0, 1/)
490 zeros_treated(2) = .
true.
491 else if (this%stargeneral%arms(i, 3) == 0)
then
494 pol(1:3, n) = (/1, j1, 0/)
496 zeros_treated(3) = .
true.
500 do i = 1, this%stargeneral%narms - count(zeros_treated)
501 if (.not. zeros_treated(1))
then
504 pol(1:3, n) = (/0, 1, j1/)
506 zeros_treated(1) = .
true.
507 else if (.not. zeros_treated(2))
then
510 pol(1:3, n) = (/j1, 0, 1/)
512 zeros_treated(2) = .
true.
513 else if (.not. zeros_treated(3))
then
516 pol(1:3, n) = (/1, j1, 0/)
518 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
This module is intended to contain "only mathematical" functions and procedures.
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.