67 integer,
parameter :: &
68 MEDIUM_PARALLELEPIPED = 1, &
74 type(space_t) :: space
75 real(real64) :: ep_factor
76 real(real64) :: mu_factor
77 real(real64) :: sigma_e_factor
78 real(real64) :: sigma_m_factor
79 integer :: edge_profile
80 type(output_t) :: outp
82 type(multicomm_t) :: mc
83 type(single_medium_box_t) :: medium_box
99 procedure linear_medium_constructor
110 class(linear_medium_t),
pointer :: sys
111 type(namespace_t),
intent(in) :: namespace
112 type(mpi_grp_t),
intent(in) :: grp
130 class(linear_medium_t),
target,
intent(inout) :: this
131 type(namespace_t),
intent(in) :: namespace
132 type(mpi_grp_t),
intent(in) :: grp
134 integer :: nlines, ncols,n_points, n_global_points
135 integer(int64) :: index_range(4)
136 integer,
allocatable :: tmp(:)
143 this%namespace = namespace
144 this%space =
space_t(this%namespace)
146 call this%init_parallelization(grp)
151 index_range(1) = this%gr%np_global
154 index_range(4) = 100000
158 index_range, (/ 5000, 1, 1, 1 /))
178 if (
parse_block(namespace,
'LinearMediumProperties', blk) == 0)
then
181 if (nlines /= 1)
then
192 write(
message(1),
'(a,es9.2)')
'Box epsilon factor: ', this%ep_factor
193 write(
message(2),
'(a,es9.2)')
'Box mu factor: ', this%mu_factor
194 write(
message(3),
'(a,es9.2)')
'Box electric sigma: ', this%sigma_e_factor
195 write(
message(4),
'(a,es9.2)')
'Box magnetic sigma: ', this%sigma_m_factor
202 message(1) =
'You must specify the properties of your linear medium through the LinearMediumProperties block.'
218 call parse_variable(namespace,
'LinearMediumEdgeProfile', option__linearmediumedgeprofile__edged, this%edge_profile)
219 if (this%edge_profile == option__linearmediumedgeprofile__edged)
then
220 write(
message(1),
'(a,a)')
'Box shape: ',
'edged'
221 else if (this%edge_profile == option__linearmediumedgeprofile__smooth)
then
222 write(
message(1),
'(a,a)')
'Box shape: ',
'smooth'
226 allocate(this%supported_interactions(0))
228 call this%quantities%add(
quantity_t(
"permitivity", updated_on_demand = .false., always_available = .
true.))
229 call this%quantities%add(
quantity_t(
"permeability", updated_on_demand = .false., always_available = .
true.))
230 call this%quantities%add(
quantity_t(
"E conductivity", updated_on_demand = .false., always_available = .
true.))
231 call this%quantities%add(
quantity_t(
"M conductivity", updated_on_demand = .false., always_available = .
true.))
238 this%outp%iter_dir, this%medium_box%points_map, this%medium_box%ep, &
239 this%medium_box%mu, this%medium_box%c)
241 if (this%medium_box%check_medium_points)
then
242 safe_allocate(tmp(1:this%gr%np))
244 write(
message(1),
'(a, a, a)')
'Check of points inside surface of medium ', trim(this%medium_box%filename),
":"
247 write(
message(1),
'(a, I8)')
'Number of points inside medium (normal coordinates):', &
248 this%medium_box%global_points_number
249 write(
message(2),
'(a, I8)')
'Number of points inside medium (rescaled coordinates):', n_global_points
252 safe_deallocate_a(tmp)
267 select type (interaction)
269 message(1) =
"Trying to initialize an unsupported interaction by a linear medium."
286 select type (interaction)
289 partner%gr, partner%space, partner%namespace)
292 medium_box_grid => partner%medium_box%to_grid(partner%gr)
295 call regridding%do_transfer(interaction%medium_box%aux_ep, medium_box_grid%aux_ep)
296 call regridding%do_transfer(interaction%medium_box%aux_mu, medium_box_grid%aux_mu)
297 call regridding%do_transfer(interaction%medium_box%ep, medium_box_grid%ep)
298 call regridding%do_transfer(interaction%medium_box%mu, medium_box_grid%mu)
299 call regridding%do_transfer(interaction%medium_box%c, medium_box_grid%c)
300 call regridding%do_transfer(interaction%medium_box%sigma_e, medium_box_grid%sigma_e)
301 call regridding%do_transfer(interaction%medium_box%sigma_m, medium_box_grid%sigma_m)
303 safe_deallocate_p(regridding)
304 safe_deallocate_p(medium_box_grid)
306 message(1) =
"Trying to initialize an unsupported interaction by a linear medium."
326 character(len=:),
allocatable,
intent(out) :: updated_quantities(:)
339 real(real64),
intent(in) :: tol
357 select type (interaction)
361 message(1) =
"Unsupported interaction."
373 integer :: restart_file_unit, ierr
379 message(1) =
"Linear medium system "//trim(this%namespace%get())//
" will only write a dummy restart file."
383 restart_file_unit = restart%open(
'restart_linear_medium')
384 if (restart%do_i_write())
write(restart_file_unit, *)
'Linear medium restart file'
385 call restart%close(restart_file_unit)
386 message(1) =
"Successfully wrote restart data for system "//trim(this%namespace%get())
389 message(1) =
"Could not write restart data for system "//trim(this%namespace%get())
404 integer :: restart_file_unit, ierr
409 restart_file_unit = restart%open(
'restart_linear_medium')
411 call restart%close(restart_file_unit)
420 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
458 type(
grid_t),
intent(in) :: gr
460 integer :: ip, ip_in, ip_bd, idim
461 integer,
allocatable :: tmp_points_map(:), tmp_bdry_map(:)
462 real(real64) :: bounds(2,gr%box%dim), xx(gr%box%dim)
469 safe_allocate(tmp_points_map(1:gr%np))
470 safe_allocate(tmp_bdry_map(1:gr%np))
477 medium_box%global_points_number, tmp_points_map)
482 bounds(1,idim) = medium_box%center(idim) - medium_box%lsize(idim)/
m_two
483 bounds(2,idim) = medium_box%center(idim) + medium_box%lsize(idim)/
m_two
488 xx(1:3) = gr%x(1:3, ip)
492 tmp_points_map(ip_in) = ip
496 tmp_bdry_map(ip_bd) = ip
500 medium_box%points_number = ip_in
501 medium_box%bdry_number = ip_bd
503 safe_allocate(medium_box%bdry_map(1:medium_box%bdry_number))
504 medium_box%bdry_map = 0
505 medium_box%bdry_map = tmp_bdry_map(1:medium_box%bdry_number)
509 safe_allocate(medium_box%points_map(1:medium_box%points_number))
510 medium_box%points_map(:) = tmp_points_map(1:medium_box%points_number)
513 safe_deallocate_a(tmp_points_map)
514 safe_deallocate_a(tmp_bdry_map)
522 real(real64),
intent(in) :: xx(:)
523 real(real64),
intent(in) :: bounds(:,:)
526 if ((xx(1) >= bounds(1,1)) .and. (xx(1) <= bounds(2,1)) .and. &
527 (xx(2) >= bounds(1,2)) .and. (xx(2) <= bounds(2,2)) .and. &
528 (xx(3) >= bounds(1,3)) .and. (xx(3) <= bounds(2,3)) )
then
534 logical pure function check_point_on_bounds(xx, bounds) result (check)
535 real(real64),
intent(in) :: xx(:)
536 real(real64),
intent(in) :: bounds(:,:)
539 if (
is_close(xx(1), bounds(1,1)) .and. (xx(2) >= bounds(1,2) .and. xx(3) >= bounds(1,3)) &
540 .and. (xx(2) <= bounds(2,2) .and. xx(3) <= bounds(2,3)) .or. &
541 is_close(xx(2), bounds(1,2)) .and. (xx(1) >= bounds(1,1) .and. xx(3) >= bounds(1,3)) &
542 .and. (xx(1) <= bounds(2,1) .and. xx(3) <= bounds(2,3)) .or. &
543 is_close(xx(3), bounds(1,3)) .and. (xx(1) >= bounds(1,1) .and. xx(2) >= bounds(1,2)) &
544 .and. (xx(1) <= bounds(2,1) .and. xx(2) <= bounds(2,2)) .or. &
545 is_close(xx(1), bounds(2,1)) .and. (xx(2) >= bounds(1,2) .and. xx(3) >= bounds(1,3)) &
546 .and. (xx(2) <= bounds(2,2) .and. xx(3) <= bounds(2,3)) .or. &
547 is_close(xx(2), bounds(2,2)) .and. (xx(1) >= bounds(1,1) .and. xx(3) >= bounds(1,3)) &
548 .and. (xx(1) <= bounds(2,1) .and. xx(3) <= bounds(2,3)) .or. &
549 is_close(xx(3), bounds(2,3)) .and. (xx(1) >= bounds(1,1) .and. xx(2) >= bounds(1,2)) &
550 .and. (xx(1) <= bounds(2,1) .and. xx(2) <= bounds(2,2)) )
then
562 type(single_medium_box_t),
intent(inout) :: medium_box
563 type(grid_t),
intent(in) :: gr
565 integer :: ip, ip_in, ip_bd, ipp
566 real(real64) :: xx(gr%box%dim), xxp(gr%box%dim), dd, dd_max, dd_min
567 real(real64),
allocatable :: tmp(:), tmp_grad(:,:)
571 call profiling_in(
'GET_LIN_MEDIUM_EM_PROP')
573 safe_allocate(tmp(1:gr%np_part))
574 safe_allocate(tmp_grad(1:gr%np_part, 1:gr%box%dim))
575 dd_max = max(2*gr%spacing(1), 2*gr%spacing(2), 2*gr%spacing(3))
577 do ip_in = 1, medium_box%points_number
578 ip = medium_box%points_map(ip_in)
579 if (this%edge_profile == option__linearmediumedgeprofile__smooth)
then
580 assert(
allocated(medium_box%bdry_map))
582 xx(1:3) = gr%x(1:3, ip)
585 do ip_bd = 1, medium_box%bdry_number
586 ipp = medium_box%bdry_map(ip_bd)
587 xxp(1:3) = gr%x(1:3, ipp)
588 dd = norm2(xx(1:3) - xxp(1:3))
589 if (dd < dd_min) dd_min = dd
592 medium_box%ep(ip_in) = p_ep + ((p_ep * this%ep_factor - p_ep) &
593 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max))))
594 medium_box%mu(ip_in) = p_mu + ((p_mu * this%mu_factor - p_mu) &
595 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max))))
596 medium_box%c(ip_in) = m_one/
sqrt(medium_box%ep(ip_in)*medium_box%mu(ip_in))
597 medium_box%sigma_e(ip_in) = this%sigma_e_factor &
598 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max)))
599 medium_box%sigma_m(ip_in) = this%sigma_m_factor &
600 * m_one/(m_one +
exp(-m_five/dd_max * (dd_min - m_two*dd_max)))
602 else if (this%edge_profile == option__linearmediumedgeprofile__edged)
then
604 medium_box%ep(ip_in) = p_ep * this%ep_factor
605 medium_box%mu(ip_in) = p_mu * this%mu_factor
606 medium_box%c(ip_in) = m_one/
sqrt(medium_box%ep(ip_in)*medium_box%mu(ip_in))
607 medium_box%sigma_e(ip_in) = this%sigma_e_factor
608 medium_box%sigma_m(ip_in) = this%sigma_m_factor
614 do ip_in = 1, medium_box%points_number
615 ip = medium_box%points_map(ip_in)
616 tmp(ip)= medium_box%ep(ip_in)
618 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
619 do ip_in = 1, medium_box%points_number
620 ip = medium_box%points_map(ip_in)
621 medium_box%aux_ep(ip_in, :) = tmp_grad(ip, :)/(m_four * medium_box%ep(ip_in))
625 do ip_in = 1, medium_box%points_number
626 ip = medium_box%points_map(ip_in)
627 tmp(ip) = medium_box%mu(ip_in)
629 call dderivatives_grad(gr%der, tmp, tmp_grad, set_bc = .false.)
630 do ip_in = 1, medium_box%points_number
631 ip = medium_box%points_map(ip_in)
632 medium_box%aux_mu(ip_in, :) = tmp_grad(ip, :)/(m_four * medium_box%mu(ip_in))
637 safe_deallocate_a(tmp)
638 safe_deallocate_a(tmp_grad)
640 call profiling_out(
'GET_LIN_MEDIUM_EM_PROP')
648 character(len=256),
intent(in) :: filename
649 class(mesh_t),
intent(in) :: mesh
650 integer,
intent(out) :: n_points
651 integer,
intent(out) :: global_points_number
652 integer,
intent(inout) :: tmp_map(:)
653 real(real64),
optional,
intent(in) :: scale_factor
656 real(real64) :: xx(3)
657 type(cgal_polyhedra_t) :: cgal_poly
661 call profiling_in(
'GET_POINTS_MAP_FROM_FILE')
663 call cgal_polyhedron_init(cgal_poly, trim(filename), verbose = .false.)
667 if (
present(scale_factor))
then
668 xx(1:3) = scale_factor * mesh%x(1:3, ip)
670 xx(1:3) = mesh%x(1:3, ip)
672 if (cgal_polyhedron_point_inside(cgal_poly, xx(1), xx(2), xx(3)))
then
678 call cgal_polyhedron_end(cgal_poly)
680 call mpi_world%allreduce(ip_in, global_points_number, 1, mpi_integer, mpi_sum)
682 call profiling_out(
'GET_POINTS_MAP_FROM_FILE')
691 type(single_medium_box_t),
intent(inout) :: medium_box
692 type(namespace_t),
intent(in) :: namespace
694 integer :: nlines, ncols, idim
713 if (.not. varinfo_valid_option(
'LinearMediumBoxShape', medium_box%box_shape))
then
714 call messages_input_error(namespace,
'LinearMediumBoxShape')
717 select case (medium_box%box_shape)
733 if (parse_block(namespace,
'LinearMediumBoxSize', blk) == 0)
then
734 call messages_print_with_emphasis(msg=trim(
'Linear Medium box center and size:'), namespace=namespace)
736 nlines = parse_block_n(blk)
737 if (nlines /= 1)
then
738 call messages_input_error(namespace,
'LinearMediumBoxSize',
'should consist of one line')
740 ncols = parse_block_cols(blk, 0)
742 call messages_input_error(namespace,
'LinearMediumBoxSize',
'should consist of six columns')
745 call parse_block_float(blk, 0, idim-1, medium_box%center(idim))
746 call parse_block_float(blk, 0, idim+2, medium_box%lsize(idim))
748 write(message(1),
'(a,es9.2,a,es9.2,a,es9.2)')
'Box center: ', medium_box%center(1),
' | ',&
749 medium_box%center(2),
' | ', medium_box%center(3)
750 write(message(2),
'(a,es9.2,a,es9.2,a,es9.2)')
'Box size : ', medium_box%lsize(1),
' | ', &
751 medium_box%lsize(2),
' | ', medium_box%lsize(3)
752 write(message(3),
'(a)')
""
753 call messages_info(3)
754 call parse_block_end(blk)
756 call messages_print_with_emphasis(namespace=namespace)
758 message(1) =
"For parallelepiped box shapes, you must provide a LinearMediumBoxSize block."
759 call messages_fatal(1, namespace=namespace)
769 if (parse_is_defined(namespace,
'LinearMediumBoxFile'))
then
770 call parse_variable(namespace,
'LinearMediumBoxFile',
'mediumboxfile', medium_box%filename)
772 message(1) =
"When using box_file as the box shape, you must provide a filename through the LinearMediumBoxFile variable."
773 call messages_fatal(1, namespace=namespace)
785 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, grp, 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)
logical function linear_medium_restart_read_data(this)
class(linear_medium_t) function, pointer linear_medium_constructor(namespace, grp)
The factory routine (or constructor) allocates a pointer of the corresponding type and then calls the...
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 get_linear_medium_em_properties(this, medium_box, gr)
Evaluate electromagnetic properties of linear medium.
subroutine, public linear_medium_init(this, namespace, grp)
The init routine is a module level procedure This has the advantage that different classes can have d...
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)
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.