Octopus
box_shape.F90
Go to the documentation of this file.
1!! Copyright (C) 2021 M. Oliveira, K. Lively, A. Obzhirov, I. Albar
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module box_shape_oct_m
22 use box_oct_m
24 use debug_oct_m
25 use global_oct_m
26 use math_oct_m
30
31 implicit none
32
33 private
34 public :: &
38
41 type, abstract, extends(box_t) :: box_shape_t
42 private
43 real(real64), allocatable, public :: center(:)
44 type(basis_vectors_t), public :: axes
45 real(real64), allocatable :: bounding_box(:,:)
48 contains
49 procedure :: contains_points => box_shape_contains_points
50 procedure :: bounds => box_shape_bounds
51 procedure(box_shape_shape_contains_points), deferred :: shape_contains_points
52 end type box_shape_t
53
54 abstract interface
55 function box_shape_shape_contains_points(this, nn, xx) result(contained)
56 import :: box_shape_t
57 import :: real64
58 class(box_shape_t), intent(in) :: this
59 integer, intent(in) :: nn
60 real(real64), contiguous, intent(in) :: xx(:,:)
61 logical :: contained(1:nn)
63 end interface
64
65contains
66
67 !--------------------------------------------------------------
68 recursive function box_shape_contains_points(this, nn, xx) result(contained)
69 class(box_shape_t), intent(in) :: this
70 integer, intent(in) :: nn
71 real(real64), contiguous, intent(in) :: xx(:,:)
72 logical :: contained(1:nn)
73
74 ! no push_sub because this function is called very frequently
75
76 contained = this%shape_contains_points(nn, this%axes%from_cartesian(nn, xx))
77
78 end function box_shape_contains_points
79
80 !--------------------------------------------------------------
81 subroutine box_shape_init(this, namespace, dim, center, bounding_box_min, bounding_box_max, axes)
82 class(box_shape_t), intent(inout) :: this
83 type(namespace_t), intent(in) :: namespace
84 integer, intent(in) :: dim
85 real(real64), intent(in) :: center(dim)
86 real(real64), intent(in) :: bounding_box_min(dim)
87 real(real64), intent(in) :: bounding_box_max(dim)
88 real(real64), optional, intent(in) :: axes(dim, dim)
89
90 integer :: idir
91 real(real64) :: normalized_axes(dim, dim)
92
93 this%dim = dim
94
95 safe_allocate(this%center(1:dim))
96 safe_allocate(this%bounding_box_l(1:dim))
97 this%bounding_box_l = m_zero
98
99 this%center(1:dim) = center(1:dim)
100
101 if (present(axes)) then
102 do idir = 1, dim
103 normalized_axes(:, idir) = axes(:, idir)/norm2(axes(:, idir))
104 end do
105 else
106 normalized_axes = diagonal_matrix(dim, m_one)
107 end if
108 this%axes = basis_vectors_t(namespace, dim, normalized_axes)
109
110 if (allocated(this%bounding_box)) then
111 safe_deallocate_a(this%bounding_box)
112 end if
113 safe_allocate(this%bounding_box(1:2, 1:dim))
114 this%bounding_box(1,:) = bounding_box_min + this%center
115 this%bounding_box(2,:) = bounding_box_max + this%center
116
117 end subroutine box_shape_init
118
119 !--------------------------------------------------------------
127 function box_shape_bounds(this, axes) result(bounds)
128 class(box_shape_t), intent(in) :: this
129 class(basis_vectors_t), optional, intent(in) :: axes
130 real(real64) :: bounds(2, this%dim)
131
132 integer :: idir, ib
133 real(real64) :: vertex_red(this%dim), vertex_cart(this%dim)
135 push_sub(box_shape_bounds)
137 if (this%is_inside_out()) then
138 ! The box is unbound.
139 bounds(1, :) = -m_huge
140 bounds(2, :) = m_huge
141 else
142 ! The bounds must be located at the axis-aligned bounding box vertices, so
143 ! we loop over the vertices, convert them to reduced coordinates, and find
144 ! the maximum and minimum coordinates. This algorithm might not be
145 ! optimal, but it will do for now.
146 bounds(1, :) = m_huge
147 bounds(2, :) = -m_huge
148 do idir = 1, this%dim
149 do ib = 1, 2
150 ! Vertex in box reduced coordinates
151 vertex_red = m_zero
152 vertex_red(idir) = this%bounding_box(ib, idir)
153
154 ! Transform vertex to Cartesian coordinates
155 vertex_cart = this%axes%to_cartesian(vertex_red)
156
157 ! Convert to reduced coordinates of the input axes
158 if (present(axes)) then
159 vertex_red = axes%from_cartesian(vertex_cart)
160 else
161 vertex_red = vertex_cart
162 end if
163
164 where (vertex_red < bounds(1,:))
165 bounds(1, :) = vertex_red
166 elsewhere (vertex_red > bounds(2,:))
167 bounds(2, :) = vertex_red
168 end where
169 end do
170 end do
171 end if
172
173 pop_sub(box_shape_bounds)
174 end function box_shape_bounds
175
176 !--------------------------------------------------------------
177 subroutine box_shape_end(this)
178 class(box_shape_t), intent(inout) :: this
179
180 safe_deallocate_a(this%center)
181 safe_deallocate_a(this%bounding_box)
182 safe_deallocate_a(this%bounding_box_l)
183
184 end subroutine box_shape_end
185
186end module box_shape_oct_m
187
188!! Local Variables:
189!! mode: f90
190!! coding: utf-8
191!! End:
subroutine, public box_shape_init(this, namespace, dim, center, bounding_box_min, bounding_box_max, axes)
Definition: box_shape.F90:175
recursive logical function, dimension(1:nn) box_shape_contains_points(this, nn, xx)
Definition: box_shape.F90:162
subroutine, public box_shape_end(this)
Definition: box_shape.F90:271
real(real64) function, dimension(2, this%dim) box_shape_bounds(this, axes)
Returns the bounding box of the shape. This is a bounding box aligned with some given axes (if presen...
Definition: box_shape.F90:221
real(real64), parameter, public m_huge
Definition: global.F90:205
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public m_one
Definition: global.F90:188
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
Vectors defining a basis in a vector space. This class provides methods to convert vector coordinates...
class to tell whether a point is inside or outside
Definition: box.F90:141
Base class for more specialized boxes that are defined by a shape and have a center and basis vectors...
Definition: box_shape.F90:134