Я пытаюсь сделать гибкий пользовательский интерфейс для численного решения. Проблема в том, что я не могу сформулировать, как реализовать динамический выбор геометрии исходного состояния (прямоугольник, сфера и т. Д.). Я пытался использовать абстрактный класс initial_conditions_geometry
как родитель с ребенком классов rectangular
и sphere
, которые указывают определенные атрибуты и реализовать метод in_bounds
для геометрии:Динамический выбор типа объекта
type ,abstract :: initial_conditions_geometry
contains
procedure (in_bounds) ,deferred :: in_bounds
end type
abstract interface
logical function in_bounds(this,coordinates)
import :: rkind
import :: initial_conditions_geometry
class(initial_conditions_geometry) ,intent(in) :: this
real(rkind) ,dimension (:) ,intent(in) :: coordinates
end function in_bounds
end interface
type ,extends(initial_conditions_geometry) :: rectangular
integer ,dimension(:,:) ,allocatable :: rectangular_bounds
contains
procedure :: in_bounds => in_bounds_rectangular
end type
type ,extends(initial_conditions_geometry) :: sphere
integer ,dimension(:,:) ,allocatable :: sphere_bounds
integer ,dimension(:) ,allocatable :: sphere_center
contains
procedure :: in_bounds => in_bounds_sphere
end type
interface rectangular
procedure constructor_rectangular
end interface
interface sphere
procedure constructor_sphere
end interface
Вот initial_conditions_layer
определение класса, который включает в себя первоначальную геометрию и распределение условие:
type :: initial_conditions_layer
class(initial_conditions_geometry) ,allocatable :: layer_geometry
type(initial_conditions_distribution) :: distributor
end type
interface initial_conditions_layer
procedure constructor
end interface
Возникает вопрос: как можно управлять, чтобы создать constuctor для initial_conditions_layer
, динамически (в зависимости от типа геометрии в некотором текстовом файле) устанавливает layer_geometry
типа (прямоугольный, сферы и т. д.)?
Редактировать Возможно, полезно добавить некоторые из моих попыток решить эту проблему. Я пытался организовать конструктор для initial_conditions_layer объекта следующим образом:
type(initial_conditions_layer) function constructor(dimensions,layer_number,initial_conditions_data_file_unit)
integer ,intent(in) :: layer_number
integer ,intent(in) :: initial_conditions_data_file_unit
integer ,intent(in) :: dimensions
character(len=20) :: layer_distribution_type
character(len=20) :: layer_geometry_name
call get_layer_properties(initial_conditions_data_file_unit,layer_number,layer_geometry_name,layer_distribution_type)
select case(layer_geometry_name)
case('rectangular')
allocate(rectangular::constructor%layer_geometry)
case('sphere')
allocate(sphere::constructor%layer_geometry)
end select
select type(constructor%layer_geometry)
type is(rectangular)
constructor%layer_geometry = rectangular()
type is(sphere)
constructor%layer_geometry = sphere()
end select
end function
Но это требует associate_name в выберите тип конструкции. Associate_name должно быть указателем на initial_conditions_geometry, но нельзя установить атрибут target в поле производного типа.
Вы имеете в виду что-то вроде (извините код комментария и неявный материал): 'if (geom.eq.'rectangle ') allocate (rectangular :: layer% layer_geometry)'? Это явно не полный ответ, но мне интересно, не хватает ли я чего-то. – francescalus
Да! Но я не нашел способ реализовать его в конструкции 'select type', потому что для этого требуется указатель' associate-name' .. И я не могу объявить конструктор переменной class (initial_conditions_geometry), allocatable, указатель :: geometry' внутри для этого требуется установить целевой атрибут для 'layer_geometry', но это запрещено стандартом. –
Думаю, вам придется отредактировать свои попытки в вопросе, потому что, боюсь, я не буду следовать. Но в конструкторе для 'initial_conditions_layer', на что вы пытаетесь« выбрать тип »? – francescalus