68 integer,
parameter :: &
69 MEDIUM_PARALLELEPIPED = 1, &
75 type(space_t) :: space
76 real(real64) :: ep_factor
77 real(real64) :: mu_factor
78 real(real64) :: sigma_e_factor
79 real(real64) :: sigma_m_factor
80 integer :: edge_profile
81 type(output_t) :: outp
83 type(multicomm_t) :: mc
84 type(single_medium_box_t) :: medium_box
100 procedure linear_medium_constructor
111 class(linear_medium_t),
pointer :: sys
112 type(namespace_t),
intent(in) :: namespace
130 class(linear_medium_t),
target,
intent(inout) :: this
131 type(namespace_t),
intent(in) :: namespace
133 integer :: nlines, ncols,n_points, n_global_points
134 integer(int64) :: index_range(4)
135 integer,
allocatable :: tmp(:)
142 this%namespace = namespace
143 this%space =
space_t(this%namespace)
147 index_range(1) = this%gr%np_global
150 index_range(4) = 100000
154 index_range, (/ 5000, 1, 1, 1 /))
174 if (
parse_block(namespace,
'LinearMediumProperties', blk) == 0)
then
177 if (nlines /= 1)
then
188 write(
message(1),
'(a,es9.2)')
'Box epsilon factor: ', this%ep_factor
189 write(
message(2),
'(a,es9.2)')
'Box mu factor: ', this%mu_factor
190 write(
message(3),
'(a,es9.2)')
'Box electric sigma: ', this%sigma_e_factor
191 write(
message(4),
'(a,es9.2)')
'Box magnetic sigma: ', this%sigma_m_factor
198 message(1) =
'You must specify the properties of your linear medium through the LinearMediumProperties block.'
214 call parse_variable(namespace,
'LinearMediumEdgeProfile', option__linearmediumedgeprofile__edged, this%edge_profile)
215 if (this%edge_profile == option__linearmediumedgeprofile__edged)
then
216 write(
message(1),
'(a,a)')
'Box shape: ',
'edged'
217 else if (this%edge_profile == option__linearmediumedgeprofile__smooth)
then
218 write(
message(1),
'(a,a)')
'Box shape: ',
'smooth'
222 allocate(this%supported_interactions(0))
224 call this%quantities%add(
quantity_t(
"permitivity", updated_on_demand = .false., always_available = .
true.))
225 call this%quantities%add(
quantity_t(
"permeability", updated_on_demand = .false., always_available = .
true.))
226 call this%quantities%add(
quantity_t(
"E conductivity", updated_on_demand = .false., always_available = .
true.))
227 call this%quantities%add(
quantity_t(
"M conductivity", updated_on_demand = .false., always_available = .
true.))
234 this%outp%iter_dir, this%medium_box%points_map, this%medium_box%ep, &
235 this%medium_box%mu, this%medium_box%c)
237 if (this%medium_box%check_medium_points)
then
238 safe_allocate(tmp(1:this%gr%np))
240 write(
message(1),
'(a, a, a)')
'Check of points inside surface of medium ', trim(this%medium_box%filename),
":"
243 write(
message(1),
'(a, I8)')
'Number of points inside medium (normal coordinates):', &
244 this%medium_box%global_points_number
245 write(
message(2),
'(a, I8)')
'Number of points inside medium (rescaled coordinates):', n_global_points
248 safe_deallocate_a(tmp)
263 select type (interaction)
265 message(1) =
"Trying to initialize an unsupported interaction by a linear medium."
282 select type (interaction)
285 partner%gr, partner%space, partner%namespace)
288 medium_box_grid => partner%medium_box%to_grid(partner%gr)
291 call regridding%do_transfer(interaction%medium_box%aux_ep, medium_box_grid%aux_ep)
292 call regridding%do_transfer(interaction%medium_box%aux_mu, medium_box_grid%aux_mu)
293 call regridding%do_transfer(interaction%medium_box%ep, medium_box_grid%ep)
294 call regridding%do_transfer(interaction%medium_box%mu, medium_box_grid%mu)
295 call regridding%do_transfer(interaction%medium_box%c, medium_box_grid%c)
296 call regridding%do_transfer(interaction%medium_box%sigma_e, medium_box_grid%sigma_e)
297 call regridding%do_transfer(interaction%medium_box%sigma_m, medium_box_grid%sigma_m)
299 safe_deallocate_p(regridding)
300 safe_deallocate_p(medium_box_grid)
302 message(1) =
"Trying to initialize an unsupported interaction by a linear medium."
322 character(len=:),
allocatable,
intent(out) :: updated_quantities(:)
335 real(real64),
intent(in) :: tol
353 select type (interaction)
357 message(1) =
"Unsupported interaction."
369 integer :: restart_file_unit, ierr
375 message(1) =
"Linear medium system "//trim(this%namespace%get())//
" will only write a dummy restart file."
379 restart_file_unit = restart%open(
'restart_linear_medium')
380 if (restart%do_i_write())
write(restart_file_unit, *)
'Linear medium restart file'
381 call restart%close(restart_file_unit)
382 message(1) =
"Successfully wrote restart data for system "//trim(this%namespace%get())
385 message(1) =
"Could not write restart data for system "//trim(this%namespace%get())
400 integer :: restart_file_unit, ierr
405 restart_file_unit = restart%open(
'restart_linear_medium')
407 call restart%close(restart_file_unit)
416 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
454 type(
grid_t),
intent(in) :: gr
456 integer :: ip, ip_in, ip_bd, idim
457 integer,
allocatable :: tmp_points_map(:), tmp_bdry_map(:)
458 real(real64) :: bounds(2,gr%box%dim), xx(gr%box%dim)
465 safe_allocate(tmp_points_map(1:gr%np))
466 safe_allocate(tmp_bdry_map(1:gr%np))
473 medium_box%global_points_number, tmp_points_map)
478 bounds(1,idim) = medium_box%center(idim) - medium_box%lsize(idim)/
m_two
479 bounds(2,idim) = medium_box%center(idim) + medium_box%lsize(idim)/
m_two
484 xx(1:3) = gr%x(ip, 1:3)
488 tmp_points_map(ip_in) = ip
492 tmp_bdry_map(ip_bd) = ip
496 medium_box%points_number = ip_in
497 medium_box%bdry_number = ip_bd
499 safe_allocate(medium_box%bdry_map(1:medium_box%bdry_number))
500 medium_box%bdry_map = 0
501 medium_box%bdry_map = tmp_bdry_map(1:medium_box%bdry_number)
505 medium_box%points_map(:) = tmp_points_map(1:medium_box%points_number)
508 safe_deallocate_a(tmp_points_map)
509 safe_deallocate_a(tmp_bdry_map)
517 real(real64),
intent(in) :: xx(:)
518 real(real64),
intent(in) :: bounds(:,:)
521 if ((xx(1) >= bounds(1,1)) .and. (xx(1) <= bounds(2,1)) .and. &
522 (xx(2) >= bounds(1,2)) .and. (xx(2) <= bounds(2,2)) .and. &
523 (xx(3) >= bounds(1,3)) .and. (xx(3) <= bounds(2,3)) )
then
529 logical pure function check_point_on_bounds(xx, bounds) result (check)
530 real(real64),
intent(in) :: xx(:)
531 real(real64),
intent(in) :: bounds(:,:)
534 if (
is_close(xx(1), bounds(1,1)) .and. (xx(2) >= bounds(1,2) .and. xx(3) >= bounds(1,3)) &
535 .and. (xx(2) <= bounds(2,2) .and. xx(3) <= bounds(2,3)) .or. &
536 is_close(xx(2), bounds(1,2)) .and. (xx(1) >= bounds(1,1) .and. xx(3) >= bounds(1,3)) &
537 .and. (xx(1) <= bounds(2,1) .and. xx(3) <= bounds(2,3)) .or. &
538 is_close(xx(3), bounds(1,3)) .and. (xx(1) >= bounds(1,1) .and. xx(2) >= bounds(1,2)) &
539 .and. (xx(1) <= bounds(2,1) .and. xx(2) <= bounds(2,2)) .or. &
540 is_close(xx(1), bounds(2,1)) .and. (xx(2) >= bounds(1,2) .and. xx(3) >= bounds(1,3)) &
541 .and. (xx(2) <= bounds(2,2) .and. xx(3) <= bounds(2,3)) .or. &
542 is_close(xx(2), bounds(2,2)) .and. (xx(1) >= bounds(1,1) .and. xx(3) >= bounds(1,3)) &
543 .and. (xx(1) <= bounds(2,1) .and. xx(3) <= bounds(2,3)) .or. &
544 is_close(xx(3), bounds(2,3)) .and. (xx(1) >= bounds(1,1) .and. xx(2) >= bounds(1,2)) &
545 .and. (xx(1) <= bounds(2,1) .and. xx(2) <= bounds(2,2)) )
then
557 type(single_medium_box_t),
intent(inout) :: medium_box
558 type(grid_t),
intent(in) :: gr
560 integer :: ip, ip_in, ip_bd, ipp
561 real(real64) :: xx(gr%box%dim), xxp(gr%box%dim), dd, dd_max, dd_min
562 real(real64),
allocatable :: tmp(:), tmp_grad(:,:)
566 call profiling_in(
'GET_LIN_MEDIUM_EM_PROP')
568 safe_allocate(tmp(1:gr%np_part))
569 safe_allocate(tmp_grad(1:gr%np_part, 1:gr%box%dim))
570 dd_max = max(2*gr%spacing(1), 2*gr%spacing(2), 2*gr%spacing(3))
572 do ip_in = 1, medium_box%points_number
573 ip = medium_box%points_map(ip_in)
574 if (this%edge_profile == option__linearmediumedgeprofile__smooth)
then
575 assert(
allocated(medium_box%bdry_map))
577 xx(1:3) = gr%x(ip,1:3)
580 do ip_bd = 1, medium_box%bdry_number
581 ipp = medium_box%bdry_map(ip_bd)
582 xxp(1:3) = gr%x(ipp,1:3)
583 dd = norm2(xx(1:3) - xxp(1:3))
584 if (dd < dd_min) dd_min = dd
587 medium_box%ep(ip_in) = p_ep + ((p_ep * this%ep_factor - p_ep) &
588 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max))))
589 medium_box%mu(ip_in) = p_mu + ((p_mu * this%mu_factor - p_mu) &
590 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max))))
591 medium_box%c(ip_in) = m_one/
sqrt(medium_box%ep(ip_in)*medium_box%mu(ip_in))
592 medium_box%sigma_e(ip_in) = this%sigma_e_factor &
593 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max)))
594 medium_box%sigma_m(ip_in) = this%sigma_m_factor &
595 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max)))
597 else if (this%edge_profile == option__linearmediumedgeprofile__edged)
then
599 medium_box%ep(ip_in) = p_ep * this%ep_factor
600 medium_box%mu(ip_in) = p_mu * this%mu_factor
601 medium_box%c(ip_in) = m_one/
sqrt(medium_box%ep(ip_in)*medium_box%mu(ip_in))
602 medium_box%sigma_e(ip_in) = this%sigma_e_factor
603 medium_box%sigma_m(ip_in) = this%sigma_m_factor
609 do ip_in = 1, medium_box%points_number
610 ip = medium_box%points_map(ip_in)
611 tmp(ip)= medium_box%ep(ip_in)
613 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
614 do ip_in = 1, medium_box%points_number
615 ip = medium_box%points_map(ip_in)
616 medium_box%aux_ep(ip_in, :) = tmp_grad(ip, :)/(m_four * medium_box%ep(ip_in))
620 do ip_in = 1, medium_box%points_number
621 ip = medium_box%points_map(ip_in)
622 tmp(ip) = medium_box%mu(ip_in)
624 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
625 do ip_in = 1, medium_box%points_number
626 ip = medium_box%points_map(ip_in)
627 medium_box%aux_mu(ip_in, :) = tmp_grad(ip, :)/(m_four * medium_box%mu(ip_in))
632 safe_deallocate_a(tmp)
633 safe_deallocate_a(tmp_grad)
635 call profiling_out(
'GET_LIN_MEDIUM_EM_PROP')
643 character(len=256),
intent(in) :: filename
644 class(mesh_t),
intent(in) :: mesh
645 integer,
intent(out) :: n_points
646 integer,
intent(out) :: global_points_number
647 integer,
intent(inout) :: tmp_map(:)
648 real(real64),
optional,
intent(in) :: scale_factor
651 real(real64) :: xx(3)
652 type(cgal_polyhedra_t) :: cgal_poly
656 call profiling_in(
'GET_POINTS_MAP_FROM_FILE')
658 call cgal_polyhedron_init(cgal_poly, trim(filename), verbose = .false.)
662 if (
present(scale_factor))
then
663 xx(1:3) = scale_factor * mesh%x(ip, 1:3)
665 xx(1:3) = mesh%x(ip, 1:3)
667 if (cgal_polyhedron_point_inside(cgal_poly, xx(1), xx(2), xx(3)))
then
673 call cgal_polyhedron_end(cgal_poly)
675 call mpi_world%allreduce(ip_in, global_points_number, 1, mpi_integer, mpi_sum)
677 call profiling_out(
'GET_POINTS_MAP_FROM_FILE')
686 type(single_medium_box_t),
intent(inout) :: medium_box
687 type(namespace_t),
intent(in) :: namespace
689 integer :: nlines, ncols, idim
708 if (.not. varinfo_valid_option(
'LinearMediumBoxShape', medium_box%box_shape))
then
709 call messages_input_error(namespace,
'LinearMediumBoxShape')
712 select case (medium_box%box_shape)
728 if (parse_block(namespace,
'LinearMediumBoxSize', blk) == 0)
then
729 call messages_print_with_emphasis(msg=trim(
'Linear Medium box center and size:'), namespace=namespace)
731 nlines = parse_block_n(blk)
732 if (nlines /= 1)
then
733 call messages_input_error(namespace,
'LinearMediumBoxSize',
'should consist of one line')
735 ncols = parse_block_cols(blk, 0)
737 call messages_input_error(namespace,
'LinearMediumBoxSize',
'should consist of six columns')
740 call parse_block_float(blk, 0, idim-1, medium_box%center(idim))
741 call parse_block_float(blk, 0, idim+2, medium_box%lsize(idim))
743 write(message(1),
'(a,es9.2,a,es9.2,a,es9.2)')
'Box center: ', medium_box%center(1),
' | ',&
744 medium_box%center(2),
' | ', medium_box%center(3)
745 write(message(2),
'(a,es9.2,a,es9.2,a,es9.2)')
'Box size : ', medium_box%lsize(1),
' | ', &
746 medium_box%lsize(2),
' | ', medium_box%lsize(3)
747 write(message(3),
'(a)')
""
748 call messages_info(3)
749 call parse_block_end(blk)
751 call messages_print_with_emphasis(namespace=namespace)
753 message(1) =
"For parallelepiped box shapes, you must provide a LinearMediumBoxSize block."
754 call messages_fatal(1, namespace=namespace)
764 if (parse_is_defined(namespace,
'LinearMediumBoxFile'))
then
765 call parse_variable(namespace,
'LinearMediumBoxFile',
'mediumboxfile', medium_box%filename)
767 message(1) =
"When using box_file as the box shape, you must provide a filename through the LinearMediumBoxFile variable."
768 call messages_fatal(1, namespace=namespace)
780 call parse_variable(namespace,
'CheckPointsMediumFromFile', .false., medium_box%check_medium_points)
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
logical pure function check_point_on_bounds(xx, bounds)
logical pure function check_point_in_bounds(xx, bounds)
This module implements the basic elements defining algorithms.
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
This module implements the underlying real-space grid.
subroutine, public grid_init_stage_1(gr, namespace, space, symm, latt, n_sites, site_position)
First stage of the grid initialization.
subroutine, public grid_init_stage_2(gr, namespace, space, mc, qvector)
Second stage of the grid initialization.
subroutine, public grid_end(gr)
finalize a grid object
integer, parameter, public linear_medium_to_em_field
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
This module defines a linear medium for use in classical electrodynamics calculations.
subroutine linear_medium_initialize(this)
logical function linear_medium_is_tolerance_reached(this, tol)
integer, parameter medium_parallelepiped
subroutine linear_medium_copy_quantities_to_interaction(partner, interaction)
subroutine linear_medium_restart_write_data(this)
class(linear_medium_t) function, pointer linear_medium_constructor(namespace)
The factory routine (or constructor) allocates a pointer of the corresponding type and then calls the...
logical function linear_medium_restart_read_data(this)
subroutine, public get_medium_box_points_map(medium_box, gr)
subroutine linear_medium_init_interaction(this, interaction)
subroutine, public medium_box_init(medium_box, namespace)
Parse and store geometry of medium box.
subroutine linear_medium_init_interaction_as_partner(partner, interaction)
subroutine linear_medium_update_kinetic_energy(this)
integer, parameter medium_box_file
logical function linear_medium_do_algorithmic_operation(this, operation, updated_quantities)
subroutine linear_medium_finalize(this)
subroutine get_points_map_from_file(filename, mesh, n_points, global_points_number, tmp_map, scale_factor)
Populate list of point indices for points inside the polyhedron.
subroutine, public linear_medium_init(this, namespace)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine get_linear_medium_em_properties(this, medium_box, gr)
Evaluate electromagnetic properties of linear medium.
subroutine, public single_medium_box_allocate(medium_box, n_points)
Allocation of medium_box components.
subroutine, public single_medium_box_end(medium_box)
Deallocation of medium_box components.
This module is intended to contain "only mathematical" functions and procedures.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
type(mpi_grp_t), public mpi_world
This module handles the communicators for the various parallelization strategies.
subroutine, public multicomm_end(mc)
subroutine, public multicomm_init(mc, namespace, base_grp, mode_para, n_node, index_range, min_range)
create index and domain communicators
subroutine, public output_linear_medium(outp, namespace, space, mesh, dir, points_map, ep, mu, cc)
subroutine, public output_linear_medium_init(outp, namespace, space)
this module contains the low-level part of the output system
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
This module implements the basic propagator framework.
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Implementation details for regridding.
integer, parameter, public restart_type_dump
integer, parameter, public restart_td
integer, parameter, public restart_type_load
This module implements the abstract system type.
subroutine, public system_end(this)
Descriptor of one algorithmic operation.
Description of the grid, containing information on derivatives, stencil, and symmetries.
abstract interaction class
surrogate interaction class to avoid circular dependencies between modules.
linear medium for classical electrodynamics
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
contains the information of the meshes and provides the transfer functions
restart_basic_t stores the basic information about a restart object.
Abstract class for systems.