Index: trunk/src/muli/muli.nw =================================================================== --- trunk/src/muli/muli.nw (revision 8286) +++ trunk/src/muli/muli.nw (revision 8287) @@ -1,17596 +1,17596 @@ % -*- ess-noweb-default-code-mode: f90-mode; noweb-default-code-mode: f90-mode; -*- % WHIZARD multiple interactions code as NOWEB source %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Multiple Interactions (MPI) Code} \includemodulegraph{muli} This is the code for the \whizard\ module for multiple interactions (MPI) in hadron collisions. It also provides the interleaved shower with together with the shower module. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Basic types} This file contains the module [[muli_basic]] which is included by all other modules of the MPI code. It's main purpose is serialization and deserialization, but it also contains some bitmodel parameters and some minor definitions common to all modules and types. Serialization is implemented in three layers: \begin{enumerate} \item {\bf I/O layer}: streamfile access and exact, retreivable and compiler independent representation of all intrinsic types \item {\bf Marking layer}: storing/restoring pointer association and better human readability \item {\bf Derived type layer}: abstract type as parent for all serializable derived types \end{enumerate} \paragraph{The I/O Layer} The I/O layer is implemented by [[page_ring_t]] and its type bound procedures. We chose not to use the standard formatted sequential I/O for several reasons: \begin{itemize} \item Sequential I/O is line orientated, but serialization is not. \item Formatted I/O of floating point numbers is inexact. There were problems in reading numbers like [[1+epsilon(1)]] or [[huge(1)]] including arithmetic exeptions and wrong results. \item Formatted reading is slow. This does matter, when you read files of $\mathcal{O}(100)$ MB. \end{itemize} [[page_ring_t]] is a ring buffer of default kind characters holding a region of the addressed file. All read and write procedures use the ring buffer, not the file. [[page_ring]] automatically reads more characters from the file when needed and writes and discards parts of the ring buffer when not any longer needed. \paragraph{Marking layer} Marking is done by [[marking_t]] and its type bound procedures. Files written by [[marking_t]] are regular XML files, so you can use your favorite XML editor to examine or edit serialized contents. The main purpose of this layer is to recover the type of polymorphic entities and to restore association of pointers, but it also assigns names to all contents, so it is much easier to read generated files. Type recovery is done by a reference list. You must push a representive object to this reference list for each type that might get resolved before starting deserialization. [[marker_t]] will care for comparing these representives to the contents of the files. Association restoration is done by a heap list. It is technically equal to the reference list, but holds all targets that have been processed so far. Generation of this list is handled by [[marking_t]], so you dont't have to care for this aspect at all. Up to the present it is not possible to restore association, when a non-pointer target is serialized after its associated pointer is serialized. There is no trivial solution and this case does not appear here, so we will not take care of this. \paragraph{Derived type layer} Each instance that shall become serialized must extend [[ser_class_t]]. Essential for type recovery is the virtual type bound procedure [[get_type]]. Each non-virtual type shall override [[get_type]] and return the actual name of its type in lower-case letters. Each type which adds new, non-redundant components shall override [[write_to_marker]] and [[read_from_marker]]. These type-bound procedures define, what contents get serialized. While the marker cares about tagging the type and association of the instance, every instance still has to define what to serialize. The rule is to mark the begin of its contents, then its parents procedure, then mark all non-redundant components, then mark the end of its contents. Finally, each serializable type shall override [[print_to_unit]]. This procedure is called for an arbitrary human-readable output. It is quite similar to [[write_to_ring]], but without strict format and ignoring machine-readability. [[ser_class_t]] has strictly speaking two layers. [[write_to_marker]] and [[read_from_marker]] are only for internal usage. Serialization and deserialization are triggered by the TBPs serialize and deserialize. These procedures take care of initialization and finalization of the marker. A serializable type should override these procedures to push a representive of itself and any other references to the reference list of it's marker before (de)serialization and to pop them from the list afterwards. <<[[muli_base.f90]]>>= <> module muli_base use, intrinsic :: iso_fortran_env <> use kinds, only: i64 <> use constants use io_units use diagnostics <> <> <> <> <> contains <> end module muli_base @ %def muli_base These are the bitmodel parameters. <>= integer, public, parameter :: dik = i64 integer(dik), public, parameter :: i_one = int(1, kind=dik) integer(dik), public, parameter :: i_zero = int(0, kind=dik) @ %def dik one i_zero These are the serialization parameters. <>= integer(dik), public, parameter :: serialize_page_size = 1024 integer(dik), public, parameter :: serialize_ok = 0000 integer(dik), public, parameter :: serialize_syntax_error = 1001 integer(dik), public, parameter :: serialize_wrong_tag = 1002 integer(dik), public, parameter :: serialize_wrong_id = 1003 integer(dik), public, parameter :: serialize_wrong_type = 1004 integer(dik), public, parameter :: serialize_wrong_name = 1005 integer(dik), public, parameter :: serialize_no_target = 1006 integer(dik), public, parameter :: serialize_no_pointer = 1007 integer(dik), public, parameter :: serialize_wrong_action = 1008 integer(dik), public, parameter :: serialize_unexpected_content = 1009 integer(dik), public, parameter :: serialize_null = 1010 integer(dik), public, parameter :: serialize_nothing = 1011 logical, public, parameter :: serialize_default_indent = .true. logical, public, parameter :: serialize_default_line_break = .true. logical, public, parameter :: serialize_default_asynchronous = .false. @ %def serializable_page_size serializable_ok @ %def serializable_syntax_error serializable_wrong_tag @ %def serializable_wrong_id serializable_wrong_type @ %def serializable_wrong_name serializable_no_target @ %def serializable_no_pointer serializable_wrong_action @ %def serializable_unexpected_content serializable_null @ %def serializable_nothing serializable_default_indent @ %def serializable_default_line_break serializable_default_asynchronous @ And some private variables: <>= integer(dik) :: last_id = 0 character(len=*), parameter :: serialize_integer_characters = & "-0123456789" @ %def last_id serialize_integer_characters <>= abstract interface subroutine ser_write_if (this, marker, status) import ser_class_t import marker_t import dik class(ser_class_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status end subroutine ser_write_if end interface abstract interface subroutine ser_read_if (this, marker, status) import ser_class_t import marker_t import dik class(ser_class_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status end subroutine ser_read_if end interface abstract interface subroutine ser_unit (this, unit, parents, components, peers) import ser_class_t import dik class(ser_class_t), intent(in) :: this integer,intent(in) :: unit integer(dik), intent(in) :: parents,components,peers end subroutine ser_unit end interface abstract interface pure subroutine ser_type (type) character(:), allocatable, intent(out) :: type end subroutine ser_type end interface @ %def ser_write_if ser_read_if ser_unit ser_type @ <>= abstract interface elemental function measure_int (this) import class(measure_class_t), intent(in) :: this real(default) :: measure_int end function measure_int end interface @ %def measure_int @ <>= public :: operator(<) <>= interface operator(<) module procedure measurable_less_measurable module procedure measurable_less_default end interface operator(<) <>= public :: operator(<=) <>= interface operator(<=) module procedure measurable_less_or_equal_measurable module procedure measurable_less_or_equal_default end interface operator(<=) <>= public :: operator(==) <>= interface operator(==) module procedure measurable_equal_measurable module procedure measurable_equal_default end interface operator(==) <>= public :: operator(>=) <>= interface operator(>=) module procedure measurable_equal_or_greater_measurable module procedure measurable_equal_or_greater_default end interface operator(>=) <>= public :: operator(>) <>= interface operator(>) module procedure measurable_greater_measurable module procedure measurable_greater_default end interface operator(>) @ %def < <= == >= > @ <>= interface page_ring_position_is_before module procedure page_ring_position_is_before_int_pos module procedure page_ring_position_is_before_pos_pos module procedure page_ring_position_is_before_pos_int end interface @ <>= public :: ser_class_t <>= type, abstract :: ser_class_t contains <> end type ser_class_t @ %def ser_class_t <>= procedure(ser_write_if), deferred :: write_to_marker @ This is a dummy procedure. Usually, you do not need to deserialize targets, so by implementing this dummy we don't force all descendants to override this procedure. Then again this is the only way to read targets from markers. <>= procedure(ser_read_if), deferred :: read_from_marker <>= subroutine serializable_read_target_from_marker (this, marker, status) class(ser_class_t), target, intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status write (output_unit, "(A)") "serializable_read_target_from_marker:" write (output_unit, "(A)") "This is a dummy procedure. Usually, this " & // "message indicates a missing overridden " & // "read_target_from_marker TPB for " call this%write_type (output_unit) write (output_unit, "(A)") "" call this%read_from_marker (marker, status) end subroutine serializable_read_target_from_marker @ %def serializable_read_target_from_marker @ <>= procedure(ser_unit), deferred :: print_to_unit <>= subroutine serializable_serialize_to_unit (this, unit, name) class(ser_class_t), intent(in) :: this integer, intent(in) :: unit character (len=*), intent(in) :: name logical :: opened character(32) :: file !!! gfortran bug !!! character::stream character::write type(marker_t)::marker ! inquire(unit=unit,opened=opened,stream=stream,write=write) inquire (unit=unit,opened=opened,write=write) if (opened) then !!! if(stream=="Y")then if(write=="Y")then print *,"dummy: serializable_serialize_to_unit" stop else print *,"serializable_serialize_to_unit: cannot write to read-only unit." end if !!! else !!! print *,"serializable_serialize_to_unit: access kind of unit is not 'stream'." !!! end if else call msg_error ("serializable_serialize_to_unit: file is not opened.") end if end subroutine serializable_serialize_to_unit @ %def serializable_serialize_to_unit @ <>= procedure(ser_type), nopass, deferred :: get_type @ <>= procedure, nopass :: verify_type => serializable_verify_type <>= elemental function serializable_verify_type (type) result (match) character(*), intent(in) :: type logical :: match match = type == "ser_class_t" end function serializable_verify_type @ %def serializable_verify_type @ <>= procedure :: read_target_from_marker => & serializable_read_target_from_marker @ <>= procedure :: write_type => serializable_write_type <>= subroutine serializable_write_type (this, unit) class(ser_class_t), intent(in) :: this integer,intent(in) :: unit character(:), allocatable :: this_type call this%get_type (this_type) write (unit, "(A)", advance="no") this_type end subroutine serializable_write_type @ %def serializable_write_type @ <>= procedure :: print => serializable_print <>= recursive subroutine serializable_print & (this, parents, components, peers, unit) class(ser_class_t), intent(in) :: this integer(dik), intent(in) :: parents, components, peers integer, intent(in), optional :: unit integer :: u u = given_output_unit (unit) write (u, "(A)") write (u, "(A)", advance="no") "Instance of type: " call this%write_type (u) write (u, "(A)") call this%print_to_unit (u, parents, components, peers) end subroutine serializable_print @ %def serializable_print @ <>= procedure :: print_error => serializable_print_error <>= recursive subroutine serializable_print_error (this) class(ser_class_t), intent(in) :: this call this%print_to_unit (error_unit, i_zero, i_zero, i_zero) end subroutine serializable_print_error @ %def serializable_print_error @ <>= procedure :: print_all => serializable_print_all <>= recursive subroutine serializable_print_all (this, unit) class(ser_class_t), intent(in) :: this integer, intent(in), optional :: unit integer :: u u = given_output_unit (unit) write (u, "(A)") write (u, "(A)", advance="no") "Instance of type: " call this%write_type (u) write (u, "(A)") call this%print_to_unit (u, huge(i_one), huge(i_one), huge(i_one)) end subroutine serializable_print_all @ %def serializable_print_all @ <>= procedure :: print_little => serializable_print_little <>= recursive subroutine serializable_print_little (this, unit) class(ser_class_t), intent(in) :: this integer, intent(in), optional :: unit integer :: u u = given_output_unit (u) write(u, "(A)") write(u, "(A)", advance="no") "Instance of type: " call this%write_type (u) write(u, "(A)") call this%print_to_unit (u, i_zero, i_zero, i_zero) end subroutine serializable_print_little @ %def serializable_print_little @ <>= procedure :: print_parents => serializable_print_parents <>= recursive subroutine serializable_print_parents (this) class(ser_class_t), intent(in) :: this write(output_unit, "(A)") write(output_unit, "(A)", advance="no") "Instance of type: " call this%write_type (output_unit) write (output_unit, "(A)") call this%print_to_unit (output_unit, huge(i_one), i_zero, i_zero) end subroutine serializable_print_parents @ %def serializable_print_parents @ <>= procedure :: print_components => serializable_print_components <>= recursive subroutine serializable_print_components(this) class(ser_class_t), intent(in) :: this write (output_unit, "(A)") write (output_unit, "(A)", advance="no") "Instance of type: " call this%write_type (output_unit) write(output_unit, "(A)") call this%print_to_unit (output_unit, i_zero, huge(i_one), i_zero) end subroutine serializable_print_components @ %def serializable_print_components @ <>= procedure :: print_peers => serializable_print_peers <>= recursive subroutine serializable_print_peers (this) class(ser_class_t), intent(in) :: this write (output_unit, "(A)") write (output_unit, "(A)", advance="no") "Instance of type: " call this%write_type (output_unit) write (output_unit, "(A)") call this%print_to_unit (output_unit, i_zero, i_zero, huge(i_one)) end subroutine serializable_print_peers @ %def serializable_print_peers @ <>= procedure :: serialize_to_file => serializable_serialize_to_file <>= subroutine serializable_serialize_to_file (this, name, file) class(ser_class_t), intent(in) :: this character(len=*), intent(in) :: file, name type(marker_t) :: marker call marker%open_for_write_access (file) write (output_unit, "(A,A)") & "Serializable_serialize_to_file: writing xml preamble to ", file call marker%activate_next_page () call marker%push ('') call marker%mark_begin (tag="file", name = file) flush(marker%unit) call this%serialize_to_marker (marker, name) call marker%mark_end ("file") call marker%close () call marker%finalize () end subroutine serializable_serialize_to_file @ %def serializable_serialize_to_file @ <>= procedure :: serialize_to_unit => serializable_serialize_to_unit @ <>= procedure :: serialize_to_marker => serializable_serialize_to_marker <>= recursive subroutine serializable_serialize_to_marker (this, marker, name) class(ser_class_t), intent(in) :: this class(marker_t), intent(inout) :: marker character(len=*), intent(in) :: name if (marker%action == 1) then call marker%mark_instance (this, name) else call msg_error ("serializable_serialize_to_marker: Marker is " & // "not ready for write access.") end if end subroutine serializable_serialize_to_marker @ %def serializable_serialize_to_marker @ <>= procedure :: deserialize_from_file => serializable_deserialize_from_file <>= subroutine serializable_deserialize_from_file (this, name, file) class(ser_class_t), intent(out) :: this character(*), intent(in) :: name, file type(marker_t) :: marker integer(dik), dimension(2) :: p1, p2 call marker%open_for_read_access (file, "") marker%eof_int = huge(i_one) marker%eof_pos = page_ring_position (marker%eof_int) call marker%read_page () call marker%find ('', skip=3, proceed=.false., pos=p2) if ((p1(2) <= 0) .or. (p2(2) <= 0)) then call msg_error ("serializable_deserialize_from_file: no " & // "version substring found.") end if call marker%set_position (p2) call marker%find ('', skip=1, proceed=.false., pos=p2) if((p1(2)>0) .and. (p2(2)>0))then call marker%push_position (p2) call marker%find ('name="', skip=4, proceed=.true., pos=p1) call marker%find ('"', skip=1, proceed=.false., pos=p2) call marker%pop_position () else call msg_error ("serializable_deserialize_from_file: no file " & // "header found.") end if call this%deserialize_from_marker (name, marker) call marker%close () call marker%finalize () end subroutine serializable_deserialize_from_file @ %def serializable_deserialize_from_file @ <>= procedure :: deserialize_from_unit => & serializable_deserialize_from_unit <>= subroutine serializable_deserialize_from_unit (this, unit, name) class(ser_class_t), intent(inout) :: this integer, intent(in) :: unit character(len=*), intent(in) :: name logical::opened !!! gfortran bug !!! character::stream character::read type(marker_t)::marker !!! inquire(unit=unit,opened=opened,stream=stream,read=read) inquire(unit=unit,opened=opened,read=read) if(opened)then !!! if(stream=="Y")then if(read=="Y")then print *,"dummy: serializable_serialize_from_unit" stop else print *,"serializable_serialize_from_unit: cannot write from read-only unit." end if !!! else !!! print *,"serializable_serialize_from_unit: access kind of unit is not 'stream'." !!! end if else print *,"serializable_serialize_from_unit: file is not opened." end if end subroutine serializable_deserialize_from_unit @ %def serializable_deserialize_from_unit @ This needs to be made public, and not only be present as a TBP. <>= public :: serializable_deserialize_from_marker <>= procedure :: deserialize_from_marker => & serializable_deserialize_from_marker <>= subroutine serializable_deserialize_from_marker (this, name, marker) class(ser_class_t), intent(out) :: this character(*), intent(in) :: name class(marker_t), intent(inout) :: marker integer(dik) :: status if (marker%action == 2) then call marker%pick_instance (name, this, status) else call msg_error ("serializable_deserialize_from_marker: Marker is " & // "not ready for read access.") end if end subroutine serializable_deserialize_from_marker @ %def serializable_deserialize_from_marker @ <>= generic :: serialize => serialize_to_file, serialize_to_unit, & serialize_to_marker @ <>= generic :: deserialize => deserialize_from_file, & deserialize_from_unit, deserialize_from_marker @ <>= public :: serialize_print_peer_pointer <>= recursive subroutine serialize_print_peer_pointer & (ser, unit, parents, components, peers, name) class(ser_class_t), pointer, intent(in) :: ser integer, intent(in) :: unit integer(dik) :: parents, components, peers character(len=*), intent(in) :: name if (associated (ser)) then write (unit,*) name, " is associated." if (peers>0) then write (unit,*) "Printing components of ", name call ser%print_to_unit (unit, parents, components, peers - i_one) else write (unit,*) "Skipping components of ", name end if else write (unit,*) name, " is not associated." end if end subroutine serialize_print_peer_pointer @ %def serialize_print_peer_pointer @ <>= public :: serialize_print_comp_pointer <>= recursive subroutine serialize_print_comp_pointer & (ser, unit, parents, components, peers, name) class(ser_class_t), pointer, intent(in) :: ser integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers character(len=*), intent(in) :: name if (associated (ser)) then write (unit,*) name," is associated." if (components > 0) then write (unit,*) "Printing components of ", name call ser%print_to_unit (unit, parents, components - i_one, peers) else write (unit,*) "Skipping components of ", name end if else write (unit,*) name," is not associated." end if end subroutine serialize_print_comp_pointer @ %def serialize_print_comp_pointer @ <>= public :: serialize_print_allocatable <>= subroutine serialize_print_allocatable & (ser, unit, parents, components, peers, name) class(ser_class_t), allocatable, intent(in) :: ser integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers character(len=*), intent(in) :: name if (allocated (ser)) then write (unit,*) name, " is allocated." if (components > 0) then write (unit,*) "Printing components of ",name call ser%print_to_unit (unit, parents, components-1, peers) else write (unit,*) "Skipping components of ",name end if else write (unit,*) name," is not allocated." end if end subroutine serialize_print_allocatable @ %def serialize_print_allocatable @ <>= public :: measure_class_t <>= type, abstract, extends (ser_class_t) :: measure_class_t contains procedure(measure_int), public, deferred :: measure end type measure_class_t @ %def measure_class_t @ <>= public :: identified_t <>= type, extends (ser_class_t) :: identified_t private integer(dik) :: id type(string_t) :: name contains <> end type identified_t @ %def identified_t @ <>= procedure :: base_write_to_marker => identified_write_to_marker procedure :: write_to_marker => identified_write_to_marker <>= subroutine identified_write_to_marker (this, marker, status) class(identified_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer(dik) :: id id = this%get_id () call marker%mark_begin ("identified_t") call marker%mark ("name", this%get_name ()) call marker%mark ("id", id) call marker%mark_end ("identified_t") end subroutine identified_write_to_marker @ %def identified_write_to_marker @ <>= procedure :: base_read_from_marker => identified_read_from_marker procedure :: read_from_marker => identified_read_from_marker <>= subroutine identified_read_from_marker (this, marker, status) class(identified_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status character(:), allocatable :: name call marker%pick_begin ("identified_t", status=status) call marker%pick ("name", name, status) call marker%pick ("id", this%id, status) call marker%pick_end ("identified_t", status=status) this%name = name end subroutine identified_read_from_marker @ %def identified_read_from_marker @ <>= procedure :: base_print_to_unit => identified_print_to_unit procedure :: print_to_unit => identified_print_to_unit <>= subroutine identified_print_to_unit (this, unit, parents, components, peers) class(identified_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(A)") "Components of identified_t:" write (unit, "(A,A)") "Name: ", this%get_name () write (unit, "(A,I10)") "ID: ", this%get_id () end subroutine identified_print_to_unit @ %def identified_print_to_unit @ <>= procedure, nopass :: get_type => identified_get_type <>= pure subroutine identified_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="identified_t") end subroutine identified_get_type @ %def identified_get_type @ <>= procedure, nopass :: verify_type => identified_verify_type <>= elemental logical function identified_verify_type (type) character(len=*), intent(in) ::type identified_verify_type = (type == "identified_t") end function identified_verify_type @ %def identified_verify_type @ <>= generic :: initialize => identified_initialize procedure, private :: identified_initialize <>= subroutine identified_initialize (this, id, name) class(identified_t), intent(out) :: this integer(dik), intent(in) :: id character(len=*), intent(in) :: name this%name = name this%id = id end subroutine identified_initialize @ %def identified_initialize @ <>= procedure :: get_id => identified_get_id <>= elemental function identified_get_id (this) result(id) class(identified_t), intent(in) :: this integer(dik) :: id id = this%id end function identified_get_id @ %def identified_get_id @ <>= procedure :: get_name => identified_get_name <>= pure function identified_get_name (this) class(identified_t), intent(in) :: this character(len (this%name)) :: identified_get_name identified_get_name = char (this%name) end function identified_get_name @ %def identified_get_name @ <>= public :: unique_t <>= type, extends (identified_t) :: unique_t private integer(dik) :: unique_id contains <> end type unique_t @ %def unique_t @ <>= procedure, nopass :: get_type => unique_get_type <>= pure subroutine unique_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="unique_t") end subroutine unique_get_type @ %def unique_get_type @ <>= procedure, nopass :: verify_type => unique_verify_type <>= elemental logical function unique_verify_type (type) character(len=*), intent(in) :: type unique_verify_type = (type == "unique_t") end function unique_verify_type @ %def unique_verify_type @ <>= procedure :: write_to_marker => unique_write_to_marker <>= subroutine unique_write_to_marker (this, marker, status) class(unique_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("unique_t") call identified_write_to_marker (this, marker, status) call marker%mark ("unique_id", this%get_unique_id ()) call marker%mark_end ("unique_t") end subroutine unique_write_to_marker @ %def unique_write_to_marker @ <>= procedure :: read_from_marker => unique_read_from_marker <>= subroutine unique_read_from_marker (this, marker, status) class(unique_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("unique_t", status=status) call identified_read_from_marker (this, marker, status) call marker%pick ("unique_id", this%unique_id, status) call marker%pick_end ("unique_t", status) end subroutine unique_read_from_marker @ %def unique_read_from_marker @ <>= procedure :: print_to_unit => unique_print_to_unit <>= subroutine unique_print_to_unit (this, unit, parents, components, peers) class(unique_t), intent(in) :: this integer,intent(in) :: unit integer(dik), intent(in) :: parents, components, peers if (parents > 0) call identified_print_to_unit & (this, unit, parents-1, components, peers) write (unit, "(A,I10)") "Unique ID: ", this%get_unique_id () end subroutine unique_print_to_unit @ %def unique_print_to_unit @ <>= procedure :: identified_initialize => unique_initialize <>= subroutine unique_initialize(this,id,name) class(unique_t), intent(out) :: this integer(dik), intent(in) :: id character(len=*), intent(in) :: name call identified_initialize (this, id, name) last_id = last_id + 1 this%unique_id = last_id end subroutine unique_initialize @ %def unique_initialize @ <>= procedure :: get_unique_id => unique_get_unique_id <>= pure function unique_get_unique_id (this) class(unique_t), intent(in) :: this integer(dik) :: unique_get_unique_id unique_get_unique_id = this%unique_id end function unique_get_unique_id @ %def unique_get_unique_id @ <>= type :: serializable_ref_type private integer(dik) :: id class(ser_class_t), pointer :: ref => null() class(serializable_ref_type), pointer :: next => null() contains <> end type serializable_ref_type @ %def serializable_ref_type @ <>= procedure :: finalize => serializable_ref_finalize <>= subroutine serializable_ref_finalize (this) class(serializable_ref_type), intent(inout) :: this class(serializable_ref_type), pointer :: next do while (associated (this%next)) next => this%next this%next => next%next nullify (next%ref) deallocate (next) end do if (associated (this%ref)) nullify (this%ref) end subroutine serializable_ref_finalize @ %def serializable_ref_finalize @ <>= type :: position_stack_t private integer(dik), dimension(2) :: position class(position_stack_t), pointer :: next => null() contains <> end type position_stack_t @ %def position_stack_t @ <>= generic :: push => push_head, push_given procedure :: push_head => position_stack_push_head procedure :: push_given => position_stack_push_given <>= subroutine position_stack_push_head (this) class(position_stack_t) :: this class(position_stack_t), pointer :: new allocate (new) new%next => this%next new%position = this%position this%next => new end subroutine position_stack_push_head @ %def position_stack_push_head @ <>= subroutine position_stack_push_given (this, position) class(position_stack_t) :: this integer(dik), dimension(2), intent(in) :: position class(position_stack_t), pointer:: new allocate (new) new%next => this%next new%position = position this%next => new end subroutine position_stack_push_given @ %def position_stack_push_given @ <>= generic :: pop => position_stack_pop, position_stack_drop procedure :: position_stack_pop procedure :: position_stack_drop <>= subroutine position_stack_pop (this) class(position_stack_t) :: this class(position_stack_t), pointer :: old if (associated (this%next)) then old => this%next this%next => old%next this%position = old%position deallocate (old) end if end subroutine position_stack_pop @ %def position_stack_pop @ <>= subroutine position_stack_drop (this, position) class(position_stack_t) :: this integer(dik), dimension(2), intent(out) :: position class(position_stack_t), pointer :: old if (associated (this%next)) then old => this%next this%next => old%next position = old%position deallocate (old) else position= [0,0] end if end subroutine position_stack_drop @ %def position_stack_drop @ <>= procedure :: nth_position => position_stack_nth_position <>= function position_stack_nth_position (this, n) result (position) class(position_stack_t), intent(in) :: this integer(dik), intent(in) :: n integer(dik), dimension(2) :: position class(position_stack_t), pointer :: tmp integer(dik) :: pos tmp => this%next pos = n do while (associated (tmp) .and. pos>0) tmp => tmp%next pos = pos - 1 end do if (associated(tmp)) then position = tmp%position else position = [0,0] end if end function position_stack_nth_position @ %def position_stack_nth_position @ <>= procedure :: first => position_stack_first <>= function position_stack_first(this) result(position) class(position_stack_t), intent(in) :: this integer(kind=dik), dimension(2) :: position, tmp_position class(position_stack_t), pointer :: tmp_stack tmp_position = this%position tmp_stack => this%next do while (associated (tmp_stack)) if (page_ring_position_is_before (tmp_stack%position, tmp_position)) then tmp_position = tmp_stack%position end if tmp_stack => tmp_stack%next end do end function position_stack_first @ %def position_stack_first @ <>= procedure :: last => position_stack_last <>= function position_stack_last (this) result (position) class(position_stack_t), intent(in) :: this integer(dik), dimension(2) :: position, tmp_position class(position_stack_t), pointer :: tmp_stack tmp_position = this%position tmp_stack => this%next do while (associated (tmp_stack)) if (page_ring_position_is_before (tmp_position, tmp_stack%position)) then tmp_position = tmp_stack%position end if tmp_stack => tmp_stack%next end do end function position_stack_last @ %def position_stack_last @ <>= procedure :: range => position_stack_range <>= pure function position_stack_range (this) result (position) class(position_stack_t), intent(in) :: this integer(dik), dimension(2) :: position class(position_stack_t), pointer :: tmp end function position_stack_range @ %def position_stack_range @ <>= public :: page_ring_t <>= type :: page_ring_t private logical :: asynchronous = serialize_default_asynchronous logical :: eof_reached = .false. integer :: unit = -1 integer(dik) :: ring_size = 2 integer(dik) :: action = 0 integer(dik) :: eof_int = -1 integer(dik) :: out_unit = output_unit integer(dik) :: err_unit = error_unit integer(dik), dimension(2) :: active_pages = [0,-1] integer(dik), dimension(2) :: eof_pos = [-1,-1] type(string_t) :: eof_string type(position_stack_t) :: position_stack character(serialize_page_size), dimension(:), allocatable::ring contains <> end type page_ring_t @ %def page_ring_t @ These are the [[page_ring_t]] procedures, here for read access only: <>= procedure :: open_for_read_access => page_ring_open_for_read_access <>= subroutine page_ring_open_for_read_access & (this, file, eof_string, asynchronous) class(page_ring_t), intent(inout) :: this character(*), intent(in) :: file, eof_string logical, intent(in), optional :: asynchronous logical :: exist this%eof_string = eof_string inquire (file=file, exist=exist) if (exist) then this%action = 2 else call msg_error ("page_ring_open: File " // file // " is opened " & // "for read access but does not exist.") end if if (present (asynchronous)) this%asynchronous = asynchronous if (this%unit < 0) call generate_unit (this%unit, 100, 1000) if (this%unit < 0) then call msg_error ("page_ring_open: No free unit found.") end if this%ring_size = 2 call this%set_position ([i_zero,i_one]) this%active_pages = [i_zero,-i_one] if (allocated (this%ring)) deallocate (this%ring) allocate (this%ring (i_zero:this%ring_size - i_one)) if (this%asynchronous) then open (this%unit, file=file, access="stream", & action="read", asynchronous="yes", status="old") else open (this%unit, file=file, access="stream", action="read", & asynchronous="no", status="old") end if call this%read_page () end subroutine page_ring_open_for_read_access @ %def page_ring_open_for_read_access @ <>= procedure :: read_page => page_ring_read_page <>= subroutine page_ring_read_page (this) class(page_ring_t), intent(inout) :: this integer(dik) :: iostat character(8) :: iomsg if (.not. this%eof_reached) then call this%activate_next_page () read (this%unit, iostat=iostat) this%ring (this%last_index ()) if (iostat == iostat_end) then this%eof_reached = .true. this%eof_pos(1) = this%last_page () this%eof_pos(2) = index(this%ring(this%last_index()), & char(this%eof_string)) this%eof_pos(2) = this%eof_pos(2) + len(this%eof_string) - 1 this%eof_int = page_ring_ordinal(this%eof_pos) end if end if end subroutine page_ring_read_page @ %def page_ring_read_page @ Those are the write access only type-bound procedures of [[page_ring_t]]: <>= procedure :: open_for_write_access => page_ring_open_for_write_access <>= subroutine page_ring_open_for_write_access (this, file, asynchronous) class(page_ring_t), intent(inout) :: this character(*), intent(in) :: file logical, intent(in), optional :: asynchronous this%action = 1 if (present (asynchronous)) this%asynchronous = asynchronous if (this%unit < 0) call generate_unit (this%unit, 100, 1000) if (this%unit < 0) then call msg_error ("page_ring_open: No free unit found.") end if this%ring_size = 2 call this%set_position ([i_zero,i_one]) this%active_pages = [i_zero,-i_one] if (allocated (this%ring)) deallocate (this%ring) allocate (this%ring (i_zero:this%ring_size-i_one)) if (this%asynchronous) then open (this%unit, file=file, access="stream", action="write", & asynchronous="yes", status="replace") else open (this%unit, file=file, access="stream", action="write", & asynchronous="no",status="replace") end if end subroutine page_ring_open_for_write_access @ %def page_ring_open_for_write_access @ <>= procedure :: flush => page_ring_flush <>= subroutine page_ring_flush (this) class(page_ring_t), intent(inout) :: this integer(dik) :: page do while (this%active_pages(1) < this%actual_page ()) if (this%asynchronous) then write (this%unit, asynchronous="yes") & this%ring(mod(this%active_pages(1), this%ring_size)) else write (this%unit, asynchronous="no") & this%ring(mod(this%active_pages(1), this%ring_size)) end if this%active_pages(1) = this%active_pages(1) + 1 end do end subroutine page_ring_flush @ %def page_ring_flush @ <>= procedure :: break => page_ring_break <>= subroutine page_ring_break(this) class(page_ring_t), intent(inout) :: this if (this%actual_page () >= this%active_pages(2)) & call this%activate_next_page () call this%turn_page () end subroutine page_ring_break @ %def page_ring_break @ For comparisons: <>= procedure :: str_equal => page_ring_str_equal <>= pure logical function page_ring_str_equal (this, string, pos) class(page_ring_t), intent(in) :: this character(*), intent(in) :: string integer(dik), dimension(2,2), intent(in) :: pos page_ring_str_equal = string == this%substring (pos) end function page_ring_str_equal @ %def page_ring_str_equal @ Routines for searching: <>= generic :: find => page_ring_find, page_ring_find_default procedure, private :: page_ring_find procedure, private :: page_ring_find_default <>= recursive subroutine page_ring_find & (this, exp, start, limit, skip, proceed, pos) class(page_ring_t), intent(inout) :: this integer(dik), dimension(2), intent(in) :: start integer(dik), dimension(2), intent(in) :: limit character(*), intent(in) :: exp integer, intent(in) :: skip logical, intent(in) :: proceed integer(dik), dimension(2), intent(out) :: pos integer(dik) :: page, page2, ind page = this%ring_index (start(1)) if (limit(1) == start(1)) then ind = index(this%ring(page) (start(2):limit(2)), exp) if (ind > 0) then select case (skip) case (1) pos= [start(1), start(2)+ind-2] if (pos(2) == 0) then pos(1) = pos(1) - 1 pos(2) = serialize_page_size end if case (2) pos = [start(1), start(2)+ind-1] case (3) pos = [start(1), start(2)+ind+len(exp)-2] case (4) pos = [start(1),start(2)+ind+len(exp)-1] if (pos(1) == this%last_page()) call this%read_page () if (pos(2) > serialize_page_size) then pos(1) = pos(1) + 1 pos(2) = pos(2) - serialize_page_size end if end select if (proceed) call this%set_position (pos) else Call msg_warning ("page_ring_find: limit reached.") pos = [-1, -1] end if else ind = index (this%ring(page) (start(2):), exp) if (ind > 0) then select case (skip) case (1) pos = [start(1), start(2)+ind-2] if (pos(2) == 0) then pos(1) = pos(1) - 1 pos(2) = serialize_page_size end if case (2) pos = [start(1), start(2)+ind-1] case (3) pos = [start(1), start(2)+ind+len(exp)-2] case (4) pos = [start(1), start(2)+ind+len(exp)-1] if (pos(1) == this%last_page ()) call this%read_page () if (pos(2) > serialize_page_size) then pos(1) = pos(1) + 1 pos(2) = i_one end if end select if(proceed)call this%set_position(pos) else if (start(1) + 1 > this%active_pages (2)) then call this%read_page () page = this%ring_index(start(1)) end if page2 = this%ring_index(start(1)+1) ind = index(this%ring(page) (serialize_page_size - & len(exp)+1:)//this%ring(page2)(:len(exp)),exp) if (ind > 0) then select case (skip) case (1) pos = [start(1), serialize_page_size-len(exp)+ind-1] case (2) pos = [start(1), serialize_page_size-len(exp)+ind] case (3) pos = [start(1)+1, ind-1] case (4) pos = [start(1)+1, ind] end select if (pos(2) > serialize_page_size) then pos(1) = pos(1) + 1 pos(2) = pos(2) - serialize_page_size else if (pos(2) < 0) then pos(1) = pos(1) - 1 pos(2) = pos(2) + serialize_page_size end if end if if (proceed) call this%set_position (pos) else if (proceed) this%active_pages(1) = this%active_pages(2) call this%find (exp, [start(1) + i_one, i_one], & limit, skip, proceed, pos) end if end if end if end subroutine page_ring_find @ %def page_ring_find @ <>= subroutine page_ring_find_default (this, exp, skip, proceed, pos) class(page_ring_t), intent(inout) :: this character(*), intent(in), optional :: exp integer, intent(in) :: skip logical, intent(in) :: proceed integer(dik), dimension(2), intent(out) :: pos call this%find (exp, this%position_stack%position, this%eof_pos, & skip, proceed, pos) end subroutine page_ring_find_default @ %def page_ring_find_default @ <>= procedure :: find_pure => page_ring_find_pure <>= pure recursive function page_ring_find_pure & (this, exp, start, limit, skip) result (pos) class(page_ring_t),intent(in) :: this integer(dik), dimension(2), intent(in) :: start integer(dik), dimension(2), intent(in) :: limit character(*),intent(in) :: exp integer,optional,intent(in) :: skip integer(dik), dimension(2) :: pos integer(dik) :: page, page2, ind, actual_skip !!! Is the starting point before limit? if (start(1) <= limit(1)) then !!! Default skip is what you expect from the build-in index function if (present(skip)) then actual_skip = skip else actual_skip = 2 end if page = mod(start(1), this%ring_size) !!! Does the scanning region end on the page? if (start(1) == limit(1)) then ind = index (this%ring (page) (start(2):limit(2)),exp) else ind = index (this%ring (page) (start(2):),exp) end if if (ind > 0) then !!! substring found on first page select case (actual_skip) case (1) pos = [start(1), start(2)+ind-2] if (pos(2) == 0) then pos(1) = pos(1) - 1 pos(2) = serialize_page_size end if case (2) pos= [start(1), start(2)+ind-1] case (3) pos= [start(1), start(2)+ind+len(exp)-2] case (4) pos= [start(1), start(2)+ind+len(exp)-1] if (pos(2) > serialize_page_size) then pos(1) = pos(1) + 1 pos(2) = pos(2) - serialize_page_size end if end select else !!! Substring not found on first page. Is the next page already read? if ((start(1) >= limit(1)) .or. & (start(1)+1 > this%active_pages(2))) then !!! Either the limit is reached or the next page is not ready. pos = [0, 0] else !!! The next page is available. page2 = mod(start(1)+1, this%ring_size) !!! We concatenate the edges. When l is the length of exp, !!! then we want to concatenate the l-1 last characters of !!! page one and the first l characters of page two. ! print *,"overlap: |",this%ring(page) & ! (serialize_page_size-len(exp)+2:)//this%ring(page2) & ! (:len(exp)),"|" ind = index (this%ring(page) (serialize_page_size - & len(exp)+2:)//this%ring(page2) (:len(exp)),exp) if (ind > 0) then select case (actual_skip) case (1) pos = [start(1), serialize_page_size-len(exp)+ind] case (2) pos = [start(1), serialize_page_size-len(exp)+ind+1] case (3) pos = [start(1)+1, ind] case (4) pos = [start(1)+1, ind+1] end select else !!! EXP is not found in the overlap region. !!! We recursively search the next pages. pos = this%find_pure (exp, [start(i_one) + i_one, i_one], & limit, skip) end if end if end if else !!! Limit is before start pos = [0, 0] end if end function page_ring_find_pure @ %def page_ring_find_pure @ [[page_ring_t]] routines for positioning: <>= generic :: get_position => page_ring_get_position1, page_ring_get_position2 procedure, private :: page_ring_get_position1 procedure, private :: page_ring_get_position2 <>= pure subroutine page_ring_get_position1 (this, pos) class(page_ring_t), intent(in) :: this integer(dik), intent(out) :: pos pos = page_ring_ordinal (this%position_stack%position) end subroutine page_ring_get_position1 @ %def page_ring_get_position1 @ <>= pure subroutine page_ring_get_position2 (this, pos) class(page_ring_t), intent(in) :: this integer(dik), dimension(2), intent(out) :: pos pos = this%position_stack%position end subroutine page_ring_get_position2 @ %def page_ring_get_position2 @ <>= generic :: pop_position => pop_actual_position, pop_given_position procedure, private :: pop_actual_position => & page_ring_ring_pop_actual_position procedure, private :: pop_given_position => & page_ring_ring_pop_given_position <>= subroutine page_ring_ring_pop_actual_position (this) class(page_ring_t), intent(inout) :: this call this%position_stack%pop () end subroutine page_ring_ring_pop_actual_position @ %def page_ring_ring_pop_actual_position @ <>= subroutine page_ring_ring_pop_given_position (this, pos) class(page_ring_t), intent(inout) :: this integer(dik), dimension(2), intent(out) :: pos call this%position_stack%pop (pos) end subroutine page_ring_ring_pop_given_position @ %def page_ring_ring_pop_given_position @ <>= generic :: push_position => push_actual_position, push_given_position procedure, private :: push_actual_position => & page_ring_ring_push_actual_position procedure, private :: push_given_position => & page_ring_ring_push_given_position <>= subroutine page_ring_ring_push_actual_position (this) class(page_ring_t), intent(inout) :: this call this%position_stack%push () end subroutine page_ring_ring_push_actual_position @ %def page_ring_ring_push_actual_position @ <>= subroutine page_ring_ring_push_given_position (this, pos) class(page_ring_t), intent(inout) :: this integer(dik), dimension(2), intent(in) :: pos call this%position_stack%push (pos) end subroutine page_ring_ring_push_given_position @ %def page_ring_ring_push_given_position @ <>= procedure :: set_position => page_ring_set_position <>= subroutine page_ring_set_position (this, pos) class(page_ring_t), intent(inout) :: this integer(dik), dimension(2), intent(in) :: pos this%position_stack%position = pos end subroutine page_ring_set_position @ %def page_ring_set_position @ <>= procedure :: turn_page => page_ring_turn_page <>= subroutine page_ring_turn_page (this) class(page_ring_t), intent(inout) :: this this%position_stack%position(1) = this%position_stack%position(1) + 1 this%position_stack%position(2) = 1 end subroutine page_ring_turn_page @ %def page_ring_turn_page @ <>= procedure :: proceed => page_ring_proceed <>= subroutine page_ring_proceed (this, n, deactivate) class(page_ring_t), intent(inout) :: this integer(dik), intent(in) :: n logical, intent(in), optional :: deactivate integer(dik) :: offset offset = this%position_stack%position(2) + n do while (offset > serialize_page_size) if (this%position_stack%position(1) >= this%active_pages(2)) & call this%activate_next_page () this%position_stack%position(1) = this%position_stack%position(1) + 1 offset = offset - serialize_page_size end do this%position_stack%position(2) = offset if (present (deactivate)) then if (deactivate)this%active_pages(1) = this%actual_page () end if end subroutine page_ring_proceed @ %def page_ring_proceed @ These are the [[page_ring_t]] routines for printing: <>= procedure :: print_to_unit => page_ring_print_to_unit <>= subroutine page_ring_print_to_unit (this, unit, parents, components, peers) class(page_ring_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "Components of page_ring_t: " write (unit, "(3x,A,A)") "asynchronous: ", this%asynchronous write (unit, "(3x,A,L1)") "eof reached: ", this%eof_reached write (unit, "(3x,A,I0)") "ring_size: ", this%ring_size write (unit, "(3x,A,I0)") "unit: ", this%unit write (unit, "(3x,A,I0)") "action: ", this%action write (unit, "(3x,A,I0,I0)") & "position: ", this%position_stack%position write (unit, "(3x,A,I0)") "active_pages: ", this%active_pages write (unit, "(3x,A,I0)") "file size: ", this%eof_int write (unit, "(3x,A,I0,I0)") "eof position: ", this%eof_pos write (unit, "(3x,A,A)") "eof string: ", char(this%eof_string) if (allocated (this%ring)) then write (unit, "(3x,A)") "Ring is allocated." if (components > 0) call this%print_ring (unit) else write (unit, "(3x,A)") "Ring is not allocated." end if end subroutine page_ring_print_to_unit @ %def page_ring_print_to_unit @ <>= procedure :: print_ring => page_ring_print_ring <>= subroutine page_ring_print_ring (this, unit) class(page_ring_t), intent(in) :: this integer, intent(in) :: unit integer(dik) :: n write (unit, "(1x,A)") "Begin of page ring" do n = this%active_pages(1), this%active_pages(2) write (unit, "(3x,A,I0,A,A)") & "(", n, ")", this%ring (mod(n, this%ring_size)) end do write (unit, "(1x,A)") "End of page ring" end subroutine page_ring_print_ring @ %def page_ring_print_ring @ <>= procedure :: print_position => page_ring_print_position <>= subroutine page_ring_print_position(this) class(page_ring_t), intent(inout) :: this print *, this%actual_position(), & this%ring(this%actual_index()) (:this%actual_offset() - 1), "|", & this%ring(this%actual_index()) (this%actual_offset():) end subroutine page_ring_print_position @ %def page_ring_print_position @ Here are the [[page_ring_t]] routines for writing: <>= procedure :: put => page_ring_put <>= subroutine page_ring_put (this) class(page_ring_t), intent(inout) :: this end subroutine page_ring_put @ %def page_ring_put @ <>= generic :: push => push_string, push_integer, push_integer_dik, & push_real, push_integer_array, push_integer_array_dik, & push_real_array <>= procedure, private :: push_string => page_ring_push_string <>= recursive subroutine page_ring_push_string (this, string) class(page_ring_t), intent(inout) :: this character(*), intent(in) :: string integer(dik) :: cut, l l = len(string) if (l <= serialize_page_size-this%actual_offset()+1) then this%ring(this%actual_index()) & (this%actual_offset():this%actual_offset()+l-1)=string if (l == serialize_page_size-this%actual_offset()+1) then call this%break() call this%flush() else call this%proceed(l) end if else cut = serialize_page_size-this%actual_offset() + 1 call this%push_string(string(:cut)) call this%push_string(string(cut+1:)) end if end subroutine page_ring_push_string @ %def page_ring_push_string @ <>= procedure, private :: push_integer => page_ring_push_integer <>= subroutine page_ring_push_integer (this, in) class(page_ring_t), intent(inout) :: this integer, intent(in) :: in call this%push_integer_dik (int(in,kind=dik)) end subroutine page_ring_push_integer @ %def page_ring_push_integer @ <>= procedure, private :: push_integer_dik => page_ring_push_integer_dik <>= recursive subroutine page_ring_push_integer_dik (this, int) class(page_ring_t), intent(inout) :: this integer(dik), intent(in) :: int integer(dik) :: int1 if (int < 0) then call this%push ("-") call this%push_integer_dik (-int) else if (int > 9) call this%push (int/10) int1 = mod(int, 10*i_one) select case (int1) case (0) call this%push ("0") case (1) call this%push ("1") case (2) call this%push ("2") case (3) call this%push ("3") case (4) call this%push ("4") case (5) call this%push ("5") case (6) call this%push ("6") case (7) call this%push ("7") case (8) call this%push ("8") case (9) call this%push ("9") end select end if end subroutine page_ring_push_integer_dik @ %def page_ring_push_integer_dik @ <>= procedure, private :: push_integer_array => page_ring_push_integer_array <>= subroutine page_ring_push_integer_array(this,int) class(page_ring_t), intent(inout) :: this integer, dimension(:), intent(in) :: int integer :: n do n = 1, size(int) call this%push (int(n)) call this%push (" ") end do end subroutine page_ring_push_integer_array @ %def page_ring_push_integer_array @ <>= procedure, private :: push_integer_array_dik => & page_ring_push_integer_array_dik <>= subroutine page_ring_push_integer_array_dik(this,int) class(page_ring_t), intent(inout) :: this integer(dik), dimension(:), intent(in) :: int integer(dik) :: n do n = 1, size(int) call this%push (int(n)) call this%push (" ") end do end subroutine page_ring_push_integer_array_dik @ %def page_ring_push_integer_array_dik @ <>= procedure, private :: push_real => page_ring_push_real <>= subroutine page_ring_push_real (this, dou) class(page_ring_t), intent(inout) :: this real(default), intent(in) :: dou integer(dik) :: f ! print *,"page_ring_push_real: ",dou if (dou == 0D0) then call this%push ("0") else f = int (scale (fraction(dou), digits(dou)), kind=dik) call this%push (digits(dou)) call this%push (":") call this%push (f) call this%push (":") call this%push (exponent(dou)) end if call this%push (" ") end subroutine page_ring_push_real @ %def page_ring_push_real @ <>= procedure, private :: push_real_array => page_ring_push_real_array <>= subroutine page_ring_push_real_array (this, dou) class(page_ring_t), intent(inout) :: this real(default), dimension(:), intent(in) :: dou integer(dik) :: n do n=1, size(dou) call this%push (dou(n)) end do end subroutine page_ring_push_real_array @ %def page_ring_push_real_array @ <>= procedure :: get_character => page_ring_get_character <>= elemental function page_ring_get_character (this) class(page_ring_t), intent(in) :: this character :: page_ring_get_character page_ring_get_character = this%ring (this%actual_index()) & (this%actual_offset():this%actual_offset()) end function page_ring_get_character @ %def page_ring_get_character @ <>= procedure :: allocate_substring => page_ring_allocate_substring <>= subroutine page_ring_allocate_substring (this, p1, p2, string) class(page_ring_t), intent(in) :: this integer(dik), dimension(2), intent(in) :: p1, p2 character(:), allocatable, intent(out) :: string string = this%substring (p1, p2) end subroutine page_ring_allocate_substring @ %def page_ring_allocate_substring @ <>= procedure :: pop_character => page_ring_pop_character <>= subroutine page_ring_pop_character (this, c) class(page_ring_t), intent(inout) :: this character, intent(out) :: c c = this%ring (this%actual_index()) & (this%actual_offset():this%actual_offset()) if (this%actual_offset () == serialize_page_size) call this%read_page call this%proceed (i_one) end subroutine page_ring_pop_character @ %def page_ring_pop_character @ <>= procedure :: pop_by_keys => page_ring_pop_by_keys <>= subroutine page_ring_pop_by_keys (this, start, stop, inclusive, res) class(page_ring_t), intent(inout) :: this character(*), intent(in), optional :: start character(*), intent(in) :: stop logical, optional, intent(in) :: inclusive character(len=*), intent(out) :: res integer(dik), dimension(2) :: i1, i2 if (inclusive) then call this%find (start, 2, .true., i1) call this%find (stop, 3, .false., i2) else call this%find (start, 4, .true., i1) call this%find (stop, 1, .false., i2) end if res = this%substring (i1, i2) call this%set_position (i2) end subroutine page_ring_pop_by_keys @ %def page_ring_pop_by_keys @ <>= generic :: substring => page_ring_substring1, page_ring_substring2 procedure, private :: page_ring_substring1 procedure, private :: page_ring_substring2 @ <>= pure function page_ring_substring1 (this, i) result (res) class(page_ring_t), intent(in) :: this integer(dik), dimension(2,2), intent(in) :: i character(ring_position_metric1(i)) :: res integer(dik) :: page, pos if (i(1,1) == i(1,2)) then res = this%ring (mod(i(1,1), this%ring_size)) (i(2,1):i(2,2)) else pos = serialize_page_size - i(2,1) res(1:pos+1) = this%ring (mod(i(1,1),this%ring_size)) (i(2,1):) do page = i(1,1) + 1, i(1,1) - 1 res (pos+2:pos+2+serialize_page_size) = & this%ring (mod(page,this%ring_size)) pos = pos + serialize_page_size end do res(pos+2:pos+1+i(2,2)) = & this%ring (mod(page,this%ring_size)) (1:i(2,2)) end if end function page_ring_substring1 @ %def page_ring_substring1 @ <>= pure function page_ring_substring2 (this, i1, i2) result (res) class(page_ring_t), intent(in) :: this integer(dik), dimension(2), intent(in) :: i1,i2 character(ring_position_metric2(i1,i2)) :: res integer(dik) :: page, pos if (i1(1) == i2(1)) then res = this%ring(mod(i1(1),this%ring_size)) (i1(2):i2(2)) else pos = serialize_page_size - i1(2) res(1:pos+1) = this%ring(mod(i1(1),this%ring_size)) (i1(2):) do page = i1(1)+1, i2(1)-1 res(pos+2:pos+2+serialize_page_size) = & this%ring(mod(page, this%ring_size)) pos = pos + serialize_page_size end do res(pos+2:pos+1+i2(2)) = this%ring(mod(page, this%ring_size)) (1:i2(2)) end if end function page_ring_substring2 @ %def page_ring_substring2 @ <>= generic :: substring_by_keys => page_ring_character_by_keys, & page_ring_positions_by_keys procedure, private :: page_ring_character_by_keys procedure, private :: page_ring_positions_by_keys <>= pure recursive subroutine page_ring_character_by_keys (this, exp1, & exp2, start, limit, inclusive, length, string) class(page_ring_t), intent(in) :: this character(*), intent(in) :: exp1, exp2 integer(dik), dimension(2), intent(in) :: start, limit logical, optional, intent(in) :: inclusive integer(dik), intent(out), optional :: length character(:), allocatable, intent(out) :: string integer(dik), dimension(2,2) :: pos call this%substring_by_keys (exp1, exp2, start, limit, & inclusive, length, pos) string = this%substring (pos(:,1),pos(:,2)) end subroutine page_ring_character_by_keys @ %def page_ring_character_by_keys @ <>= pure recursive subroutine page_ring_positions_by_keys (this, exp1, & exp2, start, limit, inclusive, length, pos) class(page_ring_t), intent(in) :: this character(*), intent(in) :: exp1, exp2 integer(dik), dimension(2), intent(in) :: start, limit logical, optional, intent(in) :: inclusive integer(dik), intent(out), optional :: length integer(dik), dimension(2,2), intent(out) :: pos if (inclusive) then pos(1:2,1) = this%find_pure (exp1, start, limit, 2) else pos(1:2,1) = this%find_pure (exp1,start, limit, 4) end if ! print *,pos1 if (present(length)) then length = 0 end if if (pos(2,1) > 0) then if (inclusive) then pos(1:2,2) = this%find_pure (exp2, pos(1:2,1), limit, 3) else pos(1:2,2) = this%find_pure (exp2, pos(1:2,1), limit, 1) end if ! print *,pos2 if (pos(2,2) > 0) then if (present (length)) then length = ring_position_metric1 (pos) end if end if end if end subroutine page_ring_positions_by_keys @ %def page_ring_positions_by_keys @ <>= generic :: pop => pop_string, pop_integer, pop_integer_dik, & pop_real, pop_logical, pop_integer_array, & pop_integer_array_dik, pop_real_array <>= procedure, private :: pop_string => page_ring_pop_string <>= recursive subroutine page_ring_pop_string (this, res) class(page_ring_t), intent(inout) :: this character(len=*), intent(out) :: res integer(dik) :: n, cut n = len(res) cut = serialize_page_size-this%actual_offset() + 1 if (n <= cut) then res = this%ring (this%actual_index()) & (this%actual_offset():this%actual_offset()+n) if (n == cut) then call this%read_page end if call this%proceed (n) else call this%pop (res(:cut)) call this%pop (res(cut+1:)) end if end subroutine page_ring_pop_string @ %def page_ring_pop_string @ <>= procedure, private :: pop_integer => page_ring_pop_integer <>= subroutine page_ring_pop_integer (this,in) class(page_ring_t), intent(inout) :: this integer, intent(out) :: in integer(dik) :: in_dik call this%pop (in_dik) in = int(in_dik) end subroutine page_ring_pop_integer @ %def page_ring_pop_integer @ <>= procedure, private :: pop_integer_dik => page_ring_pop_integer_dik <>= subroutine page_ring_pop_integer_dik (this, int) class(page_ring_t), intent(inout) :: this integer(dik), intent(out) :: int integer(dik) :: int1 integer(dik) :: sign character :: c int = 0 sign = 1 c = " " do while (scan (c, serialize_integer_characters) == 0) call this%pop_character (c) end do if (c == "-") then sign = -1 call this%pop_character (c) end if do while (scan (c, serialize_integer_characters) > 0) int = int * 10 select case (c) case ("1") int = int + 1 case ("2") int = int + 2 case ("3") int = int + 3 case ("4") int = int + 4 case ("5") int = int + 5 case ("6") int = int + 6 case ("7") int = int + 7 case ("8") int = int + 8 case ("9") int = int + 9 end select call this%pop_character (c) end do int = int * sign if (c == "<") call this%proceed (-i_one) end subroutine page_ring_pop_integer_dik @ %def page_ring_pop_integer_dik @ <>= procedure, private :: pop_integer_array => page_ring_pop_integer_array @ <>= subroutine page_ring_pop_integer_array (this, int) class(page_ring_t), intent(inout) :: this integer, dimension(:), intent(out) :: int integer :: n do n = 1, size(int) call this%pop (int(n)) end do end subroutine page_ring_pop_integer_array @ %def page_ring_pop_integer_array @ <>= procedure, private :: pop_integer_array_dik => & page_ring_pop_integer_array_dik @ <>= subroutine page_ring_pop_integer_array_dik (this, int) class(page_ring_t), intent(inout) :: this integer(dik), dimension(:), intent(out) :: int integer(dik) :: n do n = 1, size(int) call this%pop (int(n)) end do end subroutine page_ring_pop_integer_array_dik @ %def page_ring_pop_integer_array_dik @ <>= procedure, private :: pop_logical => page_ring_pop_logical <>= subroutine page_ring_pop_logical (this, l) class(page_ring_t), intent(inout) :: this logical, intent(out) :: l character(1) :: lc call this%pop (lc) do while (scan (lc,"tTfF") == 0) call this%pop (lc) end do read (lc, "(L1)") l end subroutine page_ring_pop_logical @ %def page_ring_pop_logical @ <>= procedure, private :: pop_real => page_ring_pop_real @ <>= subroutine page_ring_pop_real (this, def, skip) class(page_ring_t), intent(inout) :: this real(default), intent(out) :: def logical, optional, intent(in) :: skip integer(dik) :: d, f, e call this%pop (d) if (d == i_zero) then def = zero else call this%pop (f) call this%pop (e) def = set_exponent (scale (real(f, kind=default), -d), e) end if if (present (skip)) then if (.not. skip) call this%proceed (-i_one) end if end subroutine page_ring_pop_real @ %def page_ring_pop_real @ <>= procedure, private :: pop_real_array => page_ring_pop_real_array @ <>= subroutine page_ring_pop_real_array (this, def, skip) class(page_ring_t), intent(inout) :: this real(default), dimension(:), intent(out) :: def logical, optional, intent(in) :: skip integer(dik) :: n call this%pop_real (def(1)) do n = 2, size(def) call this%pop_real (def(n)) end do if (present(skip)) then if (.not. skip) call this%proceed (-i_one) end if end subroutine page_ring_pop_real_array @ %def page_ring_pop_real_array @ <>= procedure :: close => page_ring_close <>= subroutine page_ring_close (this) class(page_ring_t), intent(inout) :: this if (this%action == 1) then call this%flush () ! call this%print_position() if (this%asynchronous) then write (this%unit, asynchronous="yes") & this%ring (this%actual_index()) (:this%actual_offset() - 1) else write (this%unit, asynchronous="no") & this%ring (this%actual_index()) (:this%actual_offset() - 1) end if end if close (this%unit) end subroutine page_ring_close @ %def page_ring_close @ <>= procedure :: ring_index => page_ring_ring_index <>= elemental integer(dik) function page_ring_ring_index (this, n) class(page_ring_t), intent(in) :: this integer(dik), intent(in) :: n page_ring_ring_index = mod(n, this%ring_size) end function page_ring_ring_index @ %def page_ring_ring_index @ <>= procedure, private :: activate_next_page => page_ring_activate_next_page <>= subroutine page_ring_activate_next_page (this) class(page_ring_t), intent(inout) :: this if (this%active_pages(2) - this%active_pages(1) + 1 >= & this%ring_size) call this%enlarge this%active_pages(2) = this%active_pages(2) + 1 end subroutine page_ring_activate_next_page @ %def page_ring_activate_next_page @ <>= procedure, private :: enlarge => page_ring_enlarge <>= subroutine page_ring_enlarge (this) class(page_ring_t), intent(inout) :: this character(serialize_page_size), dimension(:), allocatable :: tmp_ring integer(dik) :: n call move_alloc (this%ring, tmp_ring) allocate (this%ring(0:this%ring_size*2-1)) do n = this%active_pages(1), this%active_pages(2) this%ring (mod(n,this%ring_size*2)) = tmp_ring (mod(n,this%ring_size)) end do this%ring_size = this%ring_size * 2 end subroutine page_ring_enlarge @ %def page_ring_enlarge @ These are specific implementations of generic procedures: <>= procedure, private :: actual_index => page_ring_actual_index <>= elemental integer(dik) function page_ring_actual_index (this) class(page_ring_t), intent(in) :: this page_ring_actual_index = & mod (this%position_stack%position(1), this%ring_size) end function page_ring_actual_index @ %def page_ring_actual_index @ <>= procedure, private :: actual_page => page_ring_actual_page <>= elemental integer(dik) function page_ring_actual_page (this) class(page_ring_t), intent(in) :: this page_ring_actual_page = this%position_stack%position(1) end function page_ring_actual_page @ %def page_ring_actual_page @ <>= procedure, private :: actual_offset => page_ring_actual_offset <>= elemental integer(kind=dik) function page_ring_actual_offset(this) class(page_ring_t),intent(in) :: this page_ring_actual_offset=this%position_stack%position(2) end function page_ring_actual_offset @ %def page_ring_actual_offset @ <>= procedure, private :: actual_position => page_ring_actual_position <>= pure function page_ring_actual_position(this) class(page_ring_t), intent(in) :: this integer(dik), dimension(2) :: page_ring_actual_position page_ring_actual_position = this%position_stack%position end function page_ring_actual_position @ %def page_ring_actual_position @ <>= procedure, private :: first_index => page_ring_first_index <>= elemental integer(dik) function page_ring_first_index (this) class(page_ring_t), intent(in) :: this page_ring_first_index = mod(this%active_pages(1), this%ring_size) end function page_ring_first_index @ %def page_ring_first_index @ <>= procedure, private :: first_page => page_ring_first_page <>= elemental integer(dik) function page_ring_first_page (this) class(page_ring_t), intent(in) :: this page_ring_first_page = this%active_pages(1) end function page_ring_first_page @ %def page_ring_first_page @ <>= procedure, private :: last_index => page_ring_last_index <>= elemental integer(dik) function page_ring_last_index (this) class(page_ring_t), intent(in) :: this page_ring_last_index = mod(this%active_pages(2), this%ring_size) end function page_ring_last_index @ %def page_ring_last_index @ <>= procedure, private :: last_page => page_ring_last_page <>= elemental integer(dik) function page_ring_last_page (this) class(page_ring_t), intent(in) :: this page_ring_last_page = this%active_pages(2) end function page_ring_last_page @ %def page_ring_last_page @ <>= public :: marker_t <>= type, extends (page_ring_t) :: marker_t private integer(dik) :: indentation=0 integer(dik) :: n_instances=0 logical :: do_break=.true. logical :: do_indent=.false. class(serializable_ref_type),pointer :: heap=>null() class(serializable_ref_type),pointer :: references=>null() contains <> end type marker_t @ %def marker_t @ <>= procedure :: mark_begin => marker_mark_begin <>= subroutine marker_mark_begin (this, tag, type, name, target, pointer, shape) class(marker_t), intent(inout) :: this character(*), intent(in) :: tag character(*), intent(in), optional :: type, name integer(kind=dik), intent(in), optional :: target, pointer integer,intent(in), dimension(:), optional :: shape call this%indent () call this%push ("<") call this%push (tag) if (present (type)) call this%push (' type="'//type//'"') if (present (name)) call this%push (' name="'//name//'"') if (present (target)) then call this%push (' target="') call this%push (target) call this%push ('"') end if if (present (pointer))then call this%push (' pointer="') call this%push (pointer) call this%push ('"') end if if (present (shape))then call this%push (' shape="') call this%push (shape) call this%push ('"') end if call this%push (">") this%indentation = this%indentation + 1 end subroutine marker_mark_begin @ %def marker_mark_begin @ <>= procedure :: mark_instance_begin => marker_mark_instance_begin <>= subroutine marker_mark_instance_begin & (this, ser, name, target, pointer, shape) class(marker_t), intent(inout) :: this class(ser_class_t), intent(in) :: ser character(*), intent(in) :: name integer(dik), intent(in), optional :: target, pointer integer, dimension(:), intent(in), optional :: shape character(:), allocatable :: this_type call ser%get_type (this_type) call this%mark_begin ("ser", this_type, name, target, pointer, shape) end subroutine marker_mark_instance_begin @ %def marker_mark_instance_begin @ <>= procedure :: mark_end => marker_mark_end <>= subroutine marker_mark_end (this, tag) class(marker_t), intent(inout) :: this character(*), intent(in), optional :: tag this%indentation = this%indentation - 1 call this%indent () if (present (tag)) then call this%push ("") else call this%push ("") end if end subroutine marker_mark_end @ %def marker_mark_end @ <>= procedure :: mark_instance_end => marker_mark_instance_end <>= subroutine marker_mark_instance_end (this) class(marker_t), intent(inout) :: this call this%mark_end ("ser") end subroutine marker_mark_instance_end @ %def marker_mark_instance_end @ <>= generic :: mark => mark_logical, & mark_integer, mark_integer_array, mark_integer_matrix, & mark_integer_dik, mark_integer_array_dik, mark_integer_matrix_dik, & mark_default, mark_default_array, mark_default_matrix, mark_string procedure, private :: mark_logical => marker_mark_logical <>= subroutine marker_mark_logical (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name logical, intent(in) :: content call this%indent () call this%push ("<"//name//">") if (content) then call this%push ("T") else call this%push ("F") end if call this%push ("") end subroutine marker_mark_logical @ %def marker_mark_logical @ <>= procedure :: mark_integer => marker_mark_integer <>= subroutine marker_mark_integer (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_integer @ %def marker_mark_integer @ <>= procedure :: mark_integer_array => marker_mark_integer_array <>= subroutine marker_mark_integer_array (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, dimension(:), intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_integer_array @ %def marker_mark_integer_array @ <>= procedure :: mark_integer_matrix => marker_mark_integer_matrix <>= subroutine marker_mark_integer_matrix (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, dimension(:,:), intent(in) :: content integer :: n integer, dimension(2) :: s s= shape(content) call this%indent () call this%push ("<"//name//">") do n = 1, s(2) call this%push (content(:,n)) call this%push (" ") end do call this%push ("") end subroutine marker_mark_integer_matrix @ %def marker_mark_integer_matrix @ <>= procedure :: mark_integer_dik => marker_mark_integer_dik <>= subroutine marker_mark_integer_dik (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_integer_dik @ %def marker_marker_integer_dik @ <>= procedure :: mark_integer_array_dik => marker_mark_integer_array_dik <>= subroutine marker_mark_integer_array_dik (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), dimension(:), intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_integer_array_dik @ %def marker_mark_integer_array_dik @ <>= procedure :: mark_integer_matrix_dik => marker_mark_integer_matrix_dik <>= subroutine marker_mark_integer_matrix_dik (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), dimension(:,:), intent(in) :: content integer :: n integer, dimension(2) :: s call this%indent () call this%push ("<"//name//">") do n = 1, s(2) call this%push (content(:,n)) call this%push (" ") end do call this%push ("") end subroutine marker_mark_integer_matrix_dik @ %def marker_mark_integer_matrix_dik @ <>= procedure :: mark_default => marker_mark_default <>= subroutine marker_mark_default (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_default @ %def marker_mark_default @ <>= procedure :: mark_default_array => marker_mark_default_array <>= subroutine marker_mark_default_array (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), dimension(:), intent(in) :: content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_default_array @ %def marker_mark_default_array @ <>= procedure :: mark_default_matrix => marker_mark_default_matrix <>= subroutine marker_mark_default_matrix (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), dimension(:,:), intent(in) :: content integer :: n integer, dimension(2) :: s s = shape(content) call this%indent () call this%push ("<"//name//">") do n = 1, s(2) call this%push (content(:,n)) call this%push (" ") end do call this%push ("") end subroutine marker_mark_default_matrix @ %def marker_mark_default_matrix @ <>= procedure :: mark_string => marker_mark_string <>= subroutine marker_mark_string (this, name, content) class(marker_t), intent(inout) :: this character(*), intent(in) :: name, content call this%indent () call this%push ("<"//name//">") call this%push (content) call this%push ("") end subroutine marker_mark_string @ %def marker_mark_string @ <>= procedure :: mark_instance => marker_mark_instance <>= recursive subroutine marker_mark_instance (this, ser, name, target, pointer) class(marker_t), intent(inout) :: this class(ser_class_t), intent(in) :: ser character(len=*), intent(in) :: name integer(dik), intent(in), optional :: target, pointer integer(dik) :: status call this%mark_instance_begin (ser, name, target, pointer) call ser%write_to_marker (this, status) call this%mark_end ("ser") end subroutine marker_mark_instance @ %def marker_mark_instance @ <>= procedure :: mark_target => marker_mark_target <>= recursive subroutine marker_mark_target (this, name, ser) class(marker_t), intent(inout) :: this class(ser_class_t), target, intent(in) :: ser character(len=*), intent(in) :: name this%n_instances = this%n_instances + 1 call this%push_heap (ser, this%n_instances) call this%mark_instance (ser, name, target = this%n_instances) end subroutine marker_mark_target @ %def marker_mark_target @ <>= procedure :: mark_allocatable => marker_mark_allocatable <>= subroutine marker_mark_allocatable (this, name, ser) class(marker_t), intent(inout) :: this class(ser_class_t), allocatable, intent(in) :: ser character(len=*), intent(in) :: name if (allocated (ser)) then call this%mark_instance (ser, name) else call this%mark_null (name) end if end subroutine marker_mark_allocatable @ %def marker_mark_allocatable @ <>= procedure :: mark_pointer => marker_mark_pointer <>= recursive subroutine marker_mark_pointer (this, name, ser) class(marker_t), intent(inout) :: this class(ser_class_t), pointer, intent(in) :: ser character(len=*), intent(in) :: name character(:), allocatable :: type integer(dik) :: p if (associated (ser)) then call this%search_heap (ser, p) if (p > 0) then call ser%get_type (type) call this%push ('') else call this%mark_target (name, ser) end if else call this%mark_null (name) end if end subroutine marker_mark_pointer @ %def marker_mark_pointer @ <>= procedure :: mark_null => marker_mark_null <>= subroutine marker_mark_null (this, name) class(marker_t), intent(inout) :: this character(*), intent(in) :: name call this%indent () call this%push ('') end subroutine marker_mark_null @ %def marker_mark_null @ <>= procedure :: mark_nothing => marker_mark_nothing <>= subroutine marker_mark_nothing (this, name) class(marker_t), intent(inout) :: this character(*), intent(in) :: name call this%indent () call this%push ('<') call this%push (name) call this%push ('/>') end subroutine marker_mark_nothing @ %def marker_mark_nothing @ <>= procedure :: mark_empty => marker_mark_empty <>= subroutine marker_mark_empty (this, tag, type, name, target, pointer, shape) class(marker_t), intent(inout) :: this character(*), intent(in) :: tag character(*), intent(in), optional :: type, name integer(dik), intent(in), optional :: target, pointer integer, dimension(:), intent(in), optional :: shape call this%push ("<") call this%push (tag) if (present (type)) call this%push (' type="'//type//'"') if (present (name)) call this%push (' name="'//name//'"') if (present (target)) then call this%push (' target="') call this%push (target) call this%push ('"') end if if (present (pointer)) then call this%push (' pointer="') call this%push (pointer) call this%push ('"') end if if (present (shape)) then call this%push (' shape="') call this%push (shape) call this%push ('"') end if call this%push ("/>") end subroutine marker_mark_empty @ %def marker_mark_empty @ <>= procedure :: pick_begin => marker_pick_begin <>= subroutine marker_pick_begin (this, tag, type, name, target, & pointer, shape, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: tag integer(dik), dimension(2,2),intent(out),optional :: type,name integer(dik), intent(out), optional :: target, pointer integer, dimension(:), allocatable, optional, intent(out) :: shape integer(dik), intent(out) :: status integer(dik), dimension(2) :: p1, p2, p3 integer(dik) :: l call this%find ("<", skip=4, proceed=.true., pos=p1) call this%find (">", skip=1, proceed=.false., pos=p2) p3 = this%find_pure (" ",p1,p2,skip=1) if (p3(2) > 0) then if (this%substring(p1, p3) == tag) then status = serialize_ok if (present (type)) then call this%substring_by_keys & ('type="','"', p3, p2, .false., l, type) if (l <= 0) then call msg_error ("marker_pick_begin: No type found") status = serialize_wrong_type end if end if if (present (name)) then call this%substring_by_keys & ('name="','"', p3, p2, .false., l, name) if (l <= 0) then call msg_error ("marker_pick_begin: No name found") status = serialize_wrong_name call this%print_position () stop end if end if if (present (target)) then p1 = this%find_pure ('target="', p3, p2, 4) if (p1(2) > 0) then call this%set_position (p1) call this%pop (target) else target = -1 status = serialize_ok end if end if if (present (pointer)) then p1=this%find_pure ('pointer="', p3, p2, 4) if (p1(2) > 0)then call this%set_position (p1) call this%pop (pointer) else pointer = -1 status = serialize_ok end if end if if (present (shape)) then p1 = this%find_pure ('shape="', p3, p2, 4) if (p1(2) > 0) then call this%set_position (p1) call this%pop (shape) else status = serialize_ok end if end if else call msg_error ("marker_pick_begin: Wrong tag. Expected: " // & tag // " Found: " // this%substring(p1, p3)) status = serialize_wrong_tag call this%print_position () end if else if (this%substring(p1, p2) == tag) then status = serialize_ok else call msg_error ("marker_pick_begin: Wrong tag. Expected: " // & tag // " Found: " // this%substring(p1, p2)) status = serialize_wrong_tag end if end if call this%set_position (p2) call this%proceed (i_one*2, .true.) end subroutine marker_pick_begin @ %def marker_pick_begin @ <>= procedure :: query_instance_begin => marker_query_instance_begin <>= subroutine marker_query_instance_begin & (this, type, name, target, pointer, shape,status) class(marker_t), intent(inout) :: this integer(dik), dimension(2,2), intent(out), optional :: type, name integer(dik), intent(out), optional :: target, pointer integer, dimension(:), allocatable, intent(out), optional :: shape integer(dik), intent(out) :: status call this%pick_begin ("ser", type, name, target, pointer, shape, status) end subroutine marker_query_instance_begin @ %def marker_query_instance_begin @ <>= procedure :: pick_instance_begin => marker_pick_instance_begin <>= subroutine marker_pick_instance_begin & (this, name, type, target, pointer, shape, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), dimension(2,2), intent(out), optional :: type integer(dik), intent(out), optional :: target,pointer integer, dimension(:), allocatable,intent(out), optional :: shape integer(dik), intent(out) :: status integer(dik), dimension(2,2) :: read_name call this%query_instance_begin & (type, read_name, target, pointer, shape, status) if (status == serialize_ok) then if (.not. this%str_equal (name, read_name)) & status = serialize_wrong_name end if end subroutine marker_pick_instance_begin @ %def marker_pick_instance_begin @ <>= procedure :: pick_end => marker_pick_end <>= subroutine marker_pick_end (this, tag, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: tag integer(dik), intent(out) :: status integer(dik), dimension(2) :: p1, p2 call this%find ("", skip=1, proceed=.false., pos=p2) if (tag == this%substring (p1, p2)) then status = serialize_ok else call msg_error ("marker_pick_end: Wrong tag. Expected: " // tag & // " Found: " // this%substring (p1, p2)) ! print *,"p1=",p1,"p2=",p2 call this%print_position () end if call this%set_position (p2) call this%proceed (i_one*2, .true.) end subroutine marker_pick_end @ %def marker_pick_end @ <>= procedure :: pick_instance_end => marker_pick_instance_end <>= subroutine marker_pick_instance_end (this, status) class(marker_t), intent(inout) :: this integer(dik), intent(out) :: status call this%pick_end ("ser",status) end subroutine marker_pick_instance_end @ %def marker_pick_instance_end @ <>= procedure :: pick_instance => marker_pick_instance <>= subroutine marker_pick_instance (this, name, ser, status) class(marker_t), intent(inout) :: this class(ser_class_t), intent(out) :: ser character(*), intent(in) :: name integer(dik), intent(out) :: status integer(dik), dimension(2,2) :: type, r_name call this%pick_begin ("ser", type, r_name, status=status) if (status == serialize_ok) then if (ser%verify_type (this%substring(type))) then if (this%str_equal (name, r_name)) then call ser%read_from_marker (this, status) call this%pick_end ("ser", status) else call msg_error ("marker_pick_instance: Name mismatch") write (*,*) "Expected: ", name, " Found: ", r_name status = serialize_wrong_name call this%print_position end if else call msg_error ("marker_pick_instance: Type mismatch: ") write (*,*) type call ser%write_type (output_unit) write (*,*) status = serialize_wrong_type call this%print_position end if end if end subroutine marker_pick_instance @ %def marker_pick_instance @ <>= procedure :: pick_target => marker_pick_target <>= subroutine marker_pick_target (this, name, ser, status) class(marker_t), intent(inout) :: this class(ser_class_t), target, intent(out) :: ser character(*), intent(in) :: name integer(dik), intent(out) :: status integer(dik), dimension(2,2) :: type, r_name integer(dik) :: target call this%pick_begin ("ser", type, r_name, target, status=status) if (status == serialize_ok) then if (ser%verify_type (this%substring(type))) then if (this%str_equal (name, r_name)) then call ser%read_target_from_marker (this, status) if (target > 0) call this%push_heap (ser, target) else call msg_error ("marker_pick_instance: Name mismatch: ") write (*,*) "Expected: ", name, " Found: ", r_name status = serialize_wrong_name end if else call msg_error ("marker_pick_instance: Type mismatch: ") write (*,*) type status = serialize_wrong_type end if end if call this%pick_end ("ser", status) end subroutine marker_pick_target @ %def marker_pick_target @ <>= procedure :: pick_allocatable => marker_pick_allocatable <>= subroutine marker_pick_allocatable (this, name, ser) class(marker_t), intent(inout) :: this character(*), intent(in) :: name class(ser_class_t), allocatable, intent(out) :: ser class(ser_class_t), pointer :: ref integer(dik),dimension(2,2) :: type, r_name integer(dik) :: status call this%pick_begin ("ser", type, r_name, status=status) if (status == serialize_ok) then if (ser%verify_type (this%substring(type))) then if (this%str_equal (name, r_name)) then call this%search_reference (type, ref) if (associated (ref)) then allocate (ser, source=ref) call ser%read_from_marker (this, status) else call msg_error ("marker_pick_allocatable:") write (*,*) "Type ", type, " not found on reference stack." end if else call msg_error ("marker_pick_instance: Name mismatch: ") write (*,*) "Expected: ",name," Found: ",r_name status = serialize_wrong_name end if else call msg_error ("marker_pick_instance: Type mismatch: ") write (*,*) type status = serialize_wrong_type end if end if call this%pick_end ("ser", status) end subroutine marker_pick_allocatable @ %def marker_pick_allocatable @ <>= procedure :: pick_pointer => marker_pick_pointer <>= recursive subroutine marker_pick_pointer (this, name, ser) class(marker_t), intent(inout) :: this character(*), intent(in) :: name class(ser_class_t), pointer, intent(out) :: ser class(ser_class_t), pointer :: ref integer(dik), dimension(2,2) :: type, r_name integer(dik) :: status, t, p nullify (ser) call this%pick_begin & ("ser", type, r_name, target=t, pointer=p, status=status) if (status == serialize_ok) then if (.not. this%str_equal ("null",type)) then if (p > 0) then call this%search_heap (p, ser) else call this%search_reference (type, ref) if (associated (ref))then allocate (ser, source=ref) call ser%read_target_from_marker (this, status) call this%pick_end ("ser", status) if (t > 0) call this%push_heap (ser, t) else write (*,*) "marker_pick_pointer:& & Type ",type," not found on reference stack." end if end if end if end if end subroutine marker_pick_pointer @ %def marker_pick_pointer @ <>= generic :: pick => pick_logical, & pick_integer, pick_integer_array, pick_integer_matrix, & pick_integer_dik, pick_integer_array_dik, pick_integer_matrix_dik, & pick_default, pick_default_array, pick_default_matrix, pick_string procedure :: pick_logical => marker_pick_logical <>= subroutine marker_pick_logical (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name logical, intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_logical @ %def marker_pick_logical @ <>= procedure :: pick_integer => marker_pick_integer <>= subroutine marker_pick_integer (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_integer @ %def marker_pick_integer @ <>= procedure :: pick_integer_array => marker_pick_integer_array <>= subroutine marker_pick_integer_array (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, dimension(:), intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_integer_array @ %def marker_pick_integer_array @ <>= procedure :: pick_integer_matrix => marker_pick_integer_matrix <>= subroutine marker_pick_integer_matrix (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer, dimension(:,:), intent(out) :: content integer(dik), intent(out) :: status integer :: n integer, dimension(2) :: s s = shape(content) call this%pick_begin (name, status=status) if (status == serialize_ok) then do n = 1, s(2) call this%pop (content(:,n)) end do call this%pick_end (name, status) end if end subroutine marker_pick_integer_matrix @ %def marker_pick_integer_matrix @ <>= procedure :: pick_integer_dik => marker_pick_integer_dik <>= subroutine marker_pick_integer_dik (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name,status) end if end subroutine marker_pick_integer_dik @ %def marker_pick_integer_dik @ <>= procedure :: pick_integer_array_dik => marker_pick_integer_array_dik <>= subroutine marker_pick_integer_array_dik (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), dimension(:), intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_integer_array_dik @ %def marker_pick_integer_array_dik @ <>= procedure :: pick_integer_matrix_dik => marker_pick_integer_matrix_dik <>= subroutine marker_pick_integer_matrix_dik (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik), dimension(:,:), intent(out) :: content integer(dik), intent(out) :: status integer :: n integer, dimension(2) :: s s = shape(content) call this%pick_begin (name, status=status) if (status == serialize_ok) then do n = 1, s(2) call this%pop (content(:,n)) end do call this%pick_end (name,status) end if end subroutine marker_pick_integer_matrix_dik @ %def marker_pick_integer_matrix_dik @ <>= procedure :: pick_default => marker_pick_default <>= subroutine marker_pick_default (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name,status) end if end subroutine marker_pick_default @ %def marker_pick_default @ <>= procedure :: pick_default_array => marker_pick_default_array <>= subroutine marker_pick_default_array (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), dimension(:), intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_default_array @ %def marker_pick_default_array @ <>= procedure :: pick_default_matrix => marker_pick_default_matrix <>= subroutine marker_pick_default_matrix (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name real(default), dimension(:,:), intent(out) :: content integer(dik), intent(out) :: status integer :: n integer, dimension(2) :: s s = shape(content) call this%pick_begin (name, status=status) if (status == serialize_ok) then do n = 1, s(2) call this%pop (content(:,n)) end do call this%pick_end (name,status) end if end subroutine marker_pick_default_matrix @ %def marker_pick_default_matrix @ <>= procedure :: pick_string => marker_pick_string <>= subroutine marker_pick_string (this, name, content, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name character(:), allocatable, intent(out) :: content integer(dik), intent(out) :: status call this%pick_begin (name, status=status) if (status == serialize_ok) then call this%pop (content) call this%pick_end (name, status) end if end subroutine marker_pick_string @ %def marker_pick_string @ <>= procedure :: verify_nothing => marker_verify_nothing <>= subroutine marker_verify_nothing (this, name, status) class(marker_t), intent(inout) :: this character(*), intent(in) :: name integer(dik) ,intent(out) :: status integer(dik), dimension(2) :: p1, p2 call this%find ("<", skip=4, proceed=.false., pos=p1) call this%find (">", 1, .false., p2) if (name//"/" == this%substring(p1, p2)) then status = serialize_nothing call this%set_position (p2) call this%proceed (i_one*3, .true.) else if (name == this%substring(p1, p2)) then status = serialize_ok else status = serialize_wrong_tag end if end if end subroutine marker_verify_nothing @ %def marker_verify_nothin @ <>= procedure :: indent => marker_indent <>= subroutine marker_indent (this, step) class(marker_t), intent(inout) :: this integer(dik), optional :: step if (this%do_break) call this%push (new_line(" ")) if (this%do_indent) then if (present(step)) this%indentation = this%indentation + step call this%push (repeat(" ", this%indentation)) end if this%active_pages(1) = this%actual_page() end subroutine marker_indent @ %def marker_indent @ <>= procedure :: push_heap => marker_push_heap <>= subroutine marker_push_heap (this, ser, id) class(marker_t), intent(inout) :: this class(ser_class_t), target, intent(in) :: ser integer(dik), intent(in) :: id class(serializable_ref_type), pointer :: new_ref allocate (new_ref) new_ref%next => this%heap new_ref%ref => ser new_ref%id = id this%heap => new_ref end subroutine marker_push_heap @ %def marker_push_heap @ <>= procedure :: pop_heap => marker_pop_heap <>= subroutine marker_pop_heap (this, ser) class(marker_t), intent(inout) :: this class(ser_class_t), pointer, intent(out) :: ser class(serializable_ref_type), pointer :: old_ref if (associated (this%heap)) then old_ref => this%heap ser => old_ref%ref this%heap => this%heap%next deallocate (old_ref) else call msg_error ("marker_pop_heap: heap_stack is not associated.") end if end subroutine marker_pop_heap @ %def marker_pop_heap @ <>= procedure :: push_reference => marker_push_reference <>= subroutine marker_push_reference (this, ser, id) class(marker_t), intent(inout) :: this class(ser_class_t), target, intent(in) :: ser integer(kind=dik), intent(in), optional :: id class(serializable_ref_type), pointer :: new_ref allocate (new_ref) new_ref%next => this%references new_ref%ref => ser if (present(id)) then new_ref%id = id else new_ref%id = -1 end if this%references => new_ref end subroutine marker_push_reference @ %def marker_push_reference @ <>= procedure :: pop_reference => marker_pop_reference <>= subroutine marker_pop_reference (this, ser) class(marker_t), intent(inout) :: this class(ser_class_t), pointer, intent(out) :: ser class(serializable_ref_type), pointer :: old_ref if (associated (this%references)) then old_ref => this%references ser => old_ref%ref this%references => this%references%next deallocate (old_ref) else call msg_error & ("marker_pop_reference: reference_stack is not associated.") end if end subroutine marker_pop_reference @ %def marker_pop_reference @ <>= procedure :: reset_references => marker_reset_references <>= subroutine marker_reset_references (this) class(marker_t), intent(inout) :: this if (associated (this%references)) then call this%references%finalize () deallocate (this%references) end if end subroutine marker_reset_references @ %def marker_reset_references @ <>= procedure :: search_reference => marker_search_reference <>= subroutine marker_search_reference (this, type, ser) class(marker_t), intent(in) :: this integer(dik), dimension(2,2), intent(in) :: type class(ser_class_t), pointer, intent(out) :: ser !!! !!! !!! NAG bug workaround class(ser_class_t), pointer :: tmp_ser class(serializable_ref_type), pointer :: ref ref => this%references nullify (ser) do while (associated (ref)) tmp_ser => ref%ref if (tmp_ser%verify_type (this%substring(type))) then ser => tmp_ser exit end if ref => ref%next end do end subroutine marker_search_reference @ %ref marker_search_reference @ <>= procedure :: reset_heap => marker_reset_heap <>= subroutine marker_reset_heap (this) class(marker_t), intent(inout) :: this if (associated (this%heap)) then call this%heap%finalize () deallocate (this%heap) end if end subroutine marker_reset_heap @ %def marker_reset_heap @ <>= procedure :: finalize => marker_finalize <>= subroutine marker_finalize (this) class(marker_t), intent(inout) :: this call this%reset_heap () call this%reset_references () end subroutine marker_finalize @ %def marker_finalize @ <>= generic :: search_heap => search_heap_by_id, search_heap_by_ref procedure :: search_heap_by_id => marker_search_heap_by_id procedure :: search_heap_by_ref => marker_search_heap_by_ref <>= subroutine marker_search_heap_by_ref (this, ref, id) class(marker_t), intent(in) :: this class(ser_class_t), pointer, intent(in) :: ref integer(dik), intent(out) :: id class(serializable_ref_type), pointer :: ref_p ref_p => this%heap id = 0 do while (associated (ref_p)) if (associated (ref, ref_p%ref)) then id = ref_p%id exit end if ref_p => ref_p%next end do end subroutine marker_search_heap_by_ref @ %def marker_search_heap_by_ref @ <>= subroutine marker_search_heap_by_id (this, id, ser) class(marker_t), intent(in) :: this integer(dik), intent(in) :: id class(ser_class_t), pointer, intent(out) :: ser class(serializable_ref_type), pointer :: ref ref => this%heap do while (associated (ref)) if (id == ref%id) then ser => ref%ref exit end if ref => ref%next end do end subroutine marker_search_heap_by_id @ %def marker_search_heap_by_id @ <>= elemental function measurable_less_measurable (mea1, mea2) class(measure_class_t), intent(in) :: mea1, mea2 logical :: measurable_less_measurable measurable_less_measurable = mea1%measure() < mea2%measure() end function measurable_less_measurable @ %def measurable_less_measurable @ <>= elemental function measurable_less_default (mea1, def) class(measure_class_t), intent(in) :: mea1 real(default), intent(in) :: def logical :: measurable_less_default measurable_less_default = mea1%measure() < def end function measurable_less_default @ %def measurable_less_default @ <>= elemental function measurable_less_or_equal_measurable (mea1, mea2) class(measure_class_t), intent(in) :: mea1, mea2 logical :: measurable_less_or_equal_measurable measurable_less_or_equal_measurable = mea1%measure() <= mea2%measure() end function measurable_less_or_equal_measurable @ %def measurable_less_or_equal_measurable @ <>= elemental function measurable_less_or_equal_default (mea1, def) class(measure_class_t), intent(in) :: mea1 real(default), intent(in) :: def logical :: measurable_less_or_equal_default measurable_less_or_equal_default = mea1%measure() <= def end function measurable_less_or_equal_default @ %def measurable_less_or_equal_default @ <>= elemental function measurable_equal_measurable (mea1, mea2) class(measure_class_t), intent(in) :: mea1, mea2 logical :: measurable_equal_measurable measurable_equal_measurable = mea1%measure() == mea2%measure() end function measurable_equal_measurable @ %def measurable_equal_measurable @ <>= elemental function measurable_equal_default (mea1, def) class(measure_class_t), intent(in) :: mea1 real(default), intent(in) :: def logical :: measurable_equal_default measurable_equal_default = mea1%measure() == def end function measurable_equal_default @ %def measurable_equal_default @ <>= elemental function measurable_equal_or_greater_measurable (mea1, mea2) class(measure_class_t), intent(in) :: mea1, mea2 logical :: measurable_equal_or_greater_measurable measurable_equal_or_greater_measurable = mea1%measure() >= mea2%measure() end function measurable_equal_or_greater_measurable @ %def measurable_equal_or_greater_measurable @ <>= elemental function measurable_equal_or_greater_default (mea1, def) class(measure_class_t), intent(in) :: mea1 real(default), intent(in) :: def logical :: measurable_equal_or_greater_default measurable_equal_or_greater_default = mea1%measure() >= def end function measurable_equal_or_greater_default @ %def measurable_equal_or_greater_default @ <>= elemental function measurable_greater_measurable (mea1, mea2) class(measure_class_t), intent(in) :: mea1,mea2 logical :: measurable_greater_measurable measurable_greater_measurable = mea1%measure() > mea2%measure() end function measurable_greater_measurable @ %def measurable_greater_measurable @ <>= elemental function measurable_greater_default (mea1, def) class(measure_class_t), intent(in) :: mea1 real(default), intent(in) :: def logical :: measurable_greater_default measurable_greater_default = mea1%measure() > def end function measurable_greater_default @ %def measurable_greater_default @ <>= pure function page_ring_position (n) integer(dik), intent(in) :: n integer(dik), dimension(2) :: page_ring_position page_ring_position(2) = mod(n, serialize_page_size) page_ring_position(1) = (n-page_ring_position(2)) / serialize_page_size end function page_ring_position @ %def page_ring_position @ <>= pure integer(dik) function page_ring_ordinal (pos) integer(dik), dimension(2), intent(in) :: pos page_ring_ordinal = pos(1) * serialize_page_size + pos(2) end function page_ring_ordinal @ %def page_ring_ordinal @ <>= pure logical function page_ring_position_is_before_int_pos (m, n) integer(dik), intent(in) :: m integer(dik), dimension(2), intent(in) :: n if (m < page_ring_ordinal(n)) then page_ring_position_is_before_int_pos = .true. else page_ring_position_is_before_int_pos = .false. end if end function page_ring_position_is_before_int_pos @ %def page_ring_position_is_before_int_pos @ <>= pure logical function page_ring_position_is_before_pos_int (m, n) integer(dik), dimension(2), intent(in) :: m integer(dik), intent(in) :: n if (page_ring_ordinal(m) < n) then page_ring_position_is_before_pos_int = .true. else page_ring_position_is_before_pos_int = .false. end if end function page_ring_position_is_before_pos_int @ %def page_ring_position_is_before_pos_int @ <>= pure logical function page_ring_position_is_before_pos_pos (m, n) integer(dik), dimension(2), intent(in) :: m,n if (m(1) < n(1)) then page_ring_position_is_before_pos_pos = .true. else if (m(1) > n(1)) then page_ring_position_is_before_pos_pos = .false. else if (m(2) < n(2)) then page_ring_position_is_before_pos_pos = .true. else page_ring_position_is_before_pos_pos = .false. end if end if end if end function page_ring_position_is_before_pos_pos @ %def page_ring_position_is_before_pos_pos @ <>= subroutine ring_position_increase (pos, n) integer(dik), dimension(2), intent(inout) :: pos integer(dik), intent(in) :: n pos = page_ring_position (page_ring_ordinal(pos) + n) end subroutine ring_position_increase @ %def ring_position_increase @ <>= pure integer(dik) function ring_position_metric1 (p) integer(dik), dimension(2,2), intent(in) :: p ring_position_metric1 = (p(1,2) - p(1,1)) * serialize_page_size + & p(2,2) - p(2,1) + 1 end function ring_position_metric1 pure integer(dik) function ring_position_metric2 (p1, p2) integer(dik), dimension(2), intent(in) :: p1, p2 ring_position_metric2 = (p2(1) - p1(1)) * & serialize_page_size + p2(2) - p1(2) + 1 end function ring_position_metric2 @ %def ring_position_metric1 ring_position_metric2 @ <>= public :: generate_unit <>= subroutine generate_unit (unit, min, max) integer, intent(out) :: unit integer, intent(in), optional :: min,max integer :: min_u, max_u logical :: is_open ! print *,"generate_unit" unit = -1 if (present (min)) then min_u = min else min_u = 10 end if if (present (max)) then max_u = max else max_u = huge (max_u) end if do unit = min_u, max_u !print *,"testing ",unit inquire (unit, opened = is_open) if (.not. is_open) then exit end if end do end subroutine generate_unit @ %def generate_unit @ <>= public :: ilog2 <>= subroutine ilog2 (int, exp, rem) integer,intent(in) :: int integer,intent(out) :: exp, rem integer :: count count = 2 exp = 1 do while (count < int) exp = exp + 1 count = ishft(count, 1) end do if (count > int) then rem = (int - ishft(count, -1)) else rem = 0 end if end subroutine ilog2 @ %def ilog2 @ <>= public :: integer_with_leading_zeros <>= subroutine integer_with_leading_zeros (number, length, string) integer, intent(in) :: number, length character(len=*), intent(out) :: string integer :: zeros character::sign if (number == 0) then string = repeat("0", length) else if (number > 0) then zeros = length -floor(log10 (real(number))) - 1 if (zeros < 0) then string = repeat("*", length) else write (string, fmt="(A,I0)") repeat("0", zeros), number end if else zeros = length - floor (log10 (real (-number))) - 2 if (zeros < 0) then string = repeat("*", length) else write (string, fmt="(A,A,I0)") "-", repeat("0", zeros), & abs(number) end if end if end if end subroutine integer_with_leading_zeros @ %def integer_with_leading_zeros @ <>= pure logical function character_is_in (c, array) character, intent(in) :: c character, dimension(:), intent(in) :: array integer(dik) :: n character_is_in = .false. do n=1,size(array) if (c == array(n)) then character_is_in = .true. exit end if end do end function character_is_in @ %def character_is_in @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Transverse momenta} This file contains the module [[muli_momentum]]. Its purpose is to store the actual value of the evolution parameter $p_t^2$ in a convenient way. We use the normalized value $p_t^2 / p_{t,\text{max}}^2$ for generating the next value of the scale, also need the square root of both $p_t^2$ and $p_t^2 / p_{t,\text{max}}^2$ for other purposes. That's why I store all four combinations together with $p_{t, \text{max}}$ in an array. <<[[muli_momentum.f90]]>>= <> module muli_momentum <> use constants use muli_base <> <> <> <> contains <> end module muli_momentum @ %def muli_momentum @ <>= public :: transverse_mom_t <>= type, extends (ser_class_t) :: transverse_mom_t private real(default), dimension(0:4) :: momentum = [0, 0, 0, 0, 0] contains <> end type transverse_mom_t @ %def transverse_mom_t @ <>= procedure :: mom_write_to_marker => transverse_mom_write_to_marker procedure :: write_to_marker => transverse_mom_write_to_marker <>= subroutine transverse_mom_write_to_marker (this, marker, status) class(transverse_mom_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("transverse_mom_t") call marker%mark ("gev_momenta", this%momentum(0:1)) call marker%mark_end ("transverse_mom_t") end subroutine transverse_mom_write_to_marker @ %def transverse_mom_write_to_marker @ <>= procedure :: mom_read_from_marker => transverse_mom_read_from_marker procedure :: read_from_marker => transverse_mom_read_from_marker <>= subroutine transverse_mom_read_from_marker (this, marker, status) class(transverse_mom_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("transverse_mom_t", status=status) call marker%pick ("gev_momenta", this%momentum(0:1), status) this%momentum(2:4) = [ this%momentum(1)**2, & this%momentum(1) / this%momentum(0), & (this%momentum(1)/this%momentum(0))**2 ] call marker%pick_end ("transverse_mom_t", status=status) end subroutine transverse_mom_read_from_marker @ %def transverse_mom_read_from_marker @ <>= procedure :: mom_print_to_unit => transverse_mom_print_to_unit procedure :: print_to_unit => transverse_mom_print_to_unit <>= subroutine transverse_mom_print_to_unit & (this, unit, parents, components, peers) class(transverse_mom_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "Components of transverse_mom_t:" write (unit, "(3x,A)") "Actual energy scale:" write (unit, "(A,E20.10)") "Max scale (MeV) :", this%momentum(0) write (unit, "(A,E20.10)") "Scale (MeV) :", this%momentum(1) write (unit, "(A,E20.10)") "Scale^2 (MeV^2) :", this%momentum(2) write (unit, "(A,E20.10)") "Scale normalized :", this%momentum(3) write (unit, "(A,E20.10)") "Scale^2 normalized:", this%momentum(4) end subroutine transverse_mom_print_to_unit @ %def transverse_mom_print_to_unit @ <>= procedure, nopass :: get_type => transverse_mom_get_type <>= pure subroutine transverse_mom_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="transverse_mom_t") end subroutine transverse_mom_get_type @ %def transverse_mom_get_type @ <>= procedure :: get_gev_initial_cme => transverse_mom_get_gev_initial_cme <>= elemental function transverse_mom_get_gev_initial_cme (this) result(scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(0) * 2D0 end function transverse_mom_get_gev_initial_cme @ %def transverse_mom_get_gev_initial_cme @ <>= procedure :: get_gev_max_scale => transverse_mom_get_gev_max_scale <>= elemental function transverse_mom_get_gev_max_scale (this) result (scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(0) end function transverse_mom_get_gev_max_scale @ %def transverse_mom_get_gev_max_scale @ <>= procedure :: get_gev2_max_scale => transverse_mom_get_gev2_max_scale <>= elemental function transverse_mom_get_gev2_max_scale (this) result (scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(0)**2 end function transverse_mom_get_gev2_max_scale @ %def transverse_mom_get_gev2_max_scale @ <>= procedure :: get_gev_scale => transverse_mom_get_gev_scale <>= elemental function transverse_mom_get_gev_scale(this) result(scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(1) end function transverse_mom_get_gev_scale @ %def transverse_mom_get_gev_scale @ <>= procedure :: get_gev2_scale => transverse_mom_get_gev2_scale <>= elemental function transverse_mom_get_gev2_scale (this) result (scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(2) end function transverse_mom_get_gev2_scale @ %def transverse_mom_get_gev2_scale @ <>= procedure :: get_unit_scale => transverse_mom_get_unit_scale <>= pure function transverse_mom_get_unit_scale (this) result (scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(3) end function transverse_mom_get_unit_scale @ %def transverse_mom_get_unit_scale @ <>= procedure :: get_unit2_scale => transverse_mom_get_unit2_scale <>= pure function transverse_mom_get_unit2_scale (this) result (scale) class(transverse_mom_t), intent(in) :: this real(default) :: scale scale = this%momentum(4) end function transverse_mom_get_unit2_scale @ %def transverse_mom_get_unit2_scale @ <>= procedure :: set_gev_initial_cme => transverse_mom_set_gev_initial_cme <>= subroutine transverse_mom_set_gev_initial_cme (this, new_gev_initial_cme) class(transverse_mom_t), intent(inout) :: this real(default), intent(in) :: new_gev_initial_cme this%momentum(0) = new_gev_initial_cme / 2D0 this%momentum(3) = this%momentum(1) / this%momentum(0) this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_gev_initial_cme @ %def transverse_mom_set_gev_initial_cme @ <>= procedure :: set_gev_max_scale => transverse_mom_set_gev_max_scale <>= subroutine transverse_mom_set_gev_max_scale (this, new_gev_max_scale) class(transverse_mom_t), intent(inout) :: this real(default), intent(in) :: new_gev_max_scale this%momentum(0) = new_gev_max_scale this%momentum(3) = this%momentum(1) / this%momentum(0) this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_gev_max_scale @ %def transverse_mom_set_gev_max_scale @ <>= procedure :: set_gev2_max_scale => transverse_mom_set_gev2_max_scale <>= subroutine transverse_mom_set_gev2_max_scale (this, new_gev2_max_scale) class(transverse_mom_t), intent(inout) :: this real(default), intent(in) :: new_gev2_max_scale this%momentum(0) = sqrt (new_gev2_max_scale) this%momentum(3) = this%momentum(1) / this%momentum(0) this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_gev2_max_scale @ %def transverse_mom_set_gev2_max_scale @ <>= procedure :: set_gev_scale => transverse_mom_set_gev_scale <>= subroutine transverse_mom_set_gev_scale (this, new_gev_scale) class(transverse_mom_t), intent(inout) :: this real(default), intent(in) :: new_gev_scale this%momentum(1) = new_gev_scale this%momentum(2) = new_gev_scale**2 this%momentum(3) = new_gev_scale / this%momentum(0) this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_gev_scale @ %def transverse_mom_set_gev_scale @ <>= procedure :: set_gev2_scale => transverse_mom_set_gev2_scale <>= subroutine transverse_mom_set_gev2_scale (this, new_gev2_scale) class(transverse_mom_t), intent(inout) :: this real(default), intent(in) :: new_gev2_scale this%momentum(1) = sqrt (new_gev2_scale) this%momentum(2) = new_gev2_scale this%momentum(3) = this%momentum(1) / this%momentum(0) this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_gev2_scale @ %def transverse_mom_set_gev2_scale @ <>= procedure :: set_unit_scale => transverse_mom_set_unit_scale <>= subroutine transverse_mom_set_unit_scale (this, new_unit_scale) class(transverse_mom_t), intent(inout)::this real(default), intent(in) :: new_unit_scale this%momentum(1) = new_unit_scale * this%momentum(0) this%momentum(2) = this%momentum(1)**2 this%momentum(3) = new_unit_scale this%momentum(4) = this%momentum(3)**2 end subroutine transverse_mom_set_unit_scale @ %def transverse_mom_set_unit_scale @ <>= procedure :: set_unit2_scale => transverse_mom_set_unit2_scale <>= subroutine transverse_mom_set_unit2_scale (this, new_unit2_scale) class(transverse_mom_t), intent(inout)::this real(default), intent(in) :: new_unit2_scale this%momentum(3) = sqrt (new_unit2_scale) this%momentum(4) = new_unit2_scale this%momentum(1) = this%momentum(3) * this%momentum(0) this%momentum(2) = this%momentum(1)**2 end subroutine transverse_mom_set_unit2_scale @ %def transverse_mom_set_unit2_scale @ <>= generic :: initialize => transverse_mom_initialize procedure :: transverse_mom_initialize <>= subroutine transverse_mom_initialize (this, gev2_s) class(transverse_mom_t), intent(out) :: this real(default), intent(in) :: gev2_s real(default) :: gev_s gev_s = sqrt (gev2_s) this%momentum = [gev_s/2, gev_s/2, gev2_s/4, one, one] end subroutine transverse_mom_initialize @ %def transverse_mom_initialize @ <>= public :: qcd_2_2_class <>= type, extends (transverse_mom_t), abstract :: qcd_2_2_class contains <> end type qcd_2_2_class @ %def qcd_2_2_class @ <>= procedure(qcd_get_int), deferred :: get_process_id <>= procedure(qcd_get_int), deferred :: get_integrand_id <>= procedure(qcd_get_int), deferred :: get_diagram_kind <>= procedure(qcd_get_int_4), deferred :: get_lha_flavors <>= procedure(qcd_get_int_4), deferred :: get_pdg_flavors <>= procedure(qcd_get_int_by_int), deferred :: get_parton_id <>= procedure(qcd_get_int_2), deferred :: get_parton_kinds <>= procedure(qcd_get_int_2), deferred :: get_pdf_int_kinds <>= procedure(qcd_get_real), deferred :: get_momentum_boost <>= ! procedure(qcd_get_real_3),deferred :: get_parton_in_momenta <>= procedure(qcd_get_real_2), deferred :: get_remnant_momentum_fractions <>= procedure(qcd_get_real_2), deferred :: get_total_momentum_fractions <>= abstract interface subroutine qcd_none (this) import qcd_2_2_class class(qcd_2_2_class), target, intent(in) :: this end subroutine qcd_none end interface @ %def qcd_none @ <>= ! abstract interface ! subroutine qcd_get_beam (this, beam) ! import qcd_2_2_class ! import pp_remnant_class ! class(qcd_2_2_class),target, intent(in) :: this ! class(pp_remnant_class),pointer, intent(out) :: beam ! end subroutine qcd_get_beam ! end interface @ %def qcd_get_beam @ <>= abstract interface elemental function qcd_get_real (this) import class(qcd_2_2_class), intent(in) :: this real(default) :: qcd_get_real end function qcd_get_real end interface @ %def qcd_get_real @ <>= abstract interface pure function qcd_get_real_2 (this) import class(qcd_2_2_class), intent(in) :: this real(default), dimension(2) :: qcd_get_real_2 end function qcd_get_real_2 end interface @ %def qcd_get_real_2 @ <>= abstract interface pure function qcd_get_real_3 (this) import class(qcd_2_2_class), intent(in) :: this real(default), dimension(3) :: qcd_get_real_3 end function qcd_get_real_3 end interface @ %def qcd_get_real_3 @ <>= abstract interface elemental function qcd_get_int (this) import class(qcd_2_2_class), intent(in) :: this integer :: qcd_get_int end function qcd_get_int end interface @ %def qcd_get_int @ <>= abstract interface pure function qcd_get_int_by_int (this, n) import class(qcd_2_2_class), intent(in) :: this integer, intent(in) :: n integer :: qcd_get_int_by_int end function qcd_get_int_by_int end interface @ %def qcd_get_int_by_int @ <>= abstract interface pure function qcd_get_int_2 (this) import class(qcd_2_2_class), intent(in) :: this integer, dimension(2) :: qcd_get_int_2 end function qcd_get_int_2 end interface @ %def qcd_get_int_2 @ <>= abstract interface pure function qcd_get_int_4 (this) import class(qcd_2_2_class), intent(in) :: this integer, dimension(4) :: qcd_get_int_4 end function qcd_get_int_4 end interface @ %def qcd_get_int_t @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Multi parton interactions} This file contains the module [[muli_interactions]]. The allowed interactions and their cross sections are defined here. Additionaly, some coordinate transformations which annihilate divergencies of the cross sections are defined. Since the phase space border is hyperbolic, this transformations are also hyperbolic. That's why all interactions are named [[x_cart]] for cartesian or [[x_hyp]] for hyperbolic to avoid confusion. <<[[muli_interactions.f90]]>>= <> module muli_interactions <> use constants use muli_momentum <> <> <> <> contains <> end module muli_interactions @ %def muli_interactions @ <>= character(len=2), dimension(-6:6), parameter :: integer_parton_names = & ["-6", "-5", "-4", "-3", "-2", "-1", "00", & "+1", "+2", "+3", "+4", "+5", "+6" ] character, dimension(-6:6),parameter :: traditional_parton_names = & ["T", "B", "C", "S", "U", "D", "g", "d", "u", "s", "c", "b", "t"] @ %def integer_parton_names traditional_parton_names @ These are the phase space coefficients of the polynomial mappings, the evolution variable is [[pt2s/(x1*x2)]]. <>= real(default), dimension(1:4,1:5), parameter :: & phase_space_coefficients_in = reshape (source = & [ 6144, -4608, +384, 0, & 6144, -5120, +384, 0, & 6144, -2048, +128, -576, & 13824, -9600, +1056, 0, & 31104,-19872, +2160, +486 ], shape=[4,5]) @ %def phase_space_coefficients_in @ <>= integer, parameter :: hadron_A_kind = 2212 integer, parameter :: hadron_B_kind = -2212 integer, dimension(4), parameter, public :: & parton_kind_of_int_kind = [1, 1, 2, 2] real(default), parameter :: b_sigma_tot_all = 100 !mb PDG real(default), parameter :: & b_sigma_tot_nd = 0.5*b_sigma_tot_all !!! PRD 49 n5 1994 real(default), parameter, public :: & gev_cme_tot = 14000 ! total center of mass energie real(default), parameter :: gev2_cme_tot = gev_cme_tot**2 !!! s real(default), parameter :: gev_pt_max = gev_cme_tot/2D0 real(default), parameter :: gev2_pt_max = gev2_cme_tot/4D0 !model parameters real(default), parameter :: gev_pt_min = 8E-1_default real(default), parameter :: gev2_pt_min = gev_pt_min**2 real(default), parameter :: pts_min = gev_pt_min / gev_pt_max real(default), parameter :: pts2_min = gev2_pt_min / gev2_pt_max real(default), parameter :: gev_p_t_0 = 2.0 real(default), parameter :: gev2_p_t_0 = gev_p_t_0**2 real(default), parameter :: norm_p_t_0 = gev_p_t_0 / gev_pt_max real(default), parameter :: norm2_p_t_0 = gev2_p_t_0 / gev2_pt_max !mathematical constants real(default), parameter, public :: euler = exp(one) !physical constants real(default), parameter :: gev2_mbarn = 0.389379304_default real(default), parameter :: const_pref = pi * gev2_mbarn / & (gev2_cme_tot * b_sigma_tot_nd) @ @ <>= integer, parameter, public :: LHA_FLAVOR_AT = -6 integer, parameter, public :: LHA_FLAVOR_AB = -5 integer, parameter, public :: LHA_FLAVOR_AC = -4 integer, parameter, public :: LHA_FLAVOR_AS = -3 integer, parameter, public :: LHA_FLAVOR_AU = -2 integer, parameter, public :: LHA_FLAVOR_AD = -1 integer, parameter, public :: LHA_FLAVOR_G = 0 integer, parameter, public :: LHA_FLAVOR_D = 1 integer, parameter, public :: LHA_FLAVOR_U = 2 integer, parameter, public :: LHA_FLAVOR_S = 3 integer, parameter, public :: LHA_FLAVOR_C = 4 integer, parameter, public :: LHA_FLAVOR_B = 5 integer, parameter, public :: LHA_FLAVOR_T = 6 @ %def LHA_FLAVOR_AT, LHA_FLAVOR_T, LHA_FLAVOR_AB, LHA_FLAVOR_B @ %def LHA_FLAVOR_AC, LHA_FLAVOR_C, LHA_FLAVOR_AS, LHA_FLAVOR_S @ %def LHA_FLAVOR_AU, LHA_FLAVOR_U, LHA_FLAVOR_AD, LHA_FLAVOR_D @ %def LHA_FLAVOR_G @ <>= integer, parameter, public :: PDG_FLAVOR_AT = -6 integer, parameter, public :: PDG_FLAVOR_AB = -5 integer, parameter, public :: PDG_FLAVOR_AC = -4 integer, parameter, public :: PDG_FLAVOR_AS = -3 integer, parameter, public :: PDG_FLAVOR_AU = -2 integer, parameter, public :: PDG_FLAVOR_AD = -1 integer, parameter, public :: PDG_FLAVOR_G = 21 integer, parameter, public :: PDG_FLAVOR_D = 1 integer, parameter, public :: PDG_FLAVOR_U = 2 integer, parameter, public :: PDG_FLAVOR_S = 3 integer, parameter, public :: PDG_FLAVOR_C = 4 integer, parameter, public :: PDG_FLAVOR_B = 5 integer, parameter, public :: PDG_FLAVOR_T = 6 @ %def PDG_FLAVOR_AT, PDG_FLAVOR_T, PDG_FLAVOR_AB, PDG_FLAVOR_B @ %def PDG_FLAVOR_AC, PDG_FLAVOR_C, PDG_FLAVOR_AS, PDG_FLAVOR_S @ %def PDG_FLAVOR_AU, PDG_FLAVOR_U, PDG_FLAVOR_AD, PDG_FLAVOR_D @ %def PDG_FLAVOR_G @ <>= integer, parameter, public :: PARTON_SEA = 1 integer, parameter, public :: PARTON_VALENCE = 2 integer, parameter, public :: PARTON_SEA_AND_VALENCE = 3 integer, parameter, public :: PARTON_TWIN = 4 integer, parameter, public :: PARTON_SEA_AND_TWIN = 5 integer, parameter, public :: PARTON_VALENCE_AND_TWIN = 6 integer, parameter, public :: PARTON_ALL = 7 @ %def PARTON_SEA PARTON_VALENCE PARTON_SEA_AND_VALENCE @ %def PARTON_TWIN PARTON_SEA_AND_TWIN PARTON_VALENCE_AND_TWIN PARTON_ALL @ <>= integer, parameter, public :: PDF_UNDEFINED = 0 integer, parameter, public :: PDF_GLUON = 1 integer, parameter, public :: PDF_SEA = 2 integer, parameter, public :: PDF_VALENCE_DOWN = 3 integer, parameter, public :: PDF_VALENCE_UP = 4 integer, parameter, public :: PDF_TWIN = 5 @ %def PDF_UNDEFINED, PDF_GLUON, PDF_SEA @ %def PDF_VALENCE_DOWN, PDF_VALENCE_UP, PDF_TWIN @ Evolution variable is [[pt2s/(x1*x2)]]. <>= real(default), dimension(1:4,1:8),parameter :: & phase_space_coefficients_inout = reshape(source=[ & 3072, -2304, +192, 0, & 6144, -5120, +384, 0, & 0, 0, 192, -96, & 3072, -2048, +192, -96, & 0, 2048, -2176, +576, & 0, 288, -306, +81, & 6912, -4800, +528, 0, & 31104,-23328, +5832, -486], & shape=[4,8]) @ %def phase_space_coefficients_inout @ <>= integer, dimension(1:4,0:8), parameter :: inout_signatures = & reshape (source = [ & 1, 1, 1, 1, & !1a -1, 1,-1, 1, & !1b 1, 1, 1, 1, & !2 1,-1, 1,-1, & !3 1,-1, 1,-1, & !4 1,-1, 0, 0, & !5 0, 0, 1,-1, & !6 1, 0, 1, 0, & !7 0, 0, 0, 0 ], & shape = [4,9]) @ %def inout_signatures @ <>= integer, dimension(6,-234:234), save, public :: valid_processes data valid_processes (:,-234) / -6, -6, -6, -6, 2, 2 / data valid_processes (:,-233) / -6, -5, -6, -5, 1, 1 / data valid_processes (:,-232) / -6, -5, -5, -6, 1, 1 / data valid_processes (:,-231) / -6, -4, -6, -4, 1, 1 / data valid_processes (:,-230) / -6, -4, -4, -6, 1, 1 / data valid_processes (:,-229) / -6, -3, -6, -3, 1, 1 / data valid_processes (:,-228) / -6, -3, -3, -6, 1, 1 / data valid_processes (:,-227) / -6, -2, -6, -2, 1, 1 / data valid_processes (:,-226) / -6, -2, -2, -6, 1, 1 / data valid_processes (:,-225) / -6, -1, -6, -1, 1, 1 / data valid_processes (:,-224) / -6, -1, -1, -6, 1, 1 / data valid_processes (:,-223) / -6, 0, -6, 0, 4, 7 / data valid_processes (:,-222) / -6, 0, 0, -6, 4, 7 / data valid_processes (:,-221) / -6, 1, -6, 1, 1, 1 / data valid_processes (:,-220) / -6, 1, 1, -6, 1, 1 / data valid_processes (:,-219) / -6, 2, -6, 2, 1, 1 / data valid_processes (:,-218) / -6, 2, 2, -6, 1, 1 / data valid_processes (:,-217) / -6, 3, -6, 3, 1, 1 / data valid_processes (:,-216) / -6, 3, 3, -6, 1, 1 / data valid_processes (:,-215) / -6, 4, -6, 4, 1, 1 / data valid_processes (:,-214) / -6, 4, 4, -6, 1, 1 / data valid_processes (:,-213) / -6, 5, -6, 5, 1, 1 / data valid_processes (:,-212) / -6, 5, 5, -6, 1, 1 / data valid_processes (:,-211) / -6, 6, -6, 6, 3, 4 / data valid_processes (:,-210) / -6, 6, -5, 5, 3, 3 / data valid_processes (:,-209) / -6, 6, -4, 4, 3, 3 / data valid_processes (:,-208) / -6, 6, -3, 3, 3, 3 / data valid_processes (:,-207) / -6, 6, -2, 2, 3, 3 / data valid_processes (:,-206) / -6, 6, -1, 1, 3, 3 / data valid_processes (:,-205) / -6, 6, 0, 0, 3, 5 / data valid_processes (:,-204) / -6, 6, 1, -1, 3, 3 / data valid_processes (:,-203) / -6, 6, 2, -2, 3, 3 / data valid_processes (:,-202) / -6, 6, 3, -3, 3, 3 / data valid_processes (:,-201) / -6, 6, 4, -4, 3, 3 / data valid_processes (:,-200) / -6, 6, 5, -5, 3, 3 / data valid_processes (:,-199) / -6, 6, 6, -6, 3, 4 / data valid_processes (:,-198) / -5, -6, -6, -5, 1, 1 / data valid_processes (:,-197) / -5, -6, -5, -6, 1, 1 / data valid_processes (:,-196) / -5, -5, -5, -5, 2, 2 / data valid_processes (:,-195) / -5, -4, -5, -4, 1, 1 / data valid_processes (:,-194) / -5, -4, -4, -5, 1, 1 / data valid_processes (:,-193) / -5, -3, -5, -3, 1, 1 / data valid_processes (:,-192) / -5, -3, -3, -5, 1, 1 / data valid_processes (:,-191) / -5, -2, -5, -2, 1, 1 / data valid_processes (:,-190) / -5, -2, -2, -5, 1, 1 / data valid_processes (:,-189) / -5, -1, -5, -1, 1, 1 / data valid_processes (:,-188) / -5, -1, -1, -5, 1, 1 / data valid_processes (:,-187) / -5, 0, -5, 0, 4, 7 / data valid_processes (:,-186) / -5, 0, 0, -5, 4, 7 / data valid_processes (:,-185) / -5, 1, -5, 1, 1, 1 / data valid_processes (:,-184) / -5, 1, 1, -5, 1, 1 / data valid_processes (:,-183) / -5, 2, -5, 2, 1, 1 / data valid_processes (:,-182) / -5, 2, 2, -5, 1, 1 / data valid_processes (:,-181) / -5, 3, -5, 3, 1, 1 / data valid_processes (:,-180) / -5, 3, 3, -5, 1, 1 / data valid_processes (:,-179) / -5, 4, -5, 4, 1, 1 / data valid_processes (:,-178) / -5, 4, 4, -5, 1, 1 / data valid_processes (:,-177) / -5, 5, -6, 6, 3, 3 / data valid_processes (:,-176) / -5, 5, -5, 5, 3, 4 / data valid_processes (:,-175) / -5, 5, -4, 4, 3, 3 / data valid_processes (:,-174) / -5, 5, -3, 3, 3, 3 / data valid_processes (:,-173) / -5, 5, -2, 2, 3, 3 / data valid_processes (:,-172) / -5, 5, -1, 1, 3, 3 / data valid_processes (:,-171) / -5, 5, 0, 0, 3, 5 / data valid_processes (:,-170) / -5, 5, 1, -1, 3, 3 / data valid_processes (:,-169) / -5, 5, 2, -2, 3, 3 / data valid_processes (:,-168) / -5, 5, 3, -3, 3, 3 / data valid_processes (:,-167) / -5, 5, 4, -4, 3, 3 / data valid_processes (:,-166) / -5, 5, 5, -5, 3, 4 / data valid_processes (:,-165) / -5, 5, 6, -6, 3, 3 / data valid_processes (:,-164) / -5, 6, -5, 6, 1, 1 / data valid_processes (:,-163) / -5, 6, 6, -5, 1, 1 / data valid_processes (:,-162) / -4, -6, -6, -4, 1, 1 / data valid_processes (:,-161) / -4, -6, -4, -6, 1, 1 / data valid_processes (:,-160) / -4, -5, -5, -4, 1, 1 / data valid_processes (:,-159) / -4, -5, -4, -5, 1, 1 / data valid_processes (:,-158) / -4, -4, -4, -4, 2, 2 / data valid_processes (:,-157) / -4, -3, -4, -3, 1, 1 / data valid_processes (:,-156) / -4, -3, -3, -4, 1, 1 / data valid_processes (:,-155) / -4, -2, -4, -2, 1, 1 / data valid_processes (:,-154) / -4, -2, -2, -4, 1, 1 / data valid_processes (:,-153) / -4, -1, -4, -1, 1, 1 / data valid_processes (:,-152) / -4, -1, -1, -4, 1, 1 / data valid_processes (:,-151) / -4, 0, -4, 0, 4, 7 / data valid_processes (:,-150) / -4, 0, 0, -4, 4, 7 / data valid_processes (:,-149) / -4, 1, -4, 1, 1, 1 / data valid_processes (:,-148) / -4, 1, 1, -4, 1, 1 / data valid_processes (:,-147) / -4, 2, -4, 2, 1, 1 / data valid_processes (:,-146) / -4, 2, 2, -4, 1, 1 / data valid_processes (:,-145) / -4, 3, -4, 3, 1, 1 / data valid_processes (:,-144) / -4, 3, 3, -4, 1, 1 / data valid_processes (:,-143) / -4, 4, -6, 6, 3, 3 / data valid_processes (:,-142) / -4, 4, -5, 5, 3, 3 / data valid_processes (:,-141) / -4, 4, -4, 4, 3, 4 / data valid_processes (:,-140) / -4, 4, -3, 3, 3, 3 / data valid_processes (:,-139) / -4, 4, -2, 2, 3, 3 / data valid_processes (:,-138) / -4, 4, -1, 1, 3, 3 / data valid_processes (:,-137) / -4, 4, 0, 0, 3, 5 / data valid_processes (:,-136) / -4, 4, 1, -1, 3, 3 / data valid_processes (:,-135) / -4, 4, 2, -2, 3, 3 / data valid_processes (:,-134) / -4, 4, 3, -3, 3, 3 / data valid_processes (:,-133) / -4, 4, 4, -4, 3, 4 / data valid_processes (:,-132) / -4, 4, 5, -5, 3, 3 / data valid_processes (:,-131) / -4, 4, 6, -6, 3, 3 / data valid_processes (:,-130) / -4, 5, -4, 5, 1, 1 / data valid_processes (:,-129) / -4, 5, 5, -4, 1, 1 / data valid_processes (:,-128) / -4, 6, -4, 6, 1, 1 / data valid_processes (:,-127) / -4, 6, 6, -4, 1, 1 / data valid_processes (:,-126) / -3, -6, -6, -3, 1, 1 / data valid_processes (:,-125) / -3, -6, -3, -6, 1, 1 / data valid_processes (:,-124) / -3, -5, -5, -3, 1, 1 / data valid_processes (:,-123) / -3, -5, -3, -5, 1, 1 / data valid_processes (:,-122) / -3, -4, -4, -3, 1, 1 / data valid_processes (:,-121) / -3, -4, -3, -4, 1, 1 / data valid_processes (:,-120) / -3, -3, -3, -3, 2, 2 / data valid_processes (:,-119) / -3, -2, -3, -2, 1, 1 / data valid_processes (:,-118) / -3, -2, -2, -3, 1, 1 / data valid_processes (:,-117) / -3, -1, -3, -1, 1, 1 / data valid_processes (:,-116) / -3, -1, -1, -3, 1, 1 / data valid_processes (:,-115) / -3, 0, -3, 0, 4, 7 / data valid_processes (:,-114) / -3, 0, 0, -3, 4, 7 / data valid_processes (:,-113) / -3, 1, -3, 1, 1, 1 / data valid_processes (:,-112) / -3, 1, 1, -3, 1, 1 / data valid_processes (:,-111) / -3, 2, -3, 2, 1, 1 / data valid_processes (:,-110) / -3, 2, 2, -3, 1, 1 / data valid_processes (:,-109) / -3, 3, -6, 6, 3, 3 / data valid_processes (:,-108) / -3, 3, -5, 5, 3, 3 / data valid_processes (:,-107) / -3, 3, -4, 4, 3, 3 / data valid_processes (:,-106) / -3, 3, -3, 3, 3, 4 / data valid_processes (:,-105) / -3, 3, -2, 2, 3, 3 / data valid_processes (:,-104) / -3, 3, -1, 1, 3, 3 / data valid_processes (:,-103) / -3, 3, 0, 0, 3, 5 / data valid_processes (:,-102) / -3, 3, 1, -1, 3, 3 / data valid_processes (:,-101) / -3, 3, 2, -2, 3, 3 / data valid_processes (:,-100) / -3, 3, 3, -3, 3, 4 / data valid_processes (:, -99) / -3, 3, 4, -4, 3, 3 / data valid_processes (:, -98) / -3, 3, 5, -5, 3, 3 / data valid_processes (:, -97) / -3, 3, 6, -6, 3, 3 / data valid_processes (:, -96) / -3, 4, -3, 4, 1, 1 / data valid_processes (:, -95) / -3, 4, 4, -3, 1, 1 / data valid_processes (:, -94) / -3, 5, -3, 5, 1, 1 / data valid_processes (:, -93) / -3, 5, 5, -3, 1, 1 / data valid_processes (:, -92) / -3, 6, -3, 6, 1, 1 / data valid_processes (:, -91) / -3, 6, 6, -3, 1, 1 / data valid_processes (:, -90) / -2, -6, -6, -2, 1, 1 / data valid_processes (:, -89) / -2, -6, -2, -6, 1, 1 / data valid_processes (:, -88) / -2, -5, -5, -2, 1, 1 / data valid_processes (:, -87) / -2, -5, -2, -5, 1, 1 / data valid_processes (:, -86) / -2, -4, -4, -2, 1, 1 / data valid_processes (:, -85) / -2, -4, -2, -4, 1, 1 / data valid_processes (:, -84) / -2, -3, -3, -2, 1, 1 / data valid_processes (:, -83) / -2, -3, -2, -3, 1, 1 / data valid_processes (:, -82) / -2, -2, -2, -2, 2, 2 / data valid_processes (:, -81) / -2, -1, -2, -1, 1, 1 / data valid_processes (:, -80) / -2, -1, -1, -2, 1, 1 / data valid_processes (:, -79) / -2, 0, -2, 0, 4, 7 / data valid_processes (:, -78) / -2, 0, 0, -2, 4, 7 / data valid_processes (:, -77) / -2, 1, -2, 1, 1, 1 / data valid_processes (:, -76) / -2, 1, 1, -2, 1, 1 / data valid_processes (:, -75) / -2, 2, -6, 6, 3, 3 / data valid_processes (:, -74) / -2, 2, -5, 5, 3, 3 / data valid_processes (:, -73) / -2, 2, -4, 4, 3, 3 / data valid_processes (:, -72) / -2, 2, -3, 3, 3, 3 / data valid_processes (:, -71) / -2, 2, -2, 2, 3, 4 / data valid_processes (:, -70) / -2, 2, -1, 1, 3, 3 / data valid_processes (:, -69) / -2, 2, 0, 0, 3, 5 / data valid_processes (:, -68) / -2, 2, 1, -1, 3, 3 / data valid_processes (:, -67) / -2, 2, 2, -2, 3, 4 / data valid_processes (:, -66) / -2, 2, 3, -3, 3, 3 / data valid_processes (:, -65) / -2, 2, 4, -4, 3, 3 / data valid_processes (:, -64) / -2, 2, 5, -5, 3, 3 / data valid_processes (:, -63) / -2, 2, 6, -6, 3, 3 / data valid_processes (:, -62) / -2, 3, -2, 3, 1, 1 / data valid_processes (:, -61) / -2, 3, 3, -2, 1, 1 / data valid_processes (:, -60) / -2, 4, -2, 4, 1, 1 / data valid_processes (:, -59) / -2, 4, 4, -2, 1, 1 / data valid_processes (:, -58) / -2, 5, -2, 5, 1, 1 / data valid_processes (:, -57) / -2, 5, 5, -2, 1, 1 / data valid_processes (:, -56) / -2, 6, -2, 6, 1, 1 / data valid_processes (:, -55) / -2, 6, 6, -2, 1, 1 / data valid_processes (:, -54) / -1, -6, -6, -1, 1, 1 / data valid_processes (:, -53) / -1, -6, -1, -6, 1, 1 / data valid_processes (:, -52) / -1, -5, -5, -1, 1, 1 / data valid_processes (:, -51) / -1, -5, -1, -5, 1, 1 / data valid_processes (:, -50) / -1, -4, -4, -1, 1, 1 / data valid_processes (:, -49) / -1, -4, -1, -4, 1, 1 / data valid_processes (:, -48) / -1, -3, -3, -1, 1, 1 / data valid_processes (:, -47) / -1, -3, -1, -3, 1, 1 / data valid_processes (:, -46) / -1, -2, -2, -1, 1, 1 / data valid_processes (:, -45) / -1, -2, -1, -2, 1, 1 / data valid_processes (:, -44) / -1, -1, -1, -1, 2, 2 / data valid_processes (:, -43) / -1, 0, -1, 0, 4, 7 / data valid_processes (:, -42) / -1, 0, 0, -1, 4, 7 / data valid_processes (:, -41) / -1, 1, -6, 6, 3, 3 / data valid_processes (:, -40) / -1, 1, -5, 5, 3, 3 / data valid_processes (:, -39) / -1, 1, -4, 4, 3, 3 / data valid_processes (:, -38) / -1, 1, -3, 3, 3, 3 / data valid_processes (:, -37) / -1, 1, -2, 2, 3, 3 / data valid_processes (:, -36) / -1, 1, -1, 1, 3, 4 / data valid_processes (:, -35) / -1, 1, 0, 0, 3, 5 / data valid_processes (:, -34) / -1, 1, 1, -1, 3, 4 / data valid_processes (:, -33) / -1, 1, 2, -2, 3, 3 / data valid_processes (:, -32) / -1, 1, 3, -3, 3, 3 / data valid_processes (:, -31) / -1, 1, 4, -4, 3, 3 / data valid_processes (:, -30) / -1, 1, 5, -5, 3, 3 / data valid_processes (:, -29) / -1, 1, 6, -6, 3, 3 / data valid_processes (:, -28) / -1, 2, -1, 2, 1, 1 / data valid_processes (:, -27) / -1, 2, 2, -1, 1, 1 / data valid_processes (:, -26) / -1, 3, -1, 3, 1, 1 / data valid_processes (:, -25) / -1, 3, 3, -1, 1, 1 / data valid_processes (:, -24) / -1, 4, -1, 4, 1, 1 / data valid_processes (:, -23) / -1, 4, 4, -1, 1, 1 / data valid_processes (:, -22) / -1, 5, -1, 5, 1, 1 / data valid_processes (:, -21) / -1, 5, 5, -1, 1, 1 / data valid_processes (:, -20) / -1, 6, -1, 6, 1, 1 / data valid_processes (:, -19) / -1, 6, 6, -1, 1, 1 / data valid_processes (:, -18) / 0, -6, -6, 0, 4, 7 / data valid_processes (:, -17) / 0, -6, 0, -6, 4, 7 / data valid_processes (:, -16) / 0, -5, -5, 0, 4, 7 / data valid_processes (:, -15) / 0, -5, 0, -5, 4, 7 / data valid_processes (:, -14) / 0, -4, -4, 0, 4, 7 / data valid_processes (:, -13) / 0, -4, 0, -4, 4, 7 / data valid_processes (:, -12) / 0, -3, -3, 0, 4, 7 / data valid_processes (:, -11) / 0, -3, 0, -3, 4, 7 / data valid_processes (:, -10) / 0, -2, -2, 0, 4, 7 / data valid_processes (:, -9) / 0, -2, 0, -2, 4, 7 / data valid_processes (:, -8) / 0, -1, -1, 0, 4, 7 / data valid_processes (:, -7) / 0, -1, 0, -1, 4, 7 / data valid_processes (:, -6) / 0, 0, -6, 6, 5, 6 / data valid_processes (:, -5) / 0, 0, -5, 5, 5, 6 / data valid_processes (:, -4) / 0, 0, -4, 4, 5, 6 / data valid_processes (:, -3) / 0, 0, -3, 3, 5, 6 / data valid_processes (:, -2) / 0, 0, -2, 2, 5, 6 / data valid_processes (:, -1) / 0, 0, -1, 1, 5, 6 / data valid_processes (:, 0) / 0, 0, 0, 0, 5, 8 / data valid_processes (:, 1) / 0, 0, 1, -1, 5, 6 / data valid_processes (:, 2) / 0, 0, 2, -2, 5, 6 / data valid_processes (:, 3) / 0, 0, 3, -3, 5, 6 / data valid_processes (:, 4) / 0, 0, 4, -4, 5, 6 / data valid_processes (:, 5) / 0, 0, 5, -5, 5, 6 / data valid_processes (:, 6) / 0, 0, 6, -6, 5, 6 / data valid_processes (:, 7) / 0, 1, 0, 1, 4, 7 / data valid_processes (:, 8) / 0, 1, 1, 0, 4, 7 / data valid_processes (:, 9) / 0, 2, 0, 2, 4, 7 / data valid_processes (:, 10) / 0, 2, 2, 0, 4, 7 / data valid_processes (:, 11) / 0, 3, 0, 3, 4, 7 / data valid_processes (:, 12) / 0, 3, 3, 0, 4, 7 / data valid_processes (:, 13) / 0, 4, 0, 4, 4, 7 / data valid_processes (:, 14) / 0, 4, 4, 0, 4, 7 / data valid_processes (:, 15) / 0, 5, 0, 5, 4, 7 / data valid_processes (:, 16) / 0, 5, 5, 0, 4, 7 / data valid_processes (:, 17) / 0, 6, 0, 6, 4, 7 / data valid_processes (:, 18) / 0, 6, 6, 0, 4, 7 / data valid_processes (:, 19) / 1, -6, -6, 1, 1, 1 / data valid_processes (:, 20) / 1, -6, 1, -6, 1, 1 / data valid_processes (:, 21) / 1, -5, -5, 1, 1, 1 / data valid_processes (:, 22) / 1, -5, 1, -5, 1, 1 / data valid_processes (:, 23) / 1, -4, -4, 1, 1, 1 / data valid_processes (:, 24) / 1, -4, 1, -4, 1, 1 / data valid_processes (:, 25) / 1, -3, -3, 1, 1, 1 / data valid_processes (:, 26) / 1, -3, 1, -3, 1, 1 / data valid_processes (:, 27) / 1, -2, -2, 1, 1, 1 / data valid_processes (:, 28) / 1, -2, 1, -2, 1, 1 / data valid_processes (:, 29) / 1, -1, -6, 6, 3, 3 / data valid_processes (:, 30) / 1, -1, -5, 5, 3, 3 / data valid_processes (:, 31) / 1, -1, -4, 4, 3, 3 / data valid_processes (:, 32) / 1, -1, -3, 3, 3, 3 / data valid_processes (:, 33) / 1, -1, -2, 2, 3, 3 / data valid_processes (:, 34) / 1, -1, -1, 1, 3, 4 / data valid_processes (:, 35) / 1, -1, 0, 0, 3, 5 / data valid_processes (:, 36) / 1, -1, 1, -1, 3, 4 / data valid_processes (:, 37) / 1, -1, 2, -2, 3, 3 / data valid_processes (:, 38) / 1, -1, 3, -3, 3, 3 / data valid_processes (:, 39) / 1, -1, 4, -4, 3, 3 / data valid_processes (:, 40) / 1, -1, 5, -5, 3, 3 / data valid_processes (:, 41) / 1, -1, 6, -6, 3, 3 / data valid_processes (:, 42) / 1, 0, 0, 1, 4, 7 / data valid_processes (:, 43) / 1, 0, 1, 0, 4, 7 / data valid_processes (:, 44) / 1, 1, 1, 1, 2, 2 / data valid_processes (:, 45) / 1, 2, 1, 2, 1, 1 / data valid_processes (:, 46) / 1, 2, 2, 1, 1, 1 / data valid_processes (:, 47) / 1, 3, 1, 3, 1, 1 / data valid_processes (:, 48) / 1, 3, 3, 1, 1, 1 / data valid_processes (:, 49) / 1, 4, 1, 4, 1, 1 / data valid_processes (:, 50) / 1, 4, 4, 1, 1, 1 / data valid_processes (:, 51) / 1, 5, 1, 5, 1, 1 / data valid_processes (:, 52) / 1, 5, 5, 1, 1, 1 / data valid_processes (:, 53) / 1, 6, 1, 6, 1, 1 / data valid_processes (:, 54) / 1, 6, 6, 1, 1, 1 / data valid_processes (:, 55) / 2, -6, -6, 2, 1, 1 / data valid_processes (:, 56) / 2, -6, 2, -6, 1, 1 / data valid_processes (:, 57) / 2, -5, -5, 2, 1, 1 / data valid_processes (:, 58) / 2, -5, 2, -5, 1, 1 / data valid_processes (:, 59) / 2, -4, -4, 2, 1, 1 / data valid_processes (:, 60) / 2, -4, 2, -4, 1, 1 / data valid_processes (:, 61) / 2, -3, -3, 2, 1, 1 / data valid_processes (:, 62) / 2, -3, 2, -3, 1, 1 / data valid_processes (:, 63) / 2, -2, -6, 6, 3, 3 / data valid_processes (:, 64) / 2, -2, -5, 5, 3, 3 / data valid_processes (:, 65) / 2, -2, -4, 4, 3, 3 / data valid_processes (:, 66) / 2, -2, -3, 3, 3, 3 / data valid_processes (:, 67) / 2, -2, -2, 2, 3, 4 / data valid_processes (:, 68) / 2, -2, -1, 1, 3, 3 / data valid_processes (:, 69) / 2, -2, 0, 0, 3, 5 / data valid_processes (:, 70) / 2, -2, 1, -1, 3, 3 / data valid_processes (:, 71) / 2, -2, 2, -2, 3, 4 / data valid_processes (:, 72) / 2, -2, 3, -3, 3, 3 / data valid_processes (:, 73) / 2, -2, 4, -4, 3, 3 / data valid_processes (:, 74) / 2, -2, 5, -5, 3, 3 / data valid_processes (:, 75) / 2, -2, 6, -6, 3, 3 / data valid_processes (:, 76) / 2, -1, -1, 2, 1, 1 / data valid_processes (:, 77) / 2, -1, 2, -1, 1, 1 / data valid_processes (:, 78) / 2, 0, 0, 2, 4, 7 / data valid_processes (:, 79) / 2, 0, 2, 0, 4, 7 / data valid_processes (:, 80) / 2, 1, 1, 2, 1, 1 / data valid_processes (:, 81) / 2, 1, 2, 1, 1, 1 / data valid_processes (:, 82) / 2, 2, 2, 2, 2, 2 / data valid_processes (:, 83) / 2, 3, 2, 3, 1, 1 / data valid_processes (:, 84) / 2, 3, 3, 2, 1, 1 / data valid_processes (:, 85) / 2, 4, 2, 4, 1, 1 / data valid_processes (:, 86) / 2, 4, 4, 2, 1, 1 / data valid_processes (:, 87) / 2, 5, 2, 5, 1, 1 / data valid_processes (:, 88) / 2, 5, 5, 2, 1, 1 / data valid_processes (:, 89) / 2, 6, 2, 6, 1, 1 / data valid_processes (:, 90) / 2, 6, 6, 2, 1, 1 / data valid_processes (:, 91) / 3, -6, -6, 3, 1, 1 / data valid_processes (:, 92) / 3, -6, 3, -6, 1, 1 / data valid_processes (:, 93) / 3, -5, -5, 3, 1, 1 / data valid_processes (:, 94) / 3, -5, 3, -5, 1, 1 / data valid_processes (:, 95) / 3, -4, -4, 3, 1, 1 / data valid_processes (:, 96) / 3, -4, 3, -4, 1, 1 / data valid_processes (:, 97) / 3, -3, -6, 6, 3, 3 / data valid_processes (:, 98) / 3, -3, -5, 5, 3, 3 / data valid_processes (:, 99) / 3, -3, -4, 4, 3, 3 / data valid_processes (:, 100) / 3, -3, -3, 3, 3, 4 / data valid_processes (:, 101) / 3, -3, -2, 2, 3, 3 / data valid_processes (:, 102) / 3, -3, -1, 1, 3, 3 / data valid_processes (:, 103) / 3, -3, 0, 0, 3, 5 / data valid_processes (:, 104) / 3, -3, 1, -1, 3, 3 / data valid_processes (:, 105) / 3, -3, 2, -2, 3, 3 / data valid_processes (:, 106) / 3, -3, 3, -3, 3, 4 / data valid_processes (:, 107) / 3, -3, 4, -4, 3, 3 / data valid_processes (:, 108) / 3, -3, 5, -5, 3, 3 / data valid_processes (:, 109) / 3, -3, 6, -6, 3, 3 / data valid_processes (:, 110) / 3, -2, -2, 3, 1, 1 / data valid_processes (:, 111) / 3, -2, 3, -2, 1, 1 / data valid_processes (:, 112) / 3, -1, -1, 3, 1, 1 / data valid_processes (:, 113) / 3, -1, 3, -1, 1, 1 / data valid_processes (:, 114) / 3, 0, 0, 3, 4, 7 / data valid_processes (:, 115) / 3, 0, 3, 0, 4, 7 / data valid_processes (:, 116) / 3, 1, 1, 3, 1, 1 / data valid_processes (:, 117) / 3, 1, 3, 1, 1, 1 / data valid_processes (:, 118) / 3, 2, 2, 3, 1, 1 / data valid_processes (:, 119) / 3, 2, 3, 2, 1, 1 / data valid_processes (:, 120) / 3, 3, 3, 3, 2, 2 / data valid_processes (:, 121) / 3, 4, 3, 4, 1, 1 / data valid_processes (:, 122) / 3, 4, 4, 3, 1, 1 / data valid_processes (:, 123) / 3, 5, 3, 5, 1, 1 / data valid_processes (:, 124) / 3, 5, 5, 3, 1, 1 / data valid_processes (:, 125) / 3, 6, 3, 6, 1, 1 / data valid_processes (:, 126) / 3, 6, 6, 3, 1, 1 / data valid_processes (:, 127) / 4, -6, -6, 4, 1, 1 / data valid_processes (:, 128) / 4, -6, 4, -6, 1, 1 / data valid_processes (:, 129) / 4, -5, -5, 4, 1, 1 / data valid_processes (:, 130) / 4, -5, 4, -5, 1, 1 / data valid_processes (:, 131) / 4, -4, -6, 6, 3, 3 / data valid_processes (:, 132) / 4, -4, -5, 5, 3, 3 / data valid_processes (:, 133) / 4, -4, -4, 4, 3, 4 / data valid_processes (:, 134) / 4, -4, -3, 3, 3, 3 / data valid_processes (:, 135) / 4, -4, -2, 2, 3, 3 / data valid_processes (:, 136) / 4, -4, -1, 1, 3, 3 / data valid_processes (:, 137) / 4, -4, 0, 0, 3, 5 / data valid_processes (:, 138) / 4, -4, 1, -1, 3, 3 / data valid_processes (:, 139) / 4, -4, 2, -2, 3, 3 / data valid_processes (:, 140) / 4, -4, 3, -3, 3, 3 / data valid_processes (:, 141) / 4, -4, 4, -4, 3, 4 / data valid_processes (:, 142) / 4, -4, 5, -5, 3, 3 / data valid_processes (:, 143) / 4, -4, 6, -6, 3, 3 / data valid_processes (:, 144) / 4, -3, -3, 4, 1, 1 / data valid_processes (:, 145) / 4, -3, 4, -3, 1, 1 / data valid_processes (:, 146) / 4, -2, -2, 4, 1, 1 / data valid_processes (:, 147) / 4, -2, 4, -2, 1, 1 / data valid_processes (:, 148) / 4, -1, -1, 4, 1, 1 / data valid_processes (:, 149) / 4, -1, 4, -1, 1, 1 / data valid_processes (:, 150) / 4, 0, 0, 4, 4, 7 / data valid_processes (:, 151) / 4, 0, 4, 0, 4, 7 / data valid_processes (:, 152) / 4, 1, 1, 4, 1, 1 / data valid_processes (:, 153) / 4, 1, 4, 1, 1, 1 / data valid_processes (:, 154) / 4, 2, 2, 4, 1, 1 / data valid_processes (:, 155) / 4, 2, 4, 2, 1, 1 / data valid_processes (:, 156) / 4, 3, 3, 4, 1, 1 / data valid_processes (:, 157) / 4, 3, 4, 3, 1, 1 / data valid_processes (:, 158) / 4, 4, 4, 4, 2, 2 / data valid_processes (:, 159) / 4, 5, 4, 5, 1, 1 / data valid_processes (:, 160) / 4, 5, 5, 4, 1, 1 / data valid_processes (:, 161) / 4, 6, 4, 6, 1, 1 / data valid_processes (:, 162) / 4, 6, 6, 4, 1, 1 / data valid_processes (:, 163) / 5, -6, -6, 5, 1, 1 / data valid_processes (:, 164) / 5, -6, 5, -6, 1, 1 / data valid_processes (:, 165) / 5, -5, -6, 6, 3, 3 / data valid_processes (:, 166) / 5, -5, -5, 5, 3, 4 / data valid_processes (:, 167) / 5, -5, -4, 4, 3, 3 / data valid_processes (:, 168) / 5, -5, -3, 3, 3, 3 / data valid_processes (:, 169) / 5, -5, -2, 2, 3, 3 / data valid_processes (:, 170) / 5, -5, -1, 1, 3, 3 / data valid_processes (:, 171) / 5, -5, 0, 0, 3, 5 / data valid_processes (:, 172) / 5, -5, 1, -1, 3, 3 / data valid_processes (:, 173) / 5, -5, 2, -2, 3, 3 / data valid_processes (:, 174) / 5, -5, 3, -3, 3, 3 / data valid_processes (:, 175) / 5, -5, 4, -4, 3, 3 / data valid_processes (:, 176) / 5, -5, 5, -5, 3, 4 / data valid_processes (:, 177) / 5, -5, 6, -6, 3, 3 / data valid_processes (:, 178) / 5, -4, -4, 5, 1, 1 / data valid_processes (:, 179) / 5, -4, 5, -4, 1, 1 / data valid_processes (:, 180) / 5, -3, -3, 5, 1, 1 / data valid_processes (:, 181) / 5, -3, 5, -3, 1, 1 / data valid_processes (:, 182) / 5, -2, -2, 5, 1, 1 / data valid_processes (:, 183) / 5, -2, 5, -2, 1, 1 / data valid_processes (:, 184) / 5, -1, -1, 5, 1, 1 / data valid_processes (:, 185) / 5, -1, 5, -1, 1, 1 / data valid_processes (:, 186) / 5, 0, 0, 5, 4, 7 / data valid_processes (:, 187) / 5, 0, 5, 0, 4, 7 / data valid_processes (:, 188) / 5, 1, 1, 5, 1, 1 / data valid_processes (:, 189) / 5, 1, 5, 1, 1, 1 / data valid_processes (:, 190) / 5, 2, 2, 5, 1, 1 / data valid_processes (:, 191) / 5, 2, 5, 2, 1, 1 / data valid_processes (:, 192) / 5, 3, 3, 5, 1, 1 / data valid_processes (:, 193) / 5, 3, 5, 3, 1, 1 / data valid_processes (:, 194) / 5, 4, 4, 5, 1, 1 / data valid_processes (:, 195) / 5, 4, 5, 4, 1, 1 / data valid_processes (:, 196) / 5, 5, 5, 5, 2, 2 / data valid_processes (:, 197) / 5, 6, 5, 6, 1, 1 / data valid_processes (:, 198) / 5, 6, 6, 5, 1, 1 / data valid_processes (:, 199) / 6, -6, -6, 6, 3, 4 / data valid_processes (:, 200) / 6, -6, -5, 5, 3, 3 / data valid_processes (:, 201) / 6, -6, -4, 4, 3, 3 / data valid_processes (:, 202) / 6, -6, -3, 3, 3, 3 / data valid_processes (:, 203) / 6, -6, -2, 2, 3, 3 / data valid_processes (:, 204) / 6, -6, -1, 1, 3, 3 / data valid_processes (:, 205) / 6, -6, 0, 0, 3, 5 / data valid_processes (:, 206) / 6, -6, 1, -1, 3, 3 / data valid_processes (:, 207) / 6, -6, 2, -2, 3, 3 / data valid_processes (:, 208) / 6, -6, 3, -3, 3, 3 / data valid_processes (:, 209) / 6, -6, 4, -4, 3, 3 / data valid_processes (:, 210) / 6, -6, 5, -5, 3, 3 / data valid_processes (:, 211) / 6, -6, 6, -6, 3, 4 / data valid_processes (:, 212) / 6, -5, -5, 6, 1, 1 / data valid_processes (:, 213) / 6, -5, 6, -5, 1, 1 / data valid_processes (:, 214) / 6, -4, -4, 6, 1, 1 / data valid_processes (:, 215) / 6, -4, 6, -4, 1, 1 / data valid_processes (:, 216) / 6, -3, -3, 6, 1, 1 / data valid_processes (:, 217) / 6, -3, 6, -3, 1, 1 / data valid_processes (:, 218) / 6, -2, -2, 6, 1, 1 / data valid_processes (:, 219) / 6, -2, 6, -2, 1, 1 / data valid_processes (:, 220) / 6, -1, -1, 6, 1, 1 / data valid_processes (:, 221) / 6, -1, 6, -1, 1, 1 / data valid_processes (:, 222) / 6, 0, 0, 6, 4, 7 / data valid_processes (:, 223) / 6, 0, 6, 0, 4, 7 / data valid_processes (:, 224) / 6, 1, 1, 6, 1, 1 / data valid_processes (:, 225) / 6, 1, 6, 1, 1, 1 / data valid_processes (:, 226) / 6, 2, 2, 6, 1, 1 / data valid_processes (:, 227) / 6, 2, 6, 2, 1, 1 / data valid_processes (:, 228) / 6, 3, 3, 6, 1, 1 / data valid_processes (:, 229) / 6, 3, 6, 3, 1, 1 / data valid_processes (:, 230) / 6, 4, 4, 6, 1, 1 / data valid_processes (:, 231) / 6, 4, 6, 4, 1, 1 / data valid_processes (:, 232) / 6, 5, 5, 6, 1, 1 / data valid_processes (:, 233) / 6, 5, 6, 5, 1, 1 / data valid_processes (:, 234) / 6, 6, 6, 6, 2, 2 / @ % valid_processes @ <>= integer, dimension(2,0:16), parameter, public :: & double_pdf_kinds = reshape ( [ & 0, 0, & 1, 1, & 1, 2, & 1, 3, & 1, 4, & 2, 1, & 2, 2, & 2, 3, & 2, 4, & 3, 1, & 3, 2, & 3, 3, & 3, 4, & 4, 1, & 4, 2, & 4, 3, & 4, 4], [2, 17]) @ %def double_pdf_kinds @ <>= integer, parameter, dimension(371), public :: int_all = [ & -6, -5, -4, -3, -2, -1, 0, 1 , 2, & 3, 4, 5, 6, -14, -13, -12, -11, -10, & 9, -8, -7, 7, 8, 9, 10, 11, 12, & 13, 14, 7, 8, 9, 10,-151,-150,-115, & -114, -79, -78, -43, -42, 42, 43, 78, 79, & 114, 115, 150, 151,-158,-157,-156,-155,-154, & -153,-152,-149,-148,-147,-146,-145,-144,-143, & -142,-141,-140,-139,-138,-137,-136,-135,-134, & -133,-132,-131,-122,-121,-120,-119,-118,-117, & -116,-113,-112,-111,-110,-109,-108,-107,-106, & -105,-104,-103,-102,-101,-100, -99, -98, -97, & -96, -95, -86, -85, -84, -83, -82, -81, -80, & -77, -76, -75, -74, -73, -72, -71, -70, -69, & -68, -67, -66, -65, -64, -63, -62, -61, -60, & -59, -50, -49, -48, -47, -46, -45, -44, -41, & -40, -39, -38, -37, -36, -35, -34, -33, -32, & -31, -30, -29, -28, -27, -26, -25, -24, -23, & 23, 24, 25, 26, 27, 28, 29, 30, 31, & 32, 33, 34, 35, 36, 37, 38, 39, 40, & 41, 44, 45, 46, 47, 48, 49, 50, 59, & 60, 61, 62, 63, 64, 65, 66, 67, 68, & 69, 70, 71, 72, 73, 74, 75, 76, 77, & 80, 81, 82, 83, 84, 85, 86, 95, 96, & 97, 98, 99, 100, 101, 102, 103, 104, 105, & 106, 107, 108, 109, 110, 111, 112, 113, 116, & 117, 118, 119, 120, 121, 122, 131, 132, 133, & 134, 135, 136, 137, 138, 139, 140, 141, 142, & 143, 144, 145, 146, 147, 148, 149, 152, 153, & 154, 155, 156, 157, 158,-149,-148,-113,-112, & -77, -76, -41, -40, -39, -38, -37, -36, -35, & -34, -33, -32, -31, -30, -29, 44, 80, 81, & 116, 117, 152, 153,-147,-146,-111,-110, -75, & -74, -73, -72, -71, -70, -69, -68, -67, -66, & -65, -64, -63, -28, -27, 45, 46, 82, 118, & 119, 154, 155, 42, 43, 23, 24, 25, 26, & 27, 28, 29, 30, 31, 32, 33, 34, 35, & 36, 37, 38, 39, 40, 41, 44, 45, 46, & 47, 48, 49, 50, 44, 45, 46, 78, 79, & 59, 60, 61, 62, 63, 64, 65, 66, 67, & 68, 69, 70, 71, 72, 73, 74, 75, 76, & 77, 80, 81, 82, 83, 84, 85, 86, 80, & 81, 82 ] @ %def int_all @ <>= integer, parameter, dimension(16), public :: int_sizes_all = & [13, 16, 2, 2, 16, 208, 26, 26, 2, 26, 1, 2, 2, 26, 2, 1] @ %def int_sizes_all @ <>= integer, parameter, dimension(3,0:8), public :: muli_flow_stats = & reshape( [ & 1, 2, 4, & 3, 4, 4, & 5, 6, 8, & 7, 8, 4, & 9, 10, 8, & 11, 16, 16, & 17, 22, 16, & 23, 28, 16, & 29, 52, 96 ], & [3,9]) @ %def muli_flow_states @ <>= integer, parameter, dimension(0:4,52), public :: muli_flows = & reshape( [ & 3, 0, 0, 1, 2, & !1a 1, 0, 0, 2, 1, & 1, 2, 0, 0, 3, & !1b 3, 3, 0, 0, 2, & 4, 0, 0, 1, 2, & !2 4, 0, 0, 2, 1, & 3, 2, 0, 0, 3, & !3 1, 3, 0, 0, 2, & 4, 2, 0, 0, 3, & !4 4, 3, 0, 0, 2, & 4, 0, 1, 3, 4, & !5 4, 0, 1, 4, 3, & 2, 0, 3, 1, 4, & 2, 0, 4, 1, 3, & 2, 0, 3, 4, 1, & 2, 0, 4, 3, 1, & 4, 1, 2, 4, 0, & !6 2, 1, 4, 2, 0, & 4, 2, 1, 4, 0, & 2, 4, 1, 2, 0, & 2, 2, 4, 1, 0, & 2, 4, 2, 1, 0, & 2, 0, 1, 2, 4, & !7 2, 0, 1, 4, 2, & 4, 0, 2, 1, 4, & 4, 0, 4, 1, 2, & 2, 0, 2, 4, 1, & 2, 0, 4, 2, 1, & 9, 1, 2, 3, 4, & !8 5, 1, 2, 4, 3, & 5, 1, 3, 2, 4, & 3, 1, 4, 2, 3, & 3, 1, 3, 4, 2, & 5, 1, 4, 3, 2, & 5, 2, 1, 3, 4, & 5, 2, 1, 4, 3, & 3, 3, 1, 2, 4, & 3, 4, 1, 2, 3, & 3, 3, 1, 4, 2, & 3, 4, 1, 3, 2, & 3, 2, 3, 1, 4, & 3, 2, 4, 1, 3, & 5, 3, 2, 1, 4, & 3, 4, 2, 1, 3, & 5, 3, 4, 1, 2, & 3, 4, 3, 1, 2, & 3, 2, 3, 4, 1, & 3, 2, 4, 3, 1, & 3, 3, 2, 4, 1, & 5, 4, 2, 3, 1, & 3, 3, 4, 2, 1, & 5, 4, 3, 2, 1], [5, 52]) @ %def muli_flows @ This value, [[pts2_scale]], seems to be nowhere set in the code. <>= real(default) :: pts2_scale @ <>= abstract interface function trafo_in (in) use kinds !NODEP! real(default), dimension(3) :: trafo_in real(default), dimension(3), intent(in) :: in end function trafo_in end interface @ %def trafo_in @ <>= abstract interface pure function coord_scalar_in (hyp) use kinds !NODEP! real(default) :: coord_scalar_in real(double), dimension(3), intent(in) :: hyp end function coord_scalar_in end interface @ %def coord_scalar_in @ <>= abstract interface subroutine coord_hcd_in (hyp, cart, denom) use kinds !NODEP! real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom end subroutine coord_hcd_in end interface @ %def coord_hcd_in @ This is the interface to the routines [[alphasPDF]] and [[evolvePDF]] from LHAPDF or internal PDFs which therefore need to be explicitly in [[double]] precision. <>= interface pure function alphaspdf (Q) use kinds !NODEP! real(double) :: alphaspdf real(double), intent(in) :: Q end function alphaspdf end interface @ %def alphaspdf @ <>= interface pure subroutine evolvepdf (x, q, f) use kinds !NODEP! real(double), intent(in) :: x, q real(double), intent(out), dimension(-6:6) :: f end subroutine evolvepdf end interface @ %def evolvepdf @ <>= public :: muli_get_state_transformations <>= pure function muli_get_state_transformations & (inout_kind, lha_flavors) result (transformations) integer, intent(in) :: inout_kind integer, dimension(4), intent(in) :: lha_flavors integer, dimension(4) :: signature logical, dimension(3) :: transformations where (lha_flavors > 0) signature = 1 elsewhere (lha_flavors < 0) signature = -1 elsewhere signature = 0 end where ! print *,"inout_kind=",inout_kind ! print *,"lha_flavors=",lha_flavors ! print *,"signature",signature if ((sum(inout_signatures(1:2,inout_kind)) == sum(signature(1:2))) .and. & (sum(inout_signatures(3:4,inout_kind)) == sum(signature(3:4)))) then transformations(1) = .false. else transformations(1) = .true. signature = -signature end if if (all (inout_signatures(1:2,inout_kind) == signature(1:2))) then transformations(2) = .false. else transformations(2) = .true. end if if (all(inout_signatures(3:4,inout_kind) == signature(3:4))) then transformations(3) = .false. else transformations(3) = .true. end if ! print *,"signature",signature ! print *,"transformations=",transformations end function muli_get_state_transformations @ %muli_get_state_transformations @ <>= public :: h_to_c_param <>= pure function h_to_c_param (hyp) real(default), dimension(3) :: h_to_c_param real(default), dimension(3), intent(in) :: hyp h_to_c_param = [sqrt (sqrt ((((hyp(1)**4) * (one-hyp(3))) + & hyp(3))**2 + (((hyp(2)-(5E-1_default))**3)*4)**2) - & ((hyp(2)-(5E-1_default))**3)*4), & sqrt (sqrt ((((hyp(1)**4)*(one-hyp(3))) + hyp(3))**2 + & (((hyp(2)-(5E-1_default))**3)*4)**2) + & ((hyp(2)-(5E-1_default))**3)*4), hyp(3)] end function h_to_c_param @ %def h_to_c_param @ <>= public :: c_to_h_param <>= pure function c_to_h_param (cart) real(default), dimension(3) :: c_to_h_param real(default), dimension(3), intent(in)::cart c_to_h_param= [ (((cart(1)*cart(2)) - cart(3)) / & (one - cart(3)))**(1/four), (one + sign(abs((cart(2)**2) - & (cart(1)**2))**(1/three), cart(2) - cart(1))) / two, cart(3) ] end function c_to_h_param @ %def c_to_h_param @ <>= public :: h_to_c_param_def <>= pure function h_to_c_param_def (hyp) real(default), dimension(3) :: h_to_c_param_def real(default), dimension(3), intent(in) :: hyp h_to_c_param_def = h_to_c_param ([hyp(1), hyp(2), pts2_scale]) end function h_to_c_param_def @ %def h_to_c_param_def @ <>= public :: h_to_c_ort <>= pure function h_to_c_ort (hyp) real(default), dimension(3) :: h_to_c_ort real(default), dimension(3), intent(in) :: hyp h_to_c_ort = [sqrt (sqrt (((hyp(1) * (one - hyp(3))) + hyp(3))**2 + & (hyp(2) - (5E-1_default))**2) - (hyp(2) - (5E-1_default))), & sqrt (sqrt (((hyp(1) * (one - hyp(3))) + hyp(3))**2 + & (hyp(2)-(5E-1_default))**2) + (hyp(2) - (5E-1_default))), hyp(3)] end function h_to_c_ort @ %def h_to_c_ort @ <>= public :: c_to_h_ort <>= pure function c_to_h_ort (cart) real(default), dimension(3) :: c_to_h_ort real(default), dimension(3), intent(in) :: cart c_to_h_ort = [ (cart(3) - (cart(1)*cart(2))) / (cart(3) - one), & (one - cart(1)**2 + cart(2)**2) / two, cart(3)] end function c_to_h_ort @ %def c_to_h_ort @ <>= public :: h_to_c_ort_def <>= pure function h_to_c_ort_def (hyp) real(default), dimension(3) :: h_to_c_ort_def real(default), dimension(3), intent(in) :: hyp h_to_c_ort_def = h_to_c_ort ([hyp(1), hyp(2), pts2_scale]) end function h_to_c_ort_def @ %def h_to_c_ort_def @ <>= public :: c_to_h_ort_def <>= pure function c_to_h_ort_def (cart) real(default), dimension(3) :: c_to_h_ort_def real(default), dimension(3), intent(in) :: cart c_to_h_ort_def = c_to_h_ort ([ cart(1), cart(2), pts2_scale]) end function c_to_h_ort_def @ %def c_to_h_ort_def @ <>= public :: h_to_c_noparam <>= pure function h_to_c_noparam (hyp) real(default), dimension(2) :: h_to_c_noparam real(default), dimension(2), intent(in) :: hyp h_to_c_noparam = [sqrt (sqrt (hyp(1)**8 + (((hyp(2) - & (5E-1_default))**3)*4)**2) - ((hyp(2)-(5E-1_default))**3)*4), & sqrt (sqrt (hyp(1)**8 + (((hyp(2)-(5E-1_default))**3)*4)**2) + & ((hyp(2)-(5E-1_default))**3)*4)] end function h_to_c_noparam @ %def h_to_c_noparam @ <>= public :: c_to_h_noparam <>= pure function c_to_h_noparam (cart) real(default), dimension(2) :: c_to_h_noparam real(default), dimension(2), intent(in) :: cart c_to_h_noparam = [sqrt (sqrt (cart(1)*cart(2))), & (one + sign(abs((cart(2)**2) - (cart(1)**2))**(one/three), & cart(2)-cart(1)))/two] end function c_to_h_noparam @ %def c_to_h_noparam @ <>= public :: c_to_h_param_def <>= pure function c_to_h_param_def (cart) real(default), dimension(3) :: c_to_h_param_def real(default), dimension(3), intent(in) :: cart if (product (cart(1:2)) >= pts2_scale) then c_to_h_param_def = c_to_h_param ([cart(1), cart(2), pts2_scale]) else c_to_h_param_def = [-one, -one, -one] end if end function c_to_h_param_def @ %def c_to_h_param_def @ <>= public :: h_to_c_smooth <>= pure function h_to_c_smooth (hyp) real(default), dimension(3) :: h_to_c_smooth real(default), dimension(3), intent(in) :: hyp real(default) :: h2 h2 = (((hyp(2) - 5E-1_default)**3) * 4._default + hyp(2)-5E-1_default) & / two h_to_c_smooth = & [sqrt (sqrt((((hyp(1)**4)*(one-hyp(3)))+hyp(3))**2+h2**2) - h2), & sqrt (sqrt((((hyp(1)**4)*(one-hyp(3)))+hyp(3))**2+h2**2) + h2), & hyp(3)] end function h_to_c_smooth @ %def h_to_c_smooth @ <>= public :: c_to_h_smooth <>= pure function c_to_h_smooth (cart) real(default), dimension(3) :: c_to_h_smooth real(default), dimension(3), intent(in) :: cart c_to_h_smooth = & [((product (cart(1:2)) - cart(3)) / (one - cart(3)))**(1/four), & (three-three**(two/3) / (-9._default * cart(1)**2 + & 9._default * cart(2)**2 + sqrt (three + 81._default * & (cart(1)**2 - cart(2)**2)**2))**(one/three)& + 3**(one/3)*(-9._default * cart(1)**2 + 9._default*cart(2)**2 & + sqrt(three + 81._default*(cart(1)**2& - cart(2)**2)**2))**(one/3))/6._default,cart(3)] end function c_to_h_smooth @ %def c_to_h_smooth @ <>= public :: h_to_c_smooth_def <>= pure function h_to_c_smooth_def (hyp) real(default), dimension(3) :: h_to_c_smooth_def real(default), dimension(3), intent(in) :: hyp h_to_c_smooth_def = h_to_c_smooth ([hyp(1), hyp(2), pts2_scale]) end function h_to_c_smooth_def @ %def h_to_c_smooth_def @ <>= @ <>= pure function c_to_h_smooth_def (cart) real(default), dimension(3)::c_to_h_smooth_def real(default), dimension(3), intent(in) :: cart if (product (cart(1:2)) >= pts2_scale) then c_to_h_smooth_def = c_to_h_smooth ([cart(1), cart(2), pts2_scale]) else c_to_h_smooth_def = [-one, -one, -one] end if end function c_to_h_smooth_def @ %def c_to_h_smooth_def @ <>= public :: voxel_h_to_c_ort <>= pure function voxel_h_to_c_ort (hyp) real(default) :: voxel_h_to_c_ort real(default), dimension(3), intent(in) :: hyp real(default) :: T, TH1 T = one - hyp(3) TH1 = T * (one - hyp(1)) voxel_h_to_c_ort = sqrt (T**2 / (five - four*(one-hyp(2))*hyp(2) - & four*(two-TH1)*TH1)) end function voxel_h_to_c_ort @ %def voxel_h_to_c_ort @ <>= public :: voxel_c_to_h_ort <>= pure function voxel_c_to_h_ort(cart) real(default) :: voxel_c_to_h_ort real(default), dimension(3), intent(in) :: cart real(default) :: P P = product (cart(1:2)) if (P > cart(3)) then voxel_c_to_h_ort = (cart(1)**2 + cart(2)**2) / (one -cart(3)) else voxel_c_to_h_ort = zero end if end function voxel_c_to_h_ort @ %def voxel_c_to_h_ort @ <>= public :: voxel_h_to_c_noparam <>= pure function voxel_h_to_c_noparam (hyp) real(default) :: voxel_h_to_c_noparam real(default), dimension(3), intent(in) :: hyp voxel_h_to_c_noparam = 12._default * sqrt ((hyp(1)**6 * & (one - two*hyp(2))**4) / (4*hyp(1)**8 + (one - two*hyp(2))**6)) end function voxel_h_to_c_noparam @ %def voxel_h_to_c_noparam @ <>= public :: voxel_c_to_h_noparam <>= pure function voxel_c_to_h_noparam (cart) real(default) :: voxel_c_to_h_noparam real(default), dimension(3), intent(in) :: cart real(default) :: P voxel_c_to_h_noparam = (cart(1)**2 + cart(2)**2) / (12._default * & (cart(1)*cart(2))**(three/four) * & (cart(2)**2 + cart(1)**2)**(two/three)) end function voxel_c_to_h_noparam @ %def voxel_c_to_h_param @ <>= public :: voxel_h_to_c_param <>= pure function voxel_h_to_c_param (hyp) real(default) :: voxel_h_to_c_param real(default), dimension(3), intent(in) :: hyp voxel_h_to_c_param = 12*Sqrt((hyp(1)**6 * & (one - 2._default*hyp(2))**4 * (hyp(3) - one)**2) / & ((one - two * hyp(2))**6 + four * & (hyp(3)-(hyp(1)**4*(hyp(3)-one)))**2)) end function voxel_h_to_c_param @ %def voxel_h_to_c_param @ <>= public :: voxel_c_to_h_param <>= pure function voxel_c_to_h_param (cart) real(default)::voxel_c_to_h_param real(default), dimension(3), intent(in) :: cart real(default) :: P, T, CP, CM P = product (cart(1:2)) if (P > cart(3)) then P = P - cart(3) CP = cart(1)**2 + cart(2)**2 CM = abs(cart(2)**2 - cart(1)**2) T = 1 - cart(3) voxel_c_to_h_param = (Cp*sqrt(sqrt(P/T))) / (12*Cm**(two/three)*P) else voxel_c_to_h_param = zero end if end function voxel_c_to_h_param @ %def voxel_c_to_h_param @ <>= public :: voxel_h_to_c_smooth @ <>= pure function voxel_h_to_c_smooth (hyp) real(default) :: voxel_h_to_c_smooth real(default), dimension(3), intent(in) :: hyp real(default) :: T T = one - hyp(3) voxel_h_to_c_smooth = 8._default * (hyp(1)**3 * (one + three * & (hyp(2) - one)*hyp(2))*T) / sqrt ((one - two*hyp(2) * (two + & hyp(2)*(two*hyp(2)-three)))**2 + & four * (one + (hyp(1)**4 - one)*T)**2) end function voxel_h_to_c_smooth @ %def voxel_h_to_c_smooth @ <>= public :: voxel_c_to_h_smooth <>= pure function voxel_c_to_h_smooth (cart) real(default) :: voxel_c_to_h_smooth real(default), dimension(3), intent(in) :: cart real(default) :: P, S, T, CM, CP P = product (cart(1:2)) if (P > cart(3)) then P = P - cart(3) CP = cart(1)**2 + cart(2)**2 CM = cart(2)**2 - cart(1)**2 T = 1 - cart(3) S = sqrt(three + 81._default*cm**2) voxel_c_to_h_smooth = (three**(one/three) * Cp*(three**(one/three) + & (9._default*Cm + S)**(two/three)) * sqrt (sqrt (P/T))) / & (four * P * S * (9._default * Cm + S)**(one/three)) else voxel_c_to_h_smooth = zero end if end function voxel_c_to_h_smooth @ %def voxel_c_to_h_smooth @ <>= public :: voxel_h_to_c_ort_def <>= pure function voxel_h_to_c_ort_def (hyp) real(default) :: voxel_h_to_c_ort_def real(default), dimension(3), intent(in) :: hyp voxel_h_to_c_ort_def = voxel_h_to_c_ort (hyp) end function voxel_h_to_c_ort_def @ %def voxel_h_to_c_ort_def @ <>= public :: voxel_c_to_h_ort_def <>= pure function voxel_c_to_h_ort_def (cart) real(default) :: voxel_c_to_h_ort_def real(default), dimension(3), intent(in) :: cart voxel_c_to_h_ort_def = voxel_c_to_h_ort (cart) end function voxel_c_to_h_ort_def @ %def voxel_c_to_h_ort_def @ <>= public :: voxel_h_to_c_param_def <>= pure function voxel_h_to_c_param_def (hyp) real(default) :: voxel_h_to_c_param_def real(default), dimension(3), intent(in) :: hyp voxel_h_to_c_param_def = voxel_h_to_c_param (hyp) end function voxel_h_to_c_param_def @ %def voxel_h_to_c_param_def @ <>= public :: voxel_c_to_h_param_def <>= pure function voxel_c_to_h_param_def (cart) real(default) :: voxel_c_to_h_param_def real(default), dimension(3), intent(in) :: cart voxel_c_to_h_param_def = voxel_c_to_h_param (cart) end function voxel_c_to_h_param_def @ %def voxel_c_to_h_param_def @ <>= public :: voxel_h_to_c_smooth_def <>= pure function voxel_h_to_c_smooth_def (hyp) real(default) :: voxel_h_to_c_smooth_def real(default), dimension(3), intent(in) :: hyp voxel_h_to_c_smooth_def = voxel_h_to_c_smooth (hyp) end function voxel_h_to_c_smooth_def @ %def voxel_h_to_c_smooth_def @ <>= public :: voxel_c_to_h_smooth_def <>= pure function voxel_c_to_h_smooth_def (cart) real(default) :: voxel_c_to_h_smooth_def real(default), dimension(3), intent(in) :: cart voxel_c_to_h_smooth_def = voxel_c_to_h_smooth (cart) end function voxel_c_to_h_smooth_def @ %def voxel_c_to_h_smooth_def @ <>= public :: denom_cart <>= pure function denom_cart (cart) real(default) :: denom_cart real(default), dimension(3), intent(in) :: cart denom_cart = 1._default / (864._default * sqrt (cart(3)**3 * & (1._default - cart(3) / product(cart(1:2))))) end function denom_cart @ %def denom_cart @ <>= public :: denom_ort <>= pure function denom_ort (hyp) real(default) :: denom_ort real(default), dimension(3), intent(in) :: hyp real(default) :: Y, P Y = (one - two * hyp(2))**2 P = one - hyp(3) if (hyp(1) > zero .and. hyp(3) > zero) then denom_ort = sqrt ((P + (-1 + Hyp(1))*P**2) / & (746496*hyp(1)*hyp(3)**3 * (4*(1 + (-1 + hyp(1))*P)**2 + Y))) else denom_ort = zero end if end function denom_ort @ %def denom_ort @ <>= public :: denom_param <>= pure function denom_param (hyp) real(default) :: denom_param real(default), dimension(3), intent(in) :: hyp real(default) :: X, Y, P X = hyp(1)**4 Y = 1._default - 2._default * hyp(2) P = 1._default - hyp(3) if (hyp(3) > 0._default) then denom_param = sqrt ((P * (1+P*(X-1)) * Sqrt(X)*Y**4) / & (5184*(4*(1+P*(X-1))**2+Y**6)*hyp(3)**3)) else denom_param = zero end if end function denom_param @ %def denom_param @ <>= public :: denom_param_reg <>= pure function denom_param_reg (hyp) real(default) :: denom_param_reg real(default), dimension(3), intent(in) :: hyp real(default) :: X, Y, P X = hyp(1)**4 Y = one - two * hyp(2) P = one - hyp(3) if (hyp(3) > zero) then denom_param_reg = sqrt ((P*(1+P*(X-1)) * Sqrt(X)*Y**4) / & (5184*(4*(1+P*(X-1))**2+Y**6) * (hyp(3) + norm2_p_t_0)**3)) else denom_param_reg = zero end if end function denom_param_reg @ %def denom_param_reg @ <>= public :: denom_smooth <>= pure function denom_smooth (hyp) real(default) :: denom_smooth real(default), dimension(3), intent(in) :: hyp real(default) :: X, Y, P X = hyp(1)**2 Y = (one - two * hyp(2))**2 P = one - hyp(3) if (hyp(3) > zero) then denom_smooth = sqrt ((P * X * (one + P*(-one + X**2)) * & (1 + three*Y)**2)/(46656*hyp(3)**3 & *(16*(1 + P*(-1 + X**2))**2 + Y + 2*Y**2 + Y**3))) else denom_smooth = zero end if end function denom_smooth @ %def denom_smooth @ <>= public :: denom_smooth_reg <>= pure function denom_smooth_reg (hyp) real(default) :: denom_smooth_reg real(default), dimension(3), intent(in) :: hyp real(default) :: X, Y, P X = hyp(1)**2 Y = (one - two * hyp(2))**2 P = one - hyp(3) if (hyp(3) > zero) then denom_smooth_reg = sqrt ((P * X * (1 + P*(-1 + X**2)) * & (1 + 3*Y)**2)/(46656*(hyp(3) + norm2_p_t_0)**3 * & (16 * (1 + P*(-1 + X**2))**2 + Y + 2*Y**2 + Y**3))) else denom_smooth_reg = zero end if end function denom_smooth_reg @ %def denom_smooth_reg @ <>= public :: denom_cart_save <>= pure function denom_cart_save (cart) real(default) :: denom_cart_save real(default), dimension(3), intent(in) :: cart if (product(cart(1:2)) > cart(3)) then denom_cart_save = denom_cart (cart) else denom_cart_save = zero end if end function denom_cart_save @ %def denom_cart_save @ <>= public :: denom_ort_save <>= pure function denom_ort_save (hyp) real(default) :: denom_ort_save real(default), dimension(3), intent(in) :: hyp real(default) :: Y, Z, W real(default), dimension(3) :: cart cart = h_to_c_ort (hyp) if (cart(1) > one .or. cart(2) > one) then denom_ort_save = zero else denom_ort_save = denom_ort (hyp) end if end function denom_ort_save @ %def denom_ort_save @ <>= public :: denom_param_save <>= pure function denom_param_save (hyp) real(default) :: denom_param_save real(default), dimension(3), intent(in) :: hyp real(default) :: Y, Z, W real(default), dimension(3) :: cart cart=h_to_c_param (hyp) if (cart(1) > one .or. cart(2) > one) then denom_param_save = zero else denom_param_save = denom_param (hyp) end if end function denom_param_save @ %def denom_param_save @ <>= public :: denom_smooth_save <>= pure function denom_smooth_save (hyp) real(default) :: denom_smooth_save real(default), dimension(3), intent(in) :: hyp real(default) :: Y, Z, W real(default), dimension(3) :: cart cart = h_to_c_smooth (hyp) if (cart(1) > one .or. cart(2) > one) then denom_smooth_save = zero else denom_smooth_save = denom_smooth (hyp) end if end function denom_smooth_save @ %def denom_smooth_save @ <>= public :: denom_cart_cuba_int <>= subroutine denom_cart_cuba_int (d_cart, cart, d_denom, denom, pt2s) real(default), dimension(3), intent(in) :: cart real(default), dimension(1), intent(out) :: denom real(default), intent(in) :: pt2s integer, intent(in) :: d_cart, d_denom denom(1) = denom_cart_save ([cart(1), cart(2), pt2s]) end subroutine denom_cart_cuba_int @ %def denom_cart_cuba_int @ <>= public :: denom_ort_cuba_int <>= subroutine denom_ort_cuba_int (d_hyp, hyp, d_denom, denom, pt2s) real(default), dimension(3), intent(in) :: hyp real(default), dimension(1), intent(out) :: denom real(default), intent(in) :: pt2s integer, intent(in) :: d_hyp, d_denom denom(1) = denom_ort_save ([hyp(1), hyp(2), pt2s]) end subroutine denom_ort_cuba_int @ %def denom_ort_cuba_int @ <>= public :: denom_param_cuba_int <>= subroutine denom_param_cuba_int (d_hyp, hyp, d_denom, denom, pt2s) real(default), dimension(3), intent(in) :: hyp real(default), dimension(1), intent(out) :: denom real(default), intent(in) :: pt2s integer, intent(in) :: d_hyp, d_denom denom(1) = denom_param_save ([hyp(1), hyp(2), pt2s]) end subroutine denom_param_cuba_int @ %def denom_param_cuba_int @ <>= public :: denom_smooth_cuba_int <>= subroutine denom_smooth_cuba_int (d_hyp, hyp, d_denom, denom, pt2s) real(default), dimension(3), intent(in) :: hyp real(default), dimension(1), intent(out) :: denom real(default), intent(in) :: pt2s integer, intent(in) :: d_hyp, d_denom denom(1) = denom_smooth_save ([hyp(1), hyp(2), pt2s]) end subroutine denom_smooth_cuba_int @ %def denom_smooth_cuba_int @ <>= public :: coordinates_hcd_cart <>= subroutine coordinates_hcd_cart (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom cart = hyp denom = denom_cart_save (cart) end subroutine coordinates_hcd_cart @ %def coordinates_hcd_cart @ <>= public :: coordinates_hcd_ort <>= subroutine coordinates_hcd_ort (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out)::denom cart = h_to_c_ort (hyp) denom = denom_ort (hyp) end subroutine coordinates_hcd_ort @ %def coordinates_hcd_ort @ <>= public :: coordinates_hcd_param <>= subroutine coordinates_hcd_param (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom cart = h_to_c_param (hyp) denom = denom_param (hyp) end subroutine coordinates_hcd_param @ %def coordinates_hcd_param @ <>= public :: coordinates_hcd_param_reg <>= subroutine coordinates_hcd_param_reg (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom cart = h_to_c_param (hyp) denom = denom_param_reg (hyp) end subroutine coordinates_hcd_param_reg @ %def coordinates_hcd_param_reg @ <>= public :: coordinates_hcd_smooth <>= subroutine coordinates_hcd_smooth (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom cart = h_to_c_smooth (hyp) denom = denom_smooth (hyp) end subroutine coordinates_hcd_smooth @ %def coordinates_hcd_smooth @ <>= public :: coordinates_hcd_smooth_reg <>= subroutine coordinates_hcd_smooth_reg (hyp, cart, denom) real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default), intent(out) :: denom cart = h_to_c_smooth (hyp) denom = denom_smooth_reg (hyp) end subroutine coordinates_hcd_smooth_reg @ %def coordinates_hcd_smooth_reg @ <>= public :: interactions_dddsigma_reg <>= pure subroutine interactions_dddsigma_reg & (process_id, double_pdf_id, hyp, cart, dddsigma) real(default), intent(out) :: dddsigma integer, intent(in) :: process_id, double_pdf_id real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default) :: a, pt2shat, gev_pt, gev2_pt cart = h_to_c_param (hyp) a = product (cart(1:2)) if (cart(1) <= 1D0 .and. cart(2) <= 1D0) then pt2shat = hyp(3) / a gev_pt = sqrt(hyp(3)) * gev_pt_max gev2_pt = hyp(3) * gev2_pt_max ! print *,process_id,pt2shat dddsigma = & const_pref & * alphasPDF (dble (sqrt (gev2_pt+gev2_p_t_0)))**2 & * ps_io_pol (process_id, pt2shat) & * pdf_in_in_kind & (process_id, double_pdf_id, cart(1), cart(2), gev_pt) & * denom_param_reg (hyp) / a else dddsigma = zero end if end subroutine interactions_dddsigma_reg @ %def interactions_dddsigma_reg @ <>= public :: pdf_in_in_kind <>= pure function pdf_in_in_kind (process_id, double_pdf_id, c1, c2, gev_pt) real(default) :: pdf_in_in_kind real(default), intent(in) :: c1, c2, gev_pt integer, intent(in) :: process_id, double_pdf_id real(default) :: pdf1, pdf2 call single_pdf (valid_processes(1, process_id), & double_pdf_kinds(1, double_pdf_id), c1, gev_pt, pdf1) call single_pdf (valid_processes(2, process_id), & double_pdf_kinds(2, double_pdf_id), c2, gev_pt, pdf2) pdf_in_in_kind = pdf1 * pdf2 contains pure subroutine single_pdf (flavor, pdf_kind, c, gev_pt, pdf) integer, intent(in) :: flavor, pdf_kind real(default), intent(in) :: c, gev_pt real(default), intent(out) :: pdf real(double), dimension(-6:6) :: lha_pdf call evolvePDF (dble (c), dble (gev_pt), lha_pdf) select case (pdf_kind) case (1) pdf = lha_pdf (0) case (2) if (flavor==1 .or. flavor==2) then pdf = lha_pdf (-flavor) else pdf = lha_pdf (flavor) end if case (3) pdf = lha_pdf(1) - lha_pdf(-1) case (4) pdf = lha_pdf(2) - lha_pdf(-2) end select end subroutine single_pdf end function pdf_in_in_kind @ %def pdf_in_in_kind @ <>= public :: ps_io_pol <>= elemental function ps_io_pol (process_io_id, pt2shat) real(default) :: ps_io_pol integer, intent(in) :: process_io_id real(default), intent(in) :: pt2shat ps_io_pol = dot_product([1._default, pt2shat, pt2shat**2, pt2shat**3], & phase_space_coefficients_inout (1:4, & valid_processes (6, process_io_id))) end function ps_io_pol @ %def ps_io_pol @ <>= public :: interactions_dddsigma <>= pure subroutine interactions_dddsigma & (process_id, double_pdf_id, hyp, cart, dddsigma) real(default), intent(out) :: dddsigma integer, intent(in) :: process_id, double_pdf_id real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default) :: a, pt2shat, gev_pt cart = h_to_c_param (hyp) a = product (cart(1:2)) if (cart(1) <= 1._default .and. cart(2) <= 1._default) then pt2shat = hyp(3) / a gev_pt = sqrt(hyp(3)) * gev_pt_max ! print *,process_id,pt2shat dddsigma = const_pref * & alphasPDF (dble (gev_pt))**2 * & ps_io_pol (process_id, pt2shat) * & pdf_in_in_kind & (process_id, double_pdf_id, cart(1), cart(2), gev_pt) * & denom_param(hyp) / a else dddsigma = zero end if end subroutine interactions_dddsigma @ %def interactions_dddsigma @ <>= public :: interactions_dddsigma_print <>= subroutine interactions_dddsigma_print & (process_id, double_pdf_id, hyp, cart, dddsigma) real(default), intent(out) :: dddsigma integer, intent(in) :: process_id, double_pdf_id real(default), dimension(3), intent(in) :: hyp real(default), dimension(3), intent(out) :: cart real(default) :: a, pt2shat, gev_pt cart = h_to_c_param (hyp) a = product (cart(1:2)) if (cart(1) <= 1._default .and. cart(2) <= 1._default) then pt2shat = hyp(3) / a gev_pt=sqrt(hyp(3))*gev_pt_max ! print *,process_id,pt2shat dddsigma = const_pref * & ! alphasPDF(dble (gev_pt))**2 * & ps_io_pol (process_id, pt2shat) * & pdf_in_in_kind & (process_id, double_pdf_id, cart(1), cart(2), gev_pt) * & denom_param (hyp) / a else dddsigma = zero end if write(11, *) dddsigma, pt2shat, & pdf_in_in_kind (process_id, double_pdf_id, cart(1), cart(2), & gev_pt), ps_io_pol (process_id, pt2shat), const_pref, & denom_param(hyp), a flush(11) end subroutine interactions_dddsigma_print @ %def interactions_dddsigma_print @ <>= public :: interactions_dddsigma_cart <>= pure subroutine interactions_dddsigma_cart & (process_id, double_pdf_id, cart, dddsigma) real(default), intent(out) :: dddsigma integer, intent(in) :: process_id, double_pdf_id real(default), dimension(3), intent(in) :: cart real(default) :: a, pt2shat, gev_pt a = product (cart(1:2)) if (cart(1) <= one .and. cart(2) <= one) then pt2shat = cart(3) / a gev_pt = sqrt(cart(3)) * gev_pt_max ! print *,process_id,pt2shat dddsigma = const_pref * & alphasPDF (dble (gev_pt))**2 * & ps_io_pol (process_id, pt2shat) * & pdf_in_in_kind & (process_id, double_pdf_id, cart(1), cart(2), gev_pt) * & denom_cart (cart) / a else dddsigma = zero end if end subroutine interactions_dddsigma_cart @ %def interactions_dddsigma_cart @ <>= public :: cuba_gg_me_smooth <>= subroutine cuba_gg_me_smooth (d_hyp, hyp, d_me, me, pt2s) integer, intent(in) :: d_hyp, d_me real(default), dimension(d_hyp), intent(in) :: hyp real(default), dimension(1), intent(out) :: me real(default), dimension(3) :: cart real(default), intent(in) :: pt2s real(default) :: p, p2 if (d_hyp == 3) then p = hyp(3) p2 = hyp(3)**2 else if (d_hyp == 2) then p = sqrt (pt2s) p2 = pt2s end if end if cart = h_to_c_smooth ([hyp(1), hyp(2), p2]) if (p > pts_min .and. product (cart(1:2)) > p2) then me(1) = const_pref * & alphasPDF (dble (p*gev_pt_max))**2 * & ps_io_pol (109, p2) * & pdf_in_in_kind (109, 11, cart(1), cart(2), p2) * & denom_smooth ([hyp(1), hyp(2), p2]) / product (cart(1:2)) else me(1) = zero end if end subroutine cuba_gg_me_smooth @ %def cuba_gg_me_smooth @ <>= public :: cuba_gg_me_param <>= subroutine cuba_gg_me_param (d_hyp, hyp, d_me, me, pt2s) integer, intent(in)::d_hyp,d_me real(default), dimension(d_hyp), intent(in) :: hyp real(default), dimension(1), intent(out) :: me real(default), dimension(3) :: cart real(default), intent(in) :: pt2s real(default) :: p, p2 if (d_hyp == 3) then p = hyp(3) p2 = hyp(3)**2 else if (d_hyp == 2) then p = sqrt (pt2s) p2 = pt2s end if end if cart = h_to_c_param ([hyp(1), hyp(2), p2]) if (p>pts_min .and. product (cart(1:2))>p2) then me(1) = const_pref * & alphasPDF(dble (p*gev_pt_max))**2 * & ps_io_pol (109, p2) * & pdf_in_in_kind (109, 11, cart(1), cart(2), p2) * & denom_param ([hyp(1), hyp(2), p2]) / product(cart(1:2)) else me(1) = zero end if end subroutine cuba_gg_me_param @ %def cuba_gg_me_param @ <>= public :: cuba_gg_me_ort <>= subroutine cuba_gg_me_ort (d_hyp, hyp, d_me, me, pt2s) integer, intent(in) :: d_hyp, d_me real(default), dimension(d_hyp), intent(in) :: hyp real(default), dimension(1), intent(out) :: me real(default), dimension(3) :: cart real(default), intent(in) :: pt2s real(default) :: p, p2 if (d_hyp == 3) then p = hyp(3) p2 = hyp(3)**2 else if (d_hyp == 2) then p = sqrt(pt2s) p2 = pt2s end if end if cart = h_to_c_ort ([hyp(1), cart(2), p2]) if (p > pts_min .and. product (cart(1:2)) > p2) then me(1) = const_pref * & alphasPDF(dble (p*gev_pt_max))**2 * & ps_io_pol (109, p2) * & pdf_in_in_kind (109, 11, cart(1), cart(2), p2) * & denom_ort ([hyp(1), hyp(2), p2]) / product (cart(1:2)) else me(1) = zero end if end subroutine cuba_gg_me_ort @ %def cuba_gg_me_ort @ <>= public :: cuba_gg_me_cart <>= subroutine cuba_gg_me_cart (d_cart, cart, d_me, me, pt2s) integer, intent(in) :: d_cart, d_me real(default), dimension(d_cart), intent(in) :: cart real(default), dimension(1), intent(out) :: me real(default), intent(in) :: pt2s real(default) :: a, p, p2 if (d_cart == 3) then p = cart(3) p2 = cart(3)**2 else if (d_cart == 2) then p = sqrt (pt2s) p2 = pt2s end if end if a = product (cart(1:2)) if (p > pts_min .and. a > p2) then me(1) = const_pref * & alphasPDF (dble (p*gev_pt_max))**2 * & ps_io_pol (109, p2) * & pdf_in_in_kind (109, 11, cart(1), cart(2), p2) * & denom_cart ([cart(1), cart(2), p2]) / a else me(1) = zero end if end subroutine cuba_gg_me_cart @ %def cuba_gg_me_cart @ <>= public :: interactions_proton_proton_integrand_generic_17_reg <>= subroutine interactions_proton_proton_integrand_generic_17_reg & (hyp_2, trafo, f, pt) real(default), dimension(2), intent(in) :: hyp_2 procedure(coord_hcd_in) :: trafo real(default), dimension(17), intent(out) :: f class(transverse_mom_t), intent(in) :: pt real(default), dimension(3) :: cart, hyp_3 real(default), dimension(5) :: psin real(double), dimension(-6:6) :: c_dble, d_dble real(default), dimension(-6:6) :: c, d real(default) :: gev_pt, gev2_pt, pts, pt2s, pt2shat, a, & pdf_seaquark_seaquark, pdf_seaquark_gluon, pdf_gluon_gluon, & pdf_up_seaquark, pdf_up_gluon, pdf_down_seaquark, pdf_down_gluon, & v1u, v1d, v2u, v2d, denom pts = pt%get_unit_scale() pt2s = pt%get_unit2_scale() gev_pt = pt%get_gev_scale() gev2_pt = pt%get_gev2_scale() hyp_3(1:2) = hyp_2 hyp_3(3) = pt2s call trafo (hyp_3, cart, denom) a = product (cart(1:2)) if (cart(1) <= one .and. cart(2) <= one .and. a > pt2s) then pt2shat = pt2s / a ! phase space polynom psin = matmul ([one, pt2shat, pt2shat**2, pt2shat**3], & phase_space_coefficients_in) ! pdf call evolvepdf (dble (cart(1)), dble (gev_pt), c_dble) call evolvepdf (dble (cart(2)), dble (gev_pt), d_dble) c = c_dble d = d_dble ! c = [1,1,1,1,1,1,1,1,1,1,1,1,1]*1D0 ! d = c v1d = c(1) - c(-1) v1u = c(2) - c(-2) v2d = d(1) - d(-1) v2u = d(2) - d(-2) c(1) = c(-1) c(2) = c(-2) d(1) = d(-1) d(2) = d(-2) f(1) = zero !!! gluon_gluon f( 2) = (c(0)*d(0)) * psin(5) !!! type5 !!! gluon_seaquark f( 3) = (c(0)*d(-4) + c(0)*d(-3) + c(0)*d(-2) + c(0)*d(-1) + & c(0)*d(1) + c(0)*d(2) + c(0)*d(3) + c(0)*d(4)) * psin(4) !!! type4 !!! gluon_down f( 4) = (c(0)*v2d) * psin(4) !!! type4 !!! gluon_up f( 5) = (c(0)*v2u) * psin(4) !!! type4 !!! seaquark_gluon f( 6) = (c(-4)*d(0) + c(-3)*d(0) + c(-2)*d(0) + c(-1)*d(0) + & c(1)*d(0) + c(2)*d(0) + c(3)*d(0) + c(4)*d(0)) * psin(4) !!! type4 !!! seaquark_seaquark f( 7) = & !!! type1 (c(-4)*d(-3) + c(-4)*d(-2) + c(-4)*d(-1) + c(-4)*d( 1) + & c(-4)*d( 2) + c(-4)*d( 3) + c(-3)*d(-4) + c(-3)*d(-2) + & c(-3)*d(-1) + c(-3)*d( 1) + c(-3)*d( 2) + c(-3)*d( 4) + & c(-2)*d(-4) + c(-2)*d(-3) + c(-2)*d(-1) + c(-2)*d( 1) + & c(-2)*d( 3) + c(-2)*d( 4) + c(-1)*d(-4) + c(-1)*d(-3) + & c(-1)*d(-2) + c(-1)*d( 2) + c(-1)*d( 3) + c(-1)*d( 4) + & c( 1)*d(-4) + c( 1)*d(-3) + c( 1)*d(-2) + c( 1)*d( 2) + & c( 1)*d( 3) + c( 1)*d( 4) + c( 2)*d(-4) + c( 2)*d(-3) + & c( 2)*d(-1) + c( 2)*d( 1) + c( 2)*d( 3) + c( 2)*d( 4) + & c( 3)*d(-4) + c( 3)*d(-2) + c( 3)*d(-1) + c( 3)*d( 1) + & c( 3)*d( 2) + c( 3)*d( 4) + c( 4)*d(-3) + c( 4)*d(-2) + & c( 4)*d(-1) + c( 4)*d( 1) + c( 4)*d( 2) + c( 4)*d( 3)) * & psin(1) + & !!! type2 (c(-4)*d(-4) + c(-3)*d(-3) + c(-2)*d(-2) + c(-1)*d(-1) + & c( 4)*d( 4) + c( 3)*d( 3) + c(2)*d( 2) + c(1)*d( 1)) * & psin(2) + & !!! type3 (c(-4)*d( 4) + c(-3)*d( 3) + c(-2)*d( 2) + c(-1)*d( 1) + & c( 4)*d(-4) + c( 3)*d(-3) + c(2)*d(-2) + c(1)*d(-1)) * & psin(3) !!! seaquark_down f( 8) = & !!! type1 (c(-4)*v2d + c(-3)*v2d + c(-2)*v2d + c( 2)*v2d + & c( 3)*v2d + c( 4)*v2d) * psin(1) + & !!! type2 c( 1)*v2d * psin(2) + & !!! type3 c(-1)*v2d * psin(3) !!! seaquark_up f( 9) = & !!! type1 (c(-4)*v2u + c(-3)*v2u + c(-1)*v2u + c( 1)*v2u + & c( 3)*v2u + c( 4)*v2u) * psin(1) + & !!! type2 c(2)*v2u * psin(2) + & !!! type3 c(-2)*v2u * psin(3) !!! down_gluon f(10) = (v1d*d( 0)) * psin(4) !!! type4 !!! down_seaquark f(11) = & !!! type1 (v1d*d(-4) + v1d*d(-3) + v1d*d(-2) + v1d*d( 2) + & v1d*d( 3) + v1d*d( 4)) * psin(1) + & !!! type2 v1d*d( 1) * psin(2) + & !!! type3 v1d*d(-1) * psin(3) !!! down_down f(12) = v1d*v2d * psin(2) !!! down_up f(13) = v1d*v2u * psin(1) !!! up_gluon f(14) = (v1u*d(0)) * psin(4) !!! type4 !!! up_seaquark f(15) = & !!! type1 (v1u*d(-4) + v1u*d(-3) + v1u*d(-1) + v1u*d( 1) + & v1u*d( 3) + v1u*d( 4)) * psin(1) + & !!! type2 v1u*d(2) * psin(2) + & !!! type3 v1u*d(-2) * psin(3) !!! up_down f(16) = v1u * v2d * psin(1) !!! up_up f(17) = v1u * v2u * psin(2) f=f * const_pref & * alphasPDF (dble (sqrt(gev2_pt+gev2_p_t_0)))**2 & * denom / a ! print *, const_pref, alphasPDF(gev_pt)**2, denom_smooth (hyp), a else f = [zero, zero, zero, zero, zero, zero, zero, zero, zero, & zero, zero, zero, zero, zero, zero, zero, zero] end if ! print *, pt2shat, c(0)*d(0), psin(5), const_pref, & ! alphasPDF(gev_pt)**2, denom, a end subroutine interactions_proton_proton_integrand_generic_17_reg @ %def interactions_proton_proton_integrand_generic_17_reg @ <>= ! subroutine coordinates_proton_proton_integrand_cart_11 & ! (d_hyp, hyp_2, d_f, f) ! integer, intent(in) :: d_hyp, d_f ! real(default), dimension(2), intent(in) :: hyp_2 ! real(default), dimension(11), intent(out) :: f ! call coordinates_proton_proton_integrand_generic_11 & ! (hyp_2, coordinates_hcd_cart, f) ! ! write (51,*) hyp_2, momentum_get_pts_scale(), f ! end subroutine coordinates_proton_proton_integrand_cart_11 @ %def coordinates_proton_proton_integrand_cart_11 @ <>= ! subroutine coordinates_proton_proton_integrand_ort_11 & ! (d_hyp, hyp_2, d_f, f) ! integer, intent(in) :: d_hyp, d_f ! real(default), dimension(2), intent(in) :: hyp_2 ! real(default), dimension(11), intent(out) :: f ! call coordinates_proton_proton_integrand_generic_11 & ! (hyp_2, coordinates_hcd_ort, f) ! ! write (52,*) hyp_2, momentum_get_pts_scale(), f ! end subroutine coordinates_proton_proton_integrand_ort_11 @ %def coordinates_proton_proton_integrand_ort_11 @ <>= ! subroutine coordinates_proton_proton_integrand_param_11 & ! (d_hyp, hyp_2, d_f, f) ! integer, intent(in) :: d_hyp, d_f ! real(default), dimension(2), intent(in) :: hyp_2 ! real(default), dimension(11), intent(out) :: f ! call coordinates_proton_proton_integrand_generic_11 & ! (hyp_2, coordinates_hcd_param, f) ! ! write(53,*) hyp_2, momentum_get_pts_scale(), f ! end subroutine coordinates_proton_proton_integrand_param_11 @ %def coordinates_proton_proton_integrand_param_11 @ <>= ! subroutine coordinates_proton_proton_integrand_smooth_11 & ! (d_hyp, hyp_2, d_f, f) ! integer, intent(in)::d_hyp,d_f ! real(default), dimension(2), intent(in) :: hyp_2 ! real(default), dimension(11), intent(out) :: f ! call coordinates_proton_proton_integrand_generic_11 (hyp_2, & ! coordinates_hcd_smooth, f) ! ! write (54,*) hyp_2, momentum_get_pts_scale(), f ! end subroutine coordinates_proton_proton_integrand_smooth_11 @ %def coordinates_proton_proton_integrand_smooth_11 @ <>= public :: interactions_proton_proton_integrand_param_17_reg <>= subroutine interactions_proton_proton_integrand_param_17_reg & (d_hyp, hyp_2, d_f, f, pt) integer, intent(in) :: d_hyp, d_f real(default), dimension(2), intent(in) :: hyp_2 real(default), dimension(17), intent(out) :: f class(transverse_mom_t), intent(in) :: pt call interactions_proton_proton_integrand_generic_17_reg & (hyp_2, coordinates_hcd_param_reg, f, pt) ! write (53,*) hyp_2,momentum_get_pts_scale(),f end subroutine interactions_proton_proton_integrand_param_17_reg @ %def interactions_proton_proton_integrand_param_17_reg @ <>= public :: interactions_proton_proton_integrand_smooth_17_reg <>= subroutine interactions_proton_proton_integrand_smooth_17_reg & (d_hyp, hyp_2, d_f, f, pt) integer, intent(in) :: d_hyp, d_f real(default), dimension(2), intent(in) :: hyp_2 real(default), dimension(17), intent(out) :: f class(transverse_mom_t), intent(in) :: pt call interactions_proton_proton_integrand_generic_17_reg & (hyp_2, coordinates_hcd_smooth_reg, f, pt) ! write (53,*)hyp_2,momentum_get_pts_scale(), f end subroutine interactions_proton_proton_integrand_smooth_17_reg @ %def interactions_proton_proton_integrand_smooth_17_reg @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{VEGAS and CUBA integration routines} This file contains the module [[muli_cuba]], a wrapper for the CUBA integration library. Different algorithms and settings have been tried out for the integration, including VEGAS, and this wrapper has been mainly written for that purpose. <<[[muli_cuba.f90]]>>= <> module muli_cuba <> use constants use diagnostics use muli_base use muli_momentum <> <> <> <> <> contains <> end module muli_cuba @ %def muli_cuba @ <>= integer, parameter :: max_maxeval = huge(1) @ %def max_maxeval @ <>= public :: cuba_class <>= type, extends (ser_class_t), abstract :: cuba_class real(default) :: start_time = zero real(default) :: stop_time = zero real(default) :: run_time = zero integer :: dim_x = 2 integer :: dim_f = 1 type(transverse_mom_t) :: userdata real(default) :: eps_rel = 1.E-3_default real(default) :: eps_abs = 0._default integer :: flags = 0 integer :: seed = 1 integer :: min_eval = 0 integer :: max_eval = max_maxeval integer :: neval = 0 integer, public :: fail = -1 integer :: nregions = 0 real(default), dimension(:), allocatable :: integral real(default), dimension(:), allocatable :: error real(default), dimension(:), allocatable :: prob procedure(integrand_interface), nopass, pointer :: integrand contains <> end type cuba_class @ %def cuba_class @ <>= type, extends (cuba_class) :: cuba_cuhre_t private integer :: key = 13 contains <> end type cuba_cuhre_t @ %def cuba_cuhre_t @ <>= type, extends (cuba_class) :: cuba_suave_t private integer :: nnew = 10000 !1000 integer :: flatness = 5 !50 contains <> end type cuba_suave_t @ %def cuba_suave_t @ <>= public :: cuba_divonne_t <>= type, extends (cuba_class) :: cuba_divonne_t private integer :: key1 = 13 integer :: key2 = 13 integer :: key3 = 13 integer :: maxpass = 2 real(default) :: border = zero real(default) :: maxchisq = 10._default real(default) :: mindeviation = .25_default integer :: ngiven = 0 integer :: ldxgiven = 0 ! real(default), dimension(ldxgiven,ngiven) :: & ! xgiven = reshape( source = [ 0.0,0.0 ], shape = [2,1]) real(default), dimension(:,:), allocatable :: xgiven ! real(default), dimension(2) :: xgiven = [1E-1_default, 5E-1_default] integer :: nextra = 0 contains <> end type cuba_divonne_t @ %def cuba_divonne_t @ <>= type, extends (cuba_class) :: cuba_vegas_t private integer :: nstart = 500 integer :: nincrease = 1000 integer :: nbatch = 1000 integer :: gridno = 0 character(len=8), pointer :: statefile => null() contains <> end type cuba_vegas_t @ %def cuba_vegas_t @ <>= procedure :: write_to_marker => cuba_write_to_marker <>= subroutine cuba_write_to_marker (this, marker, status) class(cuba_class), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("cuba_class") call marker%mark ("dim_x", this%dim_x) call marker%mark ("dim_f", this%dim_f) call marker%mark ("eps_rel", this%eps_rel) call marker%mark ("eps_abs", this%eps_abs) call marker%mark ("flags", this%flags) call marker%mark ("min_eval", this%min_eval) call marker%mark ("max_eval", this%max_eval) call marker%mark ("neval", this%neval) call marker%mark ("fail", this%fail) call marker%mark ("nregions", this%nregions) if (allocated (this%integral)) then call marker%mark ("integral", this%integral) else call marker%mark_null ("integral") end if if (allocated(this%error)) then call marker%mark ("error", this%error) else call marker%mark_null ("error") end if if (allocated (this%prob)) then call marker%mark ("prob", this%prob) else call marker%mark_null ("prob") end if call marker%mark_null ("cuba_class") end subroutine cuba_write_to_marker @ %def cuba_write_to_marker @ <>= procedure :: read_from_marker => cuba_read_from_marker <>= subroutine cuba_read_from_marker (this, marker, status) class(cuba_class), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out)::status call marker%pick_begin ("CUBA_CLASS", status=status) call marker%pick ("dim_x", this%dim_x,status) call marker%pick ("dim_f", this%dim_f,status) call marker%pick ("eps_rel", this%eps_rel,status) call marker%pick ("eps_abs", this%eps_abs,status) call marker%pick ("flags", this%flags,status) call marker%pick ("min_eval", this%min_eval,status) call marker%pick ("max_eval", this%max_eval,status) call marker%pick ("neval", this%neval,status) call marker%pick ("fail", this%fail,status) call marker%pick ("nregions", this%nregions,status) call marker%verify_nothing("integral",status) if (allocated (this%integral)) deallocate (this%integral) if (status == serialize_ok) then allocate (this%integral (this%dim_f)) call marker%pick ("integral", this%integral, status) end if call marker%verify_nothing ("error", status) if (allocated (this%error)) deallocate (this%error) if (status == serialize_ok) then allocate (this%error (this%dim_f)) call marker%pick ("error", this%error, status) end if call marker%verify_nothing ("prob", status) if (allocated (this%prob)) deallocate (this%prob) if (status == serialize_ok) then allocate (this%prob (this%dim_f)) call marker%pick ("prob", this%prob, status) end if call marker%pick_end ("cuba_class", status) end subroutine cuba_read_from_marker @ %def cuba_read_from_marker @ <>= procedure :: print_to_unit => cuba_print_to_unit <>= subroutine cuba_print_to_unit (this, unit, parents, components, peers) class(cuba_class), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers character(11) :: n write (n, '("(",I2,"(E12.4))")') this%dim_f write (unit, "(1x,A)") "Components of cuba_class:" write (unit, "(3x,A)") "Parameters:" write (unit, "(3x,A,I10)") "dim_f: ", this%dim_f write (unit, "(3x,A,I10)") "dim_x: ", this%dim_x call this%userdata%print_to_unit (unit, parents, components-1, peers) write (unit, "(3x,A,E10.4)") "eps_rel: ", this%eps_rel write (unit, "(3x,A,E10.4)") "eps_abs: ", this%eps_abs write (unit, "(3x,A,I10)") "flags: ", this%flags write (unit, "(3x,A,I10)") "seed: ", this%seed write (unit, "(3x,A,I10)") "min_eval: ", this%min_eval write (unit, "(3x,A,I10)") "max_eval: ", this%max_eval write (unit, "(3x,A)") "Results:" write (unit, "(3x,A,I10)") "neval: ", this%neval write (unit, "(3x,A,I10)") "fail: ", this%fail write (unit, "(3x,A)", advance="no") "integral: " write (unit, fmt=n) this%integral write (unit, "(3x,A)", advance="no") "error: " write (unit, fmt=n) this%error write (unit, "(3x,A)", advance="no") "prob: " write (unit, fmt=n) this%prob write (unit, "(3x,A,E10.4)") "time: ", & this%stop_time - this%start_time ! write(unit,'("time: ",E10.4)') this%run_time end subroutine cuba_print_to_unit @ %def cuba_print_to_unit @ <>= generic :: get_integral => get_integral_array, get_integral_1 procedure :: get_integral_array => cuba_get_integral_array procedure :: get_integral_1 => cuba_get_integral_1 <>= subroutine cuba_get_integral_array (this, integral) class(cuba_class) :: this real(default), intent(out), dimension(:) :: integral integral = this%integral end subroutine cuba_get_integral_array @ %def cuba_get_integral_array @ <>= subroutine cuba_get_integral_1 (this, integral) class(cuba_class) :: this real(default), intent(out) :: integral integral = this%integral(1) end subroutine cuba_get_integral_1 @ %def cuba_get_integral_1 @ <>= procedure :: copy_common => cuba_copy_common <>= subroutine cuba_copy_common (this, source) class(cuba_class), intent(out) :: this class(cuba_class), intent(in) :: source this%dim_x = source%dim_x this%dim_f = source%dim_f this%eps_rel = source%eps_rel this%eps_abs = source%eps_abs this%flags = source%flags this%min_eval = source%min_eval this%max_eval = source%max_eval call this%alloc() end subroutine cuba_copy_common @ %def cuba_copy_common @ <>= procedure :: set_common => cuba_set_common @ <>= subroutine cuba_set_common (this, dim_x, dim_f, eps_rel, eps_abs, & flags, seed, min_eval, max_eval, integrand, userdata) class(cuba_class), intent(inout) :: this integer, intent(in), optional :: dim_x, dim_f, flags, min_eval, & max_eval, seed real(default), intent(in), optional :: eps_rel,eps_abs type(transverse_mom_t), intent(in), optional :: userdata procedure(integrand_interface), optional :: integrand if (present (dim_x)) then call this%set_dim_x (dim_x) end if if (present (dim_f)) then call this%set_dim_f (dim_f) end if if (present (flags)) then this%flags = flags end if if (present (seed)) then this%seed = seed end if if (present (min_eval)) then this%min_eval = min_eval end if if (present (max_eval)) then if (max_eval < max_maxeval) then this%max_eval = max_eval else call msg_warning & ("cuba_set_common: Value of max_eval is too large.") this%max_eval = max_maxeval end if end if if (present (eps_rel)) then this%eps_rel = eps_rel end if if (present (eps_abs)) then this%eps_abs = eps_abs end if if (present (integrand)) this%integrand=>integrand if (present (userdata)) this%userdata=userdata end subroutine cuba_set_common @ %def cuba_set_common @ <>= procedure :: set_dim_f => cuba_set_dim_f <>= subroutine cuba_set_dim_f (this, new_dim_f) class(cuba_class) :: this integer, intent(in) :: new_dim_f if (new_dim_f > 0) then this%dim_f = new_dim_f call this%alloc_dim_f else call msg_error ("cuba_set_dim_f: New value for dim_f is " & // "negative. dim_f is not set.") end if end subroutine cuba_set_dim_f @ %def cuba_set_dim_f @ <>= procedure :: set_dim_x => cuba_set_dim_x <>= subroutine cuba_set_dim_x (this, new_dim_x) class(cuba_class) :: this integer, intent(in) :: new_dim_x if (new_dim_x > 0) then this%dim_x = new_dim_x else call msg_error ("cuba_set_dim_x: New value for dim_x is " & // "negative. dim_x is not set.") end if end subroutine cuba_set_dim_x @ %def cuba_set_dim_x @ <>= procedure :: reset_timer => cuba_reset_timer <>= subroutine cuba_reset_timer (this) class(cuba_class), intent(inout) :: this this%start_time = zero this%stop_time = zero this%run_time = zero end subroutine cuba_reset_timer @ %def cuba_reset_timer @ <>= procedure :: integrate_with_timer => cuba_integrate_with_timer <>= subroutine cuba_integrate_with_timer (this, integrand) class(cuba_class), intent(inout) :: this procedure(integrand_interface) :: integrand call cpu_time (this%start_time) call this%integrate (integrand) call cpu_time (this%stop_time) this%run_time = this%run_time + this%stop_time - this%start_time end subroutine cuba_integrate_with_timer @ %def cuba_integrate_with_timer @ <>= procedure :: integrate_associated => cuba_integrate_associated <>= subroutine cuba_integrate_associated (this) class(cuba_class), intent(inout) :: this call this%integrate_with_timer (this%integrand) end subroutine cuba_integrate_associated @ %def cuba_integrate_associated @ <>= generic :: integrate => integrate_nd, integrate_userdata procedure(integrate_interface), deferred :: integrate_nd procedure(integrate_userdata_interface), deferred :: integrate_userdata procedure(cuba_copy_interface), deferred :: copy @ <>= procedure :: dealloc_dim_f => cuba_dealloc_dim_f <>= subroutine cuba_dealloc_dim_f(this) class(cuba_class) :: this ! print '("cuba_dealloc_dim_f...")' if (allocated (this%integral)) then deallocate (this%integral) end if if (allocated (this%error)) then deallocate (this%error) end if if (allocated (this%prob)) then deallocate (this%prob) end if ! print '("done")' end subroutine cuba_dealloc_dim_f @ %def cuba_dealloc_dim_f @ <>= procedure :: alloc_dim_f => cuba_alloc_dim_f <>= subroutine cuba_alloc_dim_f (this) class(cuba_class) :: this call this%dealloc_dim_f () allocate (this%integral (this%dim_f)) allocate (this%error (this%dim_f)) allocate (this%prob (this%dim_f)) end subroutine cuba_alloc_dim_f @ %def cuba_alloc_dim_f @ <>= procedure :: dealloc => cuba_dealloc <>= subroutine cuba_dealloc (this) class(cuba_class) :: this call this%dealloc_dim_f end subroutine cuba_dealloc @ %def cuba_dealloc @ <>= procedure :: alloc => cuba_alloc <>= subroutine cuba_alloc (this) class(cuba_class) :: this call this%alloc_dim_f end subroutine cuba_alloc @ %def cuba_alloc @ <>= procedure :: write_to_marker => cuba_vegas_write_to_marker <>= subroutine cuba_vegas_write_to_marker (this, marker, status) class(cuba_vegas_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("cuba_vegas_t") call cuba_write_to_marker (this, marker, status) call marker%mark("nstart", this%nstart) call marker%mark("nincrease", this%nincrease) call marker%mark_null ("cuba_vegas_t") end subroutine cuba_vegas_write_to_marker @ %def cuba_vegas_write_to_marker @ <>= procedure :: read_from_marker => cuba_vegas_read_from_marker <>= subroutine cuba_vegas_read_from_marker (this, marker, status) class(cuba_vegas_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("cuba_vegas_t", status=status) call cuba_read_from_marker (this, marker, status) call marker%pick ("nstart", this%nstart, status) call marker%pick ("nincrease", this%nincrease, status) call marker%pick_end ("cuba_vegas_t", status) end subroutine cuba_vegas_read_from_marker @ %def cuba_vegas_read_from_marker @ <>= procedure :: print_to_unit => cuba_vegas_print_to_unit <>= subroutine cuba_vegas_print_to_unit(this,unit,parents,components,peers) class(cuba_vegas_t), intent(in) :: this INTEGER, INTENT(IN) :: unit integer(dik), intent(in)::parents,components,peers if (parents>0)call cuba_print_to_unit(this,unit,parents-1,components,peers) write (unit, "(1x,A)") "Components of cuba_vegas_t:" write (unit, "(3x,A,I10)") "nstart: ", this%nstart write (unit, "(3x,A,I10)") "nincrease: ", this%nincrease write (unit, "(3x,A,I10)") "nbatch: ", this%nbatch write (unit, "(3x,A,I10)") "gridno: ", this%gridno if (associated (this%statefile)) then write (unit, "(3x,A,A)") "statefile: ", this%statefile else write (unit, "(3x,A)") "statefile: not associated" end if end subroutine cuba_vegas_print_to_unit @ %def cuba_vegas_print_to_unit @ <>= procedure, nopass :: get_type => cuba_vegas_get_type <>= pure subroutine cuba_vegas_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="cuba_vegas_t") end subroutine cuba_vegas_get_type @ %def cuba_vegas_get_type @ <>= procedure :: integrate_nd => integrate_vegas <>= subroutine integrate_vegas (this, integrand) class(cuba_vegas_t), intent(inout) :: this procedure(integrand_interface) :: integrand ! print '("vegas")' ! call vegas (this%dim_x, this%dim_f, integrand, this%userdata, & ! this%eps_rel, this%eps_abs, this%flags, this%seed, & ! this%min_eval, this%max_eval, this%nstart, this%nincrease, & ! this%nbatch, this%gridno, this%statefile, this%neval, & ! this%fail, this%integral, this%error, this%prob) end subroutine integrate_vegas @ %def integrate_vegas @ <>= procedure :: integrate_userdata => integrate_vegas_userdata <>= subroutine integrate_vegas_userdata (this, integrand, userdata) class(cuba_vegas_t), intent(inout) :: this procedure(integrand_interface) :: integrand class(transverse_mom_t), intent(in) :: userdata ! print '("vegas")' ! call vegas(this%dim_x, this%dim_f, integrand, userdata, this%eps_rel, & ! this%eps_abs, this%flags, this%seed, this%min_eval, this%max_eval, & ! this%nstart, this%nincrease, this%nbatch, this%gridno, & ! this%statefile, this%neval, this%fail, this%integral, & ! this%error, this%prob) end subroutine integrate_vegas_userdata @ %def integrate_vegas_userdata @ <>= procedure :: copy => cuba_vegas_copy <>= subroutine cuba_vegas_copy (this, source) class(cuba_vegas_t), intent(out) :: this class(cuba_class), intent(in) :: source select type (source) class is (cuba_vegas_t) call this%copy_common (source) this%nstart = source%nstart this%nincrease = source%nincrease class default call msg_error ("cuba_vegas_copy: type of source is not type " & // "compatible with cuba_vegas_t.") end select end subroutine cuba_vegas_copy @ %def cuba_vegas_copy @ <>= procedure :: set_deferred => cuba_vegas_set_deferred <>= subroutine cuba_vegas_set_deferred & (this, n_start, n_increase, nbatch, gridno, statefile) class(cuba_vegas_t), intent(inout) :: this integer, intent(in), optional :: n_start, n_increase, nbatch, gridno character(len=*), intent(in), target, optional :: statefile if (present (n_start)) this%nstart = n_start if (present (n_increase)) this%nincrease = n_increase if (present (nbatch)) this%nbatch = nbatch if (present (gridno)) this%gridno = gridno if (present (statefile)) this%statefile => statefile end subroutine cuba_vegas_set_deferred @ %def cuba_vegas_set_deferred @ <>= procedure :: write_to_marker => cuba_divonne_write_to_marker <>= subroutine cuba_divonne_write_to_marker (this, marker, status) class(cuba_divonne_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("cuba_divonne_t") call cuba_write_to_marker (this, marker, status) call marker%mark ("key1", this%key1) call marker%mark ("key2", this%key2) call marker%mark ("key3", this%key3) call marker%mark ("maxpass", this%maxpass) call marker%mark ("border", this%border) call marker%mark ("maxchisq", this%maxchisq) call marker%mark ("mindeviation", this%mindeviation) call marker%mark ("ngiven", this%ngiven) call marker%mark ("ldxgiven", this%ldxgiven) call marker%mark ("nextra", this%nextra) call marker%mark ("xgiven", this%xgiven) call marker%mark_null ("cuba_divonne_t") end subroutine cuba_divonne_write_to_marker @ %def cuba_divonne_write_to_marker @ <>= procedure :: read_from_marker => cuba_divonne_read_from_marker <>= subroutine cuba_divonne_read_from_marker (this, marker, status) class(cuba_divonne_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("cuba_divonne_t", status=status) call cuba_read_from_marker (this, marker, status) call marker%pick ("key1", this%key1, status) call marker%pick ("key2", this%key2, status) call marker%pick ("key3", this%key3, status) call marker%pick ("maxpass", this%maxpass, status) call marker%pick ("border", this%border, status) call marker%pick ("maxchisq", this%maxchisq, status) call marker%pick ("mindeviation", this%mindeviation, status) call marker%pick ("ngiven", this%ngiven, status) call marker%pick ("ldxgiven", this%ldxgiven, status) call marker%pick ("nextra", this%nextra, status) if (allocated (this%xgiven)) deallocate (this%xgiven) allocate (this%xgiven (this%ldxgiven, this%ngiven)) call marker%pick ("xgiven", this%xgiven, status) call marker%pick_end ("cuba_divonne_t", status) end subroutine cuba_divonne_read_from_marker @ %def cuba_divonne_read_from_marker @ <>= procedure :: print_to_unit => cuba_divonne_print_to_unit <>= subroutine cuba_divonne_print_to_unit (this, unit, parents, components, peers) class(cuba_divonne_t), intent(in) :: this INTEGER, INTENT(IN) :: unit integer(dik), intent(in) :: parents, components, peers if (parents > 0) & call cuba_print_to_unit (this, unit, parents-1, components, peers) write (unit, "(1x,A)") "Components of cuba_divonne_t:" write (unit, "(3x,A,I10)") "key1: ", this%key1 write (unit, "(3x,A,I10)") "key2: ", this%key2 write (unit, "(3x,A,I10)") "key3: ", this%key3 write (unit, "(3x,A,I10)") "maxpass: ", this%maxpass write (unit, "(3x,A,I10)") "ngiven: ", this%ngiven write (unit, "(3x,A,I10)") "ldxgiven: ", this%ldxgiven write (unit, "(3x,A,I10)") "nextra: ", this%nextra write (unit, "(3x,A,E10.4)") "border: ", this%border write (unit, "(3x,A,E10.4)") "maxchisq: ", this%maxchisq write (unit, "(3x,A,E10.4)") "mindeviation:", this%mindeviation write (unit, "(3x,A,2(E10.4))") "xgiven: ", this%xgiven end subroutine cuba_divonne_print_to_unit @ %def cuba_divonne_print_to_unit @ <>= procedure, nopass :: get_type => cuba_divonne_get_type <>= pure subroutine cuba_divonne_get_type (type) character(:), allocatable, intent(out) :: type allocate(type, source="cuba_divonne_t") end subroutine cuba_divonne_get_type @ %def cuba_divonne_get_type @ <>= procedure :: integrate_nd => integrate_divonne <>= subroutine integrate_divonne (this, integrand) class(cuba_divonne_t), intent(inout) :: this procedure(integrand_interface) :: integrand ! call this%reset_output() ! print '("divonne")' ! call divonne(this%dim_x, this%dim_f, integrand, this%userdata, & ! this%eps_rel, this%eps_abs, this%flags, this%seed, this%min_eval, & ! this%max_eval, this%key1, this%key2, this%key3, this%maxpass, & ! this%border, this%maxchisq, this%mindeviation, this%ngiven, & ! this%ldxgiven, this%xgiven, this%nextra, & ! ! this%peakfinder, & ! 0, this%nregions, this%neval, this%fail, this%integral, & ! this%error, this%prob) end subroutine integrate_divonne @ %def integrate_divonne @ <>= procedure :: integrate_userdata => integrate_divonne_userdata <>= subroutine integrate_divonne_userdata (this, integrand, userdata) class(cuba_divonne_t), intent(inout) :: this procedure(integrand_interface) :: integrand class(transverse_mom_t), intent(in) :: userdata ! call this%reset_output() ! print '("divonne")' ! call divonne (this%dim_x, this%dim_f, integrand, userdata, & ! this%eps_rel, this%eps_abs, this%flags, this%seed, this%min_eval, & ! this%max_eval, this%key1, this%key2, this%key3, this%maxpass, & ! this%border, this%maxchisq, this%mindeviation, this%ngiven, & ! this%ldxgiven, this%xgiven, this%nextra, & ! ! this%peakfinder, & ! 0, this%nregions, this%neval, this%fail, this%integral, & ! this%error, this%prob) end subroutine integrate_divonne_userdata @ %def integrate_divonne_userdata @ <>= procedure :: copy => cuba_divonne_copy <>= subroutine cuba_divonne_copy (this, source) class(cuba_divonne_t), intent(out) :: this class(cuba_class), intent(in) :: source select type (source) class is (cuba_divonne_t) call this%copy_common(source) call this%set_deferred (source%key1, source%key2, source%key3, & source%maxpass, source%border, source%maxchisq, & source%mindeviation, source%xgiven) class default call msg_error ("cuba_divonne_copy: type of source is not " & // "type compatible with cuba_divonne_t.") end select end subroutine cuba_divonne_copy @ %def cuba_divonne_copy @ <>= procedure :: set_deferred => cuba_divonne_set_deferred <>= subroutine cuba_divonne_set_deferred (this, key1, key2, key3, maxpass, & border, maxchisq, mindeviation, xgiven, xgiven_flat) class(cuba_divonne_t) :: this integer, optional, intent(in) :: key1, key2, key3, maxpass real(default), optional, intent(in) :: border, maxchisq, mindeviation real(default), dimension(:,:), optional, intent(in) :: xgiven real(default), dimension(:), optional, intent(in) :: xgiven_flat integer, dimension(2) :: s if (present (key1)) this%key1 = key1 if (present (key2)) this%key2 = key2 if (present (key3)) this%key3 = key3 if (present (maxpass)) this%maxpass = maxpass if (present (border)) this%border = border if (present (maxchisq)) this%maxchisq = maxchisq if (present (mindeviation)) this%mindeviation = mindeviation if (present (xgiven)) then if (allocated (this%xgiven)) deallocate (this%xgiven) s = shape(xgiven) if (s(1) == this%dim_x) then allocate (this%xgiven (s(1), s(2)), source=xgiven) this%ldxgiven = s(1) this%ngiven = s(2) else call msg_error ("cuba_divonne_set_deferred: shape of xgiven " & // "is not [dim_x,:].") this%ngiven = 0 end if end if if (present (xgiven_flat)) then if (allocated (this%xgiven)) deallocate (this%xgiven) if (mod(size(xgiven_flat), this%dim_x) == 0) then this%ngiven = size(xgiven_flat) / this%dim_x this%ldxgiven = this%dim_x allocate (this%xgiven (this%ldxgiven,this%ngiven)) this%xgiven = reshape(xgiven_flat, [this%ldxgiven, this%ngiven]) else call msg_error ("cuba_divonne_set_deferred: size of xgiven_flat " & // "is no multiple of dim_x.") this%ngiven = 0 end if end if end subroutine cuba_divonne_set_deferred @ %def cuba_divonne_set_deferred @ <>= procedure :: write_to_marker => cuba_cuhre_write_to_marker <>= subroutine cuba_cuhre_write_to_marker (this, marker, status) class(cuba_cuhre_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("cuba_cuhre_t") call cuba_write_to_marker (this, marker, status) call marker%mark ("key", this%key) call marker%pick_end ("cuba_cuhre_t", status) end subroutine cuba_cuhre_write_to_marker @ %def cuba_cuhre_write_to_marker @ <>= procedure :: read_from_marker => cuba_cuhre_read_from_marker <>= subroutine cuba_cuhre_read_from_marker (this, marker, status) class(cuba_cuhre_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("cuba_cuhre_t", status=status) call cuba_read_from_marker (this, marker, status) call marker%pick ("key",this%key, status) call marker%pick_end ("cuba_cuhre_t", status) end subroutine cuba_cuhre_read_from_marker @ %def cuba_cuhre_read_from_marker @ <>= procedure :: print_to_unit => cuba_cuhre_print_to_unit <>= subroutine cuba_cuhre_print_to_unit (this, unit, parents, components, peers) class(cuba_cuhre_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers if (parents > 0) & call cuba_print_to_unit (this, unit, parents-1, components, peers) write (unit, "(1x,A)") "Components of cuba_cuhre_t:" write (unit, "(3x,A,I10)") "key: ", this%key end subroutine cuba_cuhre_print_to_unit @ %def cuba_cuhre_print_to_unit @ <>= procedure, nopass :: get_type => cuba_cuhre_get_type <>= pure subroutine cuba_cuhre_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="cuba_cuhre_t") end subroutine cuba_cuhre_get_type @ %def cuba_cuhre_get_type @ <>= procedure :: integrate_nd => integrate_cuhre <>= subroutine integrate_cuhre (this, integrand) class(cuba_cuhre_t), intent(inout) :: this procedure(integrand_interface) :: integrand ! print '("cuhre")' ! call cuhre(this%dim_x, this%dim_f, integrand, this%userdata, & ! this%eps_rel, this%eps_abs, this%flags, & ! ! this%seed, & ! this%min_eval, this%max_eval, this%key, this%nregions, & ! this%neval, this%fail, this%integral, this%error, this%prob) end subroutine integrate_cuhre @ %def integrate_cuhre @ <>= procedure :: integrate_userdata => integrate_cuhre_userdata <>= subroutine integrate_cuhre_userdata (this, integrand, userdata) class(cuba_cuhre_t), intent(inout) :: this procedure(integrand_interface) :: integrand class(transverse_mom_t), intent(in) :: userdata ! print '("cuhre")' ! call cuhre(this%dim_x, this%dim_f, integrand, userdata, this%eps_rel, & ! this%eps_abs, this%flags, & ! ! this%seed, & ! this%min_eval, this%max_eval, this%key, this%nregions, & ! this%neval, this%fail, this%integral, this%error, this%prob) end subroutine integrate_cuhre_userdata @ %def integrate_cuhre_userdata @ <>= procedure :: copy => cuba_cuhre_copy <>= subroutine cuba_cuhre_copy (this, source) class(cuba_cuhre_t), intent(out) :: this class(cuba_class), intent(in) :: source select type (source) class is (cuba_cuhre_t) call this%copy_common (source) this%key = source%key class default call msg_error ("cuba_cuhre_copy: type of source is not type " & // "compatible with cuba_cuhre_t.") end select end subroutine cuba_cuhre_copy @ %def cuba_cuhre_copy @ <>= procedure :: set_deferred => cuba_cuhre_set_deferred <>= subroutine cuba_cuhre_set_deferred (this, key) class(cuba_cuhre_t), intent(inout) :: this integer, intent(in) :: key this%key = key end subroutine cuba_cuhre_set_deferred @ %def cuba_cuhre_set_deferred @ <>= procedure :: write_to_marker => cuba_suave_write_to_marker <>= subroutine cuba_suave_write_to_marker (this, marker, status) class(cuba_suave_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("cuba_suave_t") call cuba_write_to_marker (this, marker, status) call marker%mark ("nnew", this%nnew) call marker%mark ("flatness", this%flatness) call marker%mark_null ("cuba_suave_t") end subroutine cuba_suave_write_to_marker @ %def cuba_suave_write_to_marker @ <>= procedure :: read_from_marker => cuba_suave_read_from_marker <>= subroutine cuba_suave_read_from_marker (this, marker, status) class(cuba_suave_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("cuba_suave_t", status=status) call cuba_read_from_marker (this, marker, status) call marker%pick ("nnew", this%nnew, status) call marker%pick ("flatnes", this%flatness, status) call marker%pick_end ("cuba_suave_t", status) end subroutine cuba_suave_read_from_marker @ %def cuba_suave_read_from_marker @ <>= procedure::print_to_unit=>cuba_suave_print_to_unit <>= subroutine cuba_suave_print_to_unit (this, unit, parents, components, peers) class(cuba_suave_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers if (parents > 0) & call cuba_print_to_unit (this, unit, parents-1, components, peers) write (unit, "(1x,A)") "Components of cuba_suave_t:" write (unit, "(3x,A,I10)") "nnew: ", this%nnew write (unit, "(3x,A,I10)") "flatness: ", this%flatness end subroutine cuba_suave_print_to_unit @ %def cuba_suave_print_to_unit @ <>= procedure, nopass :: get_type => cuba_suave_get_type <>= pure subroutine cuba_suave_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="cuba_suave_t") end subroutine cuba_suave_get_type @ %def cuba_suave_get_type @ <>= procedure :: integrate_nd => integrate_suave <>= subroutine integrate_suave (this, integrand) class(cuba_suave_t), intent(inout) :: this procedure(integrand_interface) :: integrand ! print '("suave")' ! call suave(this%dim_x, this%dim_f, integrand, this%userdata, & ! this%eps_rel, this%eps_abs, this%flags, this%seed, & ! this%min_eval, this%max_eval, this%nnew, this%flatness, & ! this%nregions, this%neval, this%fail, this%integral, & ! this%error, this%prob) end subroutine integrate_suave @ %def integrate_suave @ <>= procedure :: integrate_userdata => integrate_suave_userdata <>= subroutine integrate_suave_userdata (this, integrand, userdata) class(cuba_suave_t), intent(inout) :: this procedure(integrand_interface) :: integrand class(transverse_mom_t), intent(in) :: userdata ! print '("suave")' ! call suave (this%dim_x, this%dim_f, integrand, userdata, & ! this%eps_rel, this%eps_abs, this%flags, this%seed, & ! this%min_eval, this%max_eval, this%nnew, this%flatness, & ! this%nregions, this%neval, this%fail, this%integral, & ! this%error, this%prob) end subroutine integrate_suave_userdata @ %def integrate_suave_userdata @ <>= procedure :: copy => cuba_suave_copy <>= subroutine cuba_suave_copy (this, source) class(cuba_suave_t), intent(out) :: this class(cuba_class), intent(in) :: source select type (source) class is (cuba_suave_t) call this%copy_common (source) this%nnew = source%nnew this%flatness = source%flatness class default call msg_error ("cuba_suave_copy: type of source is not type " & // "compatible with cuba_suave_t.") end select end subroutine cuba_suave_copy @ %def cuba_suave_copy @ <>= interface subroutine integrand_interface (dim_x, x, dim_f, f,userdata) <> use muli_momentum integer, intent(in) :: dim_x, dim_f real(default), dimension(dim_x), intent(in) :: x real(default), dimension(dim_f), intent(out) :: f class(transverse_mom_t), intent(in) :: userdata end subroutine integrand_interface end interface @ %def integrand_interface @ <>= interface subroutine cuba_copy_interface (this, source) import :: cuba_class class(cuba_class), intent(out) :: this class(cuba_class), intent(in) :: source end subroutine cuba_copy_interface end interface @ %def cuba_copy_interface @ <>= interface subroutine ca_plain (this) import :: cuba_class class(cuba_class) :: this end subroutine ca_plain end interface @ %def ca_plain @ <>= interface subroutine integrate_interface (this, integrand) import :: cuba_class class(cuba_class), intent(inout) :: this interface subroutine integrand (dim_x, x, dim_f, f,userdata) <> use muli_momentum integer, intent(in) :: dim_x, dim_f real(default), dimension(dim_x), intent(in) :: x real(default), dimension(dim_f), intent(out) :: f class(transverse_mom_t), intent(in) :: userdata end subroutine integrand end interface end subroutine integrate_interface end interface @ %def integrate_interface @ <>= interface subroutine integrate_userdata_interface (this, integrand,userdata) use muli_momentum import :: cuba_class class(cuba_class), intent(inout) :: this interface subroutine integrand (dim_x, x, dim_f, f,userdata) <> use muli_momentum integer, intent(in) :: dim_x, dim_f real(default), dimension(dim_x), intent(in) :: x real(default), dimension(dim_f), intent(out) :: f class(transverse_mom_t), intent(in) :: userdata end subroutine integrand end interface class(transverse_mom_t), intent(in) :: userdata end subroutine integrate_userdata_interface end interface @ %def integrate_userdata_interface @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Trapezoidal integration routines} This file contains the module [["muli_trapezium"]]. The name is derived from the trapezoidal integration rule. The purpose of this module is to define a binary tree [[muli_trapezium_tree_t]] which holds a probability function in terms of trapezoidal segments. Its leaves of type [[muli_trapezium_list_t]] are connected to form a list, so you can either walk the root function back and forth or pick a certain segment in logarithmic time by walking down the tree. All nodes extend [[muli_trapezium_t]] which holds the actual values. Those are the values of the density function, the integral from this segment to the end of the integration area and a probability function calculated from these values. All values are taken at the upper "right" bound of the segment. Additionally the differences of these values to the values of the left neighbor is stored. <<[[muli_trapezium.f90]]>>= <> module muli_trapezium use, intrinsic :: iso_fortran_env, only: output_unit <> use constants use diagnostics use muli_base <> <> <> <> <> contains <> end module muli_trapezium @ %def muli_trapezium @ <>= integer, private, parameter :: value_dimension = 7 integer, private, parameter :: r_value_index = 1 integer, private, parameter :: d_value_index = 2 integer, private, parameter :: r_integral_index = 3 integer, private, parameter :: d_integral_index = 4 integer, private, parameter :: r_probability_index = 5 integer, private, parameter :: d_probability_index = 6 integer, private, parameter :: error_index = 7 @ %def value_dimension r_value_index d_value_index @ %def r_integral_index d_integral_index @ %def r_probability_index d_probability_index error_index @ <>= abstract interface subroutine muli_trapezium_append_interface (this, right) import muli_trapezium_node_class_t class(muli_trapezium_node_class_t), intent(inout), target :: this, right end subroutine muli_trapezium_append_interface end interface @ %def muli_trapezium_append_interface @ <>= abstract interface subroutine muli_trapezium_final_interface (this) import muli_trapezium_node_class_t class(muli_trapezium_node_class_t), intent(inout) :: this end subroutine muli_trapezium_final_interface end interface @ %def muli_trapezium_final_interface @ This is the base type [[muli_trapezium_t]]. Its component [[values]] has a first index is in $\left\{ 0, \ldots, \text{dim}-1 \right\}$, while the second index distingiushes between [[r_value]], [[d_value]], [[r_integral]], [[d_integral]], [[r_probability]], [[d_probability]]. <>= public :: muli_trapezium_t <>= type, extends (measure_class_t) :: muli_trapezium_t private integer :: dim = 0 real(default) :: r_position = 0 real(default) :: d_position = 0 real(default) :: measure_comp = 0 real(default), dimension(:,:), allocatable :: values contains <> end type muli_trapezium_t @ %def muli_trapezium_t @ <>= public :: muli_trapezium_node_class_t <>= type, extends (muli_trapezium_t), abstract :: muli_trapezium_node_class_t private class(muli_trapezium_node_class_t), pointer :: left => null() class(muli_trapezium_node_class_t), pointer :: right => null() ! real(default) :: criterion contains <> end type muli_trapezium_node_class_t @ %def muli_trapezium_node_class_t @ <>= public :: muli_trapezium_tree_t <>= type, extends(muli_trapezium_node_class_t) :: muli_trapezium_tree_t class(muli_trapezium_node_class_t), pointer :: down => null() contains <> end type muli_trapezium_tree_t @ %def muli_trapezium_tree_t @ <>= public :: muli_trapezium_list_t <>= type, extends (muli_trapezium_node_class_t) :: muli_trapezium_list_t contains <> end type muli_trapezium_list_t @ %def muli_trapezium_list_t @ <>= procedure :: write_to_marker => muli_trapezium_write_to_marker <>= subroutine muli_trapezium_write_to_marker (this,marker,status) class(muli_trapezium_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer::dim call marker%mark_begin ("muli_trapezium_t") call marker%mark ("dim", this%dim) call marker%mark ("r_position", this%r_position) call marker%mark ("d_position", this%d_position) if (allocated(this%values)) then call marker%mark ("values", this%values) else call marker%mark_null ("values") end if call marker%mark_end ("muli_trapezium_t") end subroutine muli_trapezium_write_to_marker @ %def muli_trapezium_write_to_marker @ <>= procedure :: read_from_marker => muli_trapezium_read_from_marker <>= subroutine muli_trapezium_read_from_marker (this,marker,status) class(muli_trapezium_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: dim call marker%pick_begin ("muli_trapezium_t", status=status) call marker%pick ("dim", this%dim,status) call marker%pick ("r_position", this%r_position, status) call marker%pick ("d_position", this%d_position, status) if (allocated (this%values)) deallocate (this%values) call marker%verify_nothing ("values", status) if (status == serialize_ok) then allocate(this%values(0:this%dim-1,7)) call marker%pick ("values",this%values, status) end if call marker%pick_end("muli_trapezium_t",status) end subroutine muli_trapezium_read_from_marker @ %def muli_trapezium_read_from_marker @ <>= procedure :: print_to_unit => muli_trapezium_print_to_unit <>= subroutine muli_trapezium_print_to_unit (this, unit, parents, components, peers) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "Components of muli_trapezium_t:" write (unit, fmt=*)"Dimension: ",this%dim write (unit,fmt=*)"Right position: ",this%r_position write (unit,fmt=*)"Position step: ",this%d_position if (allocated(this%values)) then if (components>0) then write (unit,fmt=*)"Right values: ",muli_trapezium_get_r_value_array(this) write (unit,fmt=*) "Value step: ", this%get_d_value() write (unit,fmt=*)"Right integrals: ",this%get_r_integral() write (unit,fmt=*)"Integral step: ",this%get_d_integral() write (unit,fmt=*)"Right propabilities:",this%get_r_probability() write (unit,fmt=*)"Probability step: ",this%get_d_probability() write (unit,fmt=*)"Errors: ",this%get_error() else write (unit, "(3x,A)") "Values are allocated." end if else write (unit, "(3x,A)") "Values are not allocated." end if end subroutine muli_trapezium_print_to_unit @ %def muli_trapezium_print_to_unit @ <>= procedure, nopass :: get_type => muli_trapezium_get_type <>= pure subroutine muli_trapezium_get_type (type) character(:),allocatable, intent(out) :: type allocate (type, source="muli_trapezium_t") end subroutine muli_trapezium_get_type @ %def muli_trapezium_get_type @ <>= procedure, nopass :: verify_type => muli_trapezium_verify_type <>= elemental logical function muli_trapezium_verify_type (type) result (match) character(*), intent(in) :: type match = type == "muli_trapezium_t" end function muli_trapezium_verify_type @ %def muli_trapezium_verify_type @ <>= procedure :: measure => muli_trapezium_measure <>= elemental function muli_trapezium_measure (this) class(muli_trapezium_t), intent(in) :: this real(default) :: muli_trapezium_measure muli_trapezium_measure = this%measure_comp end function muli_trapezium_measure @ %def muli_trapezium_measure @ <>= procedure :: initialize => muli_trapezium_initialize <>= subroutine muli_trapezium_initialize (this, dim, r_position, d_position) class(muli_trapezium_t), intent(inout) :: this integer, intent(in) :: dim real(default), intent(in) :: r_position, d_position integer :: dim1, dim2 this%dim = dim this%r_position = r_position this%d_position = d_position if (allocated (this%values)) deallocate (this%values) allocate (this%values(0:dim-1,value_dimension)) do dim2 = 1, value_dimension-1 do dim1 = 0, dim-1 this%values(dim1,dim2) = zero end do end do do dim1 = 0, dim-1 this%values(dim1, value_dimension) = huge(one) end do this%measure_comp = huge(one) end subroutine muli_trapezium_initialize @ %def muli_trapezium_initialize @ <>= procedure :: get_dimension => muli_trapezium_get_dimension <>= elemental function muli_trapezium_get_dimension (this) result (dim) class(muli_trapezium_t), intent(in) :: this integer :: dim dim = this%dim end function muli_trapezium_get_dimension @ %def muli_trapezium_get_dimension @ <>= procedure :: get_l_position => muli_trapezium_get_l_position <>= pure function muli_trapezium_get_l_position (this) result (pos) class(muli_trapezium_t), intent(in) :: this real(default) :: pos pos = this%r_position - this%d_position end function muli_trapezium_get_l_position @ %def muli_trapezium_get_l_position @ <>= procedure :: get_r_position => muli_trapezium_get_r_position <>= pure function muli_trapezium_get_r_position (this) result (pos) class(muli_trapezium_t), intent(in) :: this real(default) :: pos pos = this%r_position end function muli_trapezium_get_r_position @ %def muli_trapezium_get_r_position @ <>= procedure :: get_d_position => muli_trapezium_get_d_position <>= pure function muli_trapezium_get_d_position (this) result (pos) class(muli_trapezium_t), intent(in) :: this real(default) :: pos pos = this%d_position end function muli_trapezium_get_d_position @ %def muli_trapezium_get_d_position @ <>= generic :: get_l_value => get_l_value_array, get_l_value_element procedure :: get_l_value_array => muli_trapezium_get_l_value_array procedure :: get_l_value_element => muli_trapezium_get_l_value_element <>= pure function muli_trapezium_get_l_value_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values(0:this%dim-1, r_value_index) - & this%values(0:this%dim-1, d_value_index) end function muli_trapezium_get_l_value_array @ %def muli_trapezium_get_l_value_array @ <>= pure function muli_trapezium_get_l_value_element (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values(set, r_value_index) - this%values(set, d_value_index) end function muli_trapezium_get_l_value_element @ %def muli_trapezium_get_l_value_element @ <>= generic :: get_r_value => get_r_value_array, get_r_value_element procedure :: get_r_value_array => muli_trapezium_get_r_value_array procedure :: get_r_value_element => muli_trapezium_get_r_value_element @ <>= pure function muli_trapezium_get_r_value_element (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, r_value_index) end function muli_trapezium_get_r_value_element @ %def muli_trapezium_get_r_value_element @ <>= pure function muli_trapezium_get_r_value_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values(0:this%dim-1, r_value_index) end function muli_trapezium_get_r_value_array @ %def muli_trapezium_get_r_value_array @ <>= generic :: get_d_value => get_d_value_array, get_d_value_element procedure :: get_d_value_array => muli_trapezium_get_d_value_array procedure :: get_d_value_element => muli_trapezium_get_d_value_element <>= pure function muli_trapezium_get_d_value_element (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element=this%values (set, d_value_index) end function muli_trapezium_get_d_value_element @ %def muli_trapezium_get_d_value_element @ <>= pure function muli_trapezium_get_d_value_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values(0:this%dim-1, d_value_index) end function muli_trapezium_get_d_value_array @ %def muli_trapezium_get_d_value_array @ <>= generic :: get_l_integral => get_l_integral_array, get_l_integral_element procedure :: get_l_integral_array => muli_trapezium_get_l_integral_array procedure :: get_l_integral_element => muli_trapezium_get_l_integral_element <>= pure function muli_trapezium_get_l_integral_element & (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, r_integral_index) - & this%values (set, d_integral_index) end function muli_trapezium_get_l_integral_element @ %def muli_trapezium_get_l_integral_element @ <>= pure function muli_trapezium_get_l_integral_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, r_integral_index) - & this%values (0:this%dim-1, d_integral_index) end function muli_trapezium_get_l_integral_array @ %def muli_trapezium_get_l_integral_array @ <>= generic :: get_r_integral => get_r_integral_array, get_r_integral_element procedure :: get_r_integral_array => muli_trapezium_get_r_integral_array procedure :: get_r_integral_element => muli_trapezium_get_r_integral_element <>= pure function muli_trapezium_get_r_integral_element (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, r_integral_index) end function muli_trapezium_get_r_integral_element @ %def muli_trapezium_get_r_integral_element @ <>= pure function muli_trapezium_get_r_integral_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, r_integral_index) end function muli_trapezium_get_r_integral_array @ %def muli_trapezium_get_r_integral_array @ <>= generic :: get_d_integral => get_d_integral_array, get_d_integral_element procedure :: get_d_integral_array => muli_trapezium_get_d_integral_array procedure :: get_d_integral_element => muli_trapezium_get_d_integral_element <>= pure function muli_trapezium_get_d_integral_element & (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, d_integral_index) end function muli_trapezium_get_d_integral_element @ %def muli_trapezium_get_d_integral_element @ <>= pure function muli_trapezium_get_d_integral_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, d_integral_index) end function muli_trapezium_get_d_integral_array @ %def muli_trapezium_get_d_integral_array @ <>= generic :: get_l_probability => & get_l_probability_array, get_l_probability_element procedure :: get_l_probability_element => & muli_trapezium_get_l_probability_element procedure :: get_l_probability_array => & muli_trapezium_get_l_probability_array @ <>= pure function muli_trapezium_get_l_probability_element & (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, r_probability_index) - & this%values (set, d_probability_index) end function muli_trapezium_get_l_probability_element @ %def muli_trapezium_get_l_probability_element @ <>= pure function muli_trapezium_get_l_probability_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, r_probability_index) - & this%values (0:this%dim-1, d_probability_index) end function muli_trapezium_get_l_probability_array @ %def muli_trapezium_get_l_probability_array @ <>= generic :: get_r_probability => & get_r_probability_array, get_r_probability_element procedure :: get_r_probability_element => & muli_trapezium_get_r_probability_element procedure :: get_r_probability_array => & muli_trapezium_get_r_probability_array @ <>= pure function muli_trapezium_get_r_probability_element & (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, r_probability_index) end function muli_trapezium_get_r_probability_element @ %def muli_trapezium_get_r_probability_element @ <>= pure function muli_trapezium_get_r_probability_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, r_probability_index) end function muli_trapezium_get_r_probability_array @ %def muli_trapezium_get_r_probability_array @ <>= generic :: get_d_probability => & get_d_probability_array, get_d_probability_element procedure :: get_d_probability_element => & muli_trapezium_get_d_probability_element procedure :: get_d_probability_array => & muli_trapezium_get_d_probability_array <>= pure function muli_trapezium_get_d_probability_array (this) result (subarray) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: subarray subarray = this%values (0:this%dim-1, d_probability_index) end function muli_trapezium_get_d_probability_array @ %def muli_trapezium_get_d_probability_array @ <>= pure function muli_trapezium_get_d_probability_element & (this, set) result (element) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: set real(default) :: element element = this%values (set, d_probability_index) end function muli_trapezium_get_d_probability_element @ %def muli_trapezium_get_d_probability_element @ <>= procedure :: get_error => muli_trapezium_get_error <>= pure function muli_trapezium_get_error_sum (this) result (error) class(muli_trapezium_t), intent(in) :: this real(default) :: error error = sum (this%values (0:this%dim-1, error_index)) end function muli_trapezium_get_error_sum @ %def muli_trapezium_get_error_sum @ <>= procedure :: get_error_sum => muli_trapezium_get_error_sum <>= pure function muli_trapezium_get_error (this) result (error) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: error error = this%values (0:this%dim-1, error_index) end function muli_trapezium_get_error @ %def muli_trapezium_get_error @ <>= procedure :: get_integral_sum => muli_trapezium_get_integral_sum <>= pure function muli_trapezium_get_integral_sum (this) result (error) class(muli_trapezium_t), intent(in) :: this real(default) :: error error = sum (this%values (0:this%dim-1, d_integral_index)) end function muli_trapezium_get_integral_sum @ %def muli_trapezium_get_integral_sum @ <>= procedure :: get_value_at_position => muli_trapezium_get_value_at_position <>= subroutine muli_trapezium_get_value_at_position (this, pos, subarray) class(muli_trapezium_t), intent(in) :: this real(default), intent(in) :: pos real(default), dimension(this%dim), intent(out) :: subarray subarray = this%get_r_value_array() - this%get_d_value() * & this%d_position / (this%r_position-pos) end subroutine muli_trapezium_get_value_at_position @ %def muli_trapezium_get_value_at_position @ <>= procedure :: set_r_value => muli_trapezium_set_r_value <>= subroutine muli_trapezium_set_r_value (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values(0:this%dim-1, r_value_index) = subarray end subroutine muli_trapezium_set_r_value @ %def muli_trapezium_set_r_value @ <>= procedure :: set_d_value => muli_trapezium_set_d_value <>= subroutine muli_trapezium_set_d_value (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values(0:this%dim-1,d_value_index) = subarray end subroutine muli_trapezium_set_d_value @ %def muli_trapezium_set_d_value @ <>= procedure :: set_r_integral => muli_trapezium_set_r_integral <>= subroutine muli_trapezium_set_r_integral (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values(0:this%dim-1,r_integral_index) = subarray end subroutine muli_trapezium_set_r_integral @ %def muli_trapezium_set_r_integral @ <>= procedure :: set_d_integral => muli_trapezium_set_d_integral <>= subroutine muli_trapezium_set_d_integral (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values (0:this%dim-1, d_integral_index) = subarray end subroutine muli_trapezium_set_d_integral @ %def muli_trapezium_set_d_integral @ <>= procedure :: set_r_probability => muli_trapezium_set_r_probability <>= subroutine muli_trapezium_set_r_probability (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values (0:this%dim-1,r_probability_index) = subarray end subroutine muli_trapezium_set_r_probability @ %def muli_trapezium_set_r_probability @ <>= procedure :: set_d_probability => muli_trapezium_set_d_probability <>= subroutine muli_trapezium_set_d_probability (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values (0:this%dim-1,d_probability_index) = subarray end subroutine muli_trapezium_set_d_probability @ %def muli_trapezium_set_d_probability @ <>= procedure :: set_error => muli_trapezium_set_error <>= subroutine muli_trapezium_set_error (this, subarray) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in), dimension(0:this%dim-1) :: subarray this%values (0:this%dim-1, error_index) = subarray this%measure_comp = sum (subarray) end subroutine muli_trapezium_set_error @ %def muli_trapezium_set_error @ <>= procedure :: is_left_of => muli_trapezium_is_left_of <>= pure function muli_trapezium_is_left_of (this, that) result (is_left) logical :: is_left class(muli_trapezium_t), intent(in) :: this, that is_left = this%r_position <= that%r_position !-that%d_position ! if (is_left.and.that%r_position < this%r_position) then ! print *,"!" ! STOP ! end if end function muli_trapezium_is_left_of @ %def muli_trapezium_is_left_of @ <>= procedure :: includes => muli_trapezium_includes <>= elemental logical function muli_trapezium_includes & (this, dim, position, value, integral, probability) result (includes) class(muli_trapezium_t), intent(in) :: this integer, intent(in) :: dim real(default), intent(in),optional :: position, value, integral, probability includes = .true. if (present (position)) then if (this%get_l_position() > position .or. & position >= this%get_r_position()) includes = .false. end if if (present (value)) then if (this%get_l_value(dim) > value .or. value >= & this%get_r_value(dim)) includes = .false. end if if (present (integral)) then if (this%get_l_integral(dim) > integral .or. integral >= & this%get_r_integral(dim)) includes = .false. end if if (present (probability)) then if (this%get_l_probability(dim) > probability .or. & probability >= this%get_r_probability(dim)) includes = .false. end if end function muli_trapezium_includes @ %def muli_trapezium_includes @ <>= procedure :: to_node => muli_trapezium_to_node <>= subroutine muli_trapezium_to_node (this, value, list, tree) class(muli_trapezium_t), intent(in) :: this real(default), intent(in) :: value ! class(muli_trapezium_node_class_t), optional, pointer, intent(out) :: node class(muli_trapezium_list_t), optional, pointer, intent(out) :: list class(muli_trapezium_tree_t), optional, pointer, intent(out) :: tree ! if (present (node)) then ! allocate (node) ! node%dim = this%dim ! node%r_position = this%r_position ! node%d_position = this%d_position ! allocate (node%values (this%dim, value_dimension), source=this%values) ! end if if (present (list)) then allocate (list) list%dim = this%dim list%r_position = this%r_position list%d_position = this%d_position allocate (list%values (0:this%dim-1, value_dimension), source=this%values) end if if (present (tree)) then allocate (tree) tree%dim = this%dim tree%r_position = this%r_position tree%d_position = this%d_position allocate (tree%values (0:this%dim-1, value_dimension), source=this%values) end if end subroutine muli_trapezium_to_node @ %def muli_trapezium_to_node @ <>= procedure :: sum_up => muli_trapezium_sum_up <>= subroutine muli_trapezium_sum_up (this) class(muli_trapezium_t), intent(inout) :: this integer :: i if (allocated (this%values)) then do i = 1, 7 this%values (0,i) = sum (this%values (1:this%dim-1,i)) end do end if end subroutine muli_trapezium_sum_up @ %def muli_trapezium_sum_up @ <>= procedure :: approx_value => muli_trapezium_approx_value <>= pure function muli_trapezium_approx_value (this, x) result (val) ! returns the values at x class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: val real(default), intent(in) :: x val = this%get_r_value_array() + (x - this%r_position) * & this%get_d_value() / this%d_position end function muli_trapezium_approx_value @ %def muli_trapezium_approx_value_n @ This function returns the value at [[x]]. <>= procedure :: approx_value_n => muli_trapezium_approx_value_n <>= elemental function muli_trapezium_approx_value_n (this, x, n) result (val) class(muli_trapezium_t), intent(in) :: this real(default) :: val real(default), intent(in) :: x integer, intent(in) :: n val = this%get_r_value_element(n) + (x - this%r_position) * & this%get_d_value_element(n) / this%d_position end function muli_trapezium_approx_value_n @ %def muli_trapezium_approx_value_n @ This function returns the integral from [[x]] to [[r_position]]. <>= procedure :: approx_integral => muli_trapezium_approx_integral <>= pure function muli_trapezium_approx_integral (this, x) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: muli_trapezium_approx_integral real(default), intent(in) :: x muli_trapezium_approx_integral = & ! this%get_r_integral()+& ! (this%r_position-x)*this%get_r_value()+& ! (x**2-this%r_position**2)*this%get_d_integral()/(this%d_position*2D0) this%get_r_integral() + & ((this%r_position - x) * & (-this%get_d_value() * (this%r_position - x) + 2 * & this%d_position*this%get_r_value_array())) / & (2 * this%d_position) end function muli_trapezium_approx_integral @ %def muli_trapezium_approx_integral @ This function returns the integral from [[x]] to [[r_position]]. <>= procedure :: approx_integral_n => muli_trapezium_approx_integral_n <>= elemental function muli_trapezium_approx_integral_n (this, x, n) result (val) class(muli_trapezium_t), intent(in) :: this real(default) :: val real(default), intent(in) :: x integer, intent(in) :: n val = this%get_r_integral_element (n) + ((this%r_position - x) * & (-this%get_d_value_element (n) * (this%r_position - x) + 2 * & this%d_position * this%get_r_value_element (n))) / & (2 * this%d_position) end function muli_trapezium_approx_integral_n @ %def muli_trapezium_approx_integral_n @ This function returns the values at [[x]]. <>= procedure :: approx_probability => muli_trapezium_approx_probability <>= pure function muli_trapezium_approx_probability (this, x) result (prop) class(muli_trapezium_t), intent(in) :: this real(default), dimension(this%dim) :: prop real(default), intent(in) :: x prop = exp (- this%approx_integral (x)) end function muli_trapezium_approx_probability @ %def muli_trapezium_approx_probability @ This function returns the integral from [[x]] to [[r_position]]. <>= procedure :: approx_probability_n => muli_trapezium_approx_probability_n <>= elemental function muli_trapezium_approx_probability_n (this, x, n) result (val) class(muli_trapezium_t), intent(in) :: this real(default) :: val real(default), intent(in) :: x integer, intent(in) :: n val = exp (- this%approx_integral_n (x, n)) end function muli_trapezium_approx_probability_n @ %def muli_trapezium_approx_probability_n @ <>= procedure :: approx_position_by_integral => & muli_trapezium_approx_position_by_integral <>= elemental function muli_trapezium_approx_position_by_integral & (this, dim, int) result (val) class(muli_trapezium_t), intent(in) :: this real(default) :: val integer, intent(in) :: dim real(default), intent(in) :: int real(default) :: dpdv dpdv = (this%d_position / this%values (dim,d_value_index)) val = this%r_position - dpdv * (this%values (dim, r_value_index) - & sqrt (((this%values (dim, r_integral_index) - int) * two / dpdv) + & this%values (dim, r_value_index)**2)) end function muli_trapezium_approx_position_by_integral @ %def muli_trapezium_position_by_integral @ <>= ! procedure :: choose_partons => muli_trapezium_choose_partons @ @ <>= procedure :: split => muli_trapezium_split <>= subroutine muli_trapezium_split (this, c_value, c_position, new_node) class(muli_trapezium_t), intent(inout) :: this real(default), intent(in) :: c_position real(default), intent(in), dimension(this%dim) :: c_value class(muli_trapezium_t), intent(out), pointer :: new_node real(default) :: ndpr, ndpl real(default), dimension(:), allocatable :: ov, edv ndpr = this%r_position - c_position ndpl = this%d_position - ndpr allocate (ov (0:this%dim-1), source=this%get_r_value_array() - ndpr * & this%get_d_value() / this%d_position) allocate (edv (0:this%dim-1), source=c_value-ov) allocate (new_node) call new_node%initialize (dim=this%dim, r_position=c_position, & d_position=ndpl) call new_node%set_r_value (c_value) call new_node%set_d_value (this%get_d_value() + & c_value-this%get_r_value_array()) call new_node%set_d_integral (ndpl*(this%get_d_value() - & this%get_r_value_array() - c_value) / two) call new_node%set_error (abs((edv*ndpl) / two)) ! new_node%measure_comp = sum (abs((edv*ndpl) / two)) this%d_position = ndpr call this%set_d_value (this%get_r_value_array() - c_value) call this%set_d_integral (- (ndpr*(this%get_r_value_array() + c_value) / two)) call this%set_error (abs(edv*ndpr / two)) ! this%measure_comp = sum (abs(edv*ndpr / two)) ! write (*, "(1x,A)") "muli_trapezium_split: new errors:" ! write (*, "(3x,ES14.7)") this%get_error() ! write (*, "(3x,ES14.7)") new_node%get_error() ! write (*, "(3x,11(ES20.10)") new_node%get_d_integral() ! write (*, "(3x,11(ES20.10)") this%get_d_integral() end subroutine muli_trapezium_split @ %def muli_trapezium_split @ <>= procedure :: update => muli_trapezium_update <>= subroutine muli_trapezium_update (this) class(muli_trapezium_t), intent(inout) :: this real(default), dimension(:), allocatable :: integral real(default), dimension(0:this%dim-1) :: d_int !!! !!! !!! Workaround for gfortran 5.0 ICE d_int = this%get_d_integral () allocate (integral (0:this%dim-1), source=d_int) call this%set_d_integral (-this%d_position * (this%get_r_value_array() & - this%get_d_value() / 2)) call this%set_error (abs (this%get_d_integral() - integral)) ! write (*, "(3x,11(ES20.10)") this%get_d_integral() end subroutine muli_trapezium_update @ %def muli_trapezium_update @ <>= procedure :: deserialize_from_marker => & muli_trapezium_node_deserialize_from_marker <>= subroutine muli_trapezium_node_deserialize_from_marker (this, name, marker) class(muli_trapezium_node_class_t), intent(out) :: this character(*), intent(in) :: name class(marker_t), intent(inout) :: marker integer(dik) :: status class(ser_class_t), pointer :: ser allocate (muli_trapezium_tree_t :: ser) call marker%push_reference (ser) allocate (muli_trapezium_list_t::ser) call marker%push_reference (ser) call serializable_deserialize_from_marker (this, name, marker) call marker%pop_reference (ser) deallocate (ser) call marker%pop_reference (ser) deallocate (ser) end subroutine muli_trapezium_node_deserialize_from_marker @ %def muli_trapezium_node_deserialize_from_marker @ <>= procedure(muli_trapezium_append_interface), deferred :: append @ @ <>= procedure(muli_trapezium_final_interface), deferred :: finalize @ @ <>= procedure :: append => muli_trapezium_list_append <>= subroutine muli_trapezium_list_append (this, right) class(muli_trapezium_list_t), intent(inout), target :: this class(muli_trapezium_node_class_t), intent(inout), target :: right this%right => right right%left => this end subroutine muli_trapezium_list_append @ %def muli_trapezium_list_append @ <>= procedure :: nullify => muli_trapezium_node_nullify <>= subroutine muli_trapezium_node_nullify (this) class(muli_trapezium_node_class_t), intent(out) :: this nullify (this%left) nullify (this%right) end subroutine muli_trapezium_node_nullify @ %def muli_trapezium_node_nullify @ <>= procedure :: get_left => muli_trapezium_node_get_left <>= subroutine muli_trapezium_node_get_left (this, left) class(muli_trapezium_node_class_t), intent(in) :: this class(muli_trapezium_node_class_t), pointer, intent(out) :: left left => this%left end subroutine muli_trapezium_node_get_left @ %def muli_trapezium_get_left @ <>= procedure :: get_right => muli_trapezium_node_get_right <>= subroutine muli_trapezium_node_get_right (this, right) class(muli_trapezium_node_class_t), intent(in) :: this class(muli_trapezium_node_class_t), pointer, intent(out) :: right right => this%right end subroutine muli_trapezium_node_get_right @ %def muli_trapezium_get_right @ <>= procedure :: get_leftmost => muli_trapezium_node_get_leftmost <>= subroutine muli_trapezium_node_get_leftmost (this, node) class(muli_trapezium_node_class_t), intent(in) :: this class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (associated (this%left)) then node => this%left do while (associated (node%left)) node => node%left end do else nullify (node) end if end subroutine muli_trapezium_node_get_leftmost @ %def muli_trapezium_get_leftmost @ <>= procedure :: get_rightmost => muli_trapezium_node_get_rightmost <>= subroutine muli_trapezium_node_get_rightmost (this, right) class(muli_trapezium_node_class_t), intent(in) :: this class(muli_trapezium_node_class_t), pointer, intent(out) :: right if (associated (this%right)) then right => this%right do while (associated (right%right)) right => right%right end do else nullify (right) end if end subroutine muli_trapezium_node_get_rightmost @ %def muli_trapezium_node_get_rightmost @ <>= generic :: decide => decide_by_value, decide_by_position procedure :: decide_by_value => muli_trapezium_node_decide_by_value procedure :: decide_by_position => muli_trapezium_node_decide_by_position <>= subroutine muli_trapezium_node_decide_by_value (this, value, dim, record, node) class(muli_trapezium_node_class_t), intent(in) :: this real(default), intent(in) :: value integer, intent(in) :: record, dim class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (this%values (dim, record) > value) then node => this%left else node => this%right end if end subroutine muli_trapezium_node_decide_by_value @ %def muli_trapezium_node_decide_by_value @ <>= subroutine muli_trapezium_node_decide_by_position (this, position, node) class(muli_trapezium_node_class_t), intent(in) :: this real(default), intent(in) :: position class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (this%r_position > position) then node => this%left else node => this%right end if end subroutine muli_trapezium_node_decide_by_position @ %def muli_trapezium_node_decide_by_position @ <>= procedure :: decide_decreasing => muli_trapezium_node_decide_decreasing <>= subroutine muli_trapezium_node_decide_decreasing & (this, value, dim, record, node) class(muli_trapezium_node_class_t), intent(in) :: this real(default), intent(in) :: value integer, intent(in) :: record, dim class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (this%values (dim, record) <= value) then node => this%left else node => this%right end if end subroutine muli_trapezium_node_decide_decreasing @ %def muli_trapezium_node_decide_decreasing @ <>= procedure :: to_tree => muli_trapezium_node_to_tree <>= subroutine muli_trapezium_node_to_tree (this, out_tree) class(muli_trapezium_node_class_t), target, intent(in) :: this class(muli_trapezium_tree_t), intent(out) :: out_tree out_tree%left => this%left out_tree%right => this%right end subroutine muli_trapezium_node_to_tree @ %def muli_trapezium_node_to_tree @ <>= procedure :: untangle => muli_trapezium_node_untangle <>= subroutine muli_trapezium_node_untangle(this) class(muli_trapezium_node_class_t), intent(inout), target :: this if (associated (this%left)) then if (associated (this%left%right, this)) then nullify (this%left%right) nullify (this%left) end if end if end subroutine muli_trapezium_node_untangle @ %def muli_trapezium_node_untangle @ <>= procedure :: apply => muli_trapezium_node_apply <>= recursive subroutine muli_trapezium_node_apply(this,proc) class(muli_trapezium_node_class_t), intent(inout) :: this interface subroutine proc(this) import muli_trapezium_node_class_t class(muli_trapezium_node_class_t), intent(inout) :: this end subroutine proc end interface if (associated(this%right))call proc(this%right) if (associated(this%left))call proc(this%left) call proc(this) end subroutine muli_trapezium_node_apply @ %def muli_trapezium_node_apply @ <>= ! procedure :: copy => muli_trapezium_node_copy ! generic :: assignment(=) => copy ! procedure, deferred :: approx => muli_trapezium_node_approx @ @ <>= procedure :: write_to_marker => muli_trapezium_tree_write_to_marker <>= subroutine muli_trapezium_tree_write_to_marker (this, marker, status) class(muli_trapezium_tree_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(muli_trapezium_list_t), pointer :: list class(ser_class_t), pointer :: ser call marker%mark_begin ("muli_trapezium_tree_t") call this%get_left_list (list) ser => list call marker%mark_pointer ("list", ser) call marker%mark_end ("muli_trapezium_tree_t") end subroutine muli_trapezium_tree_write_to_marker @ %def muli_trapezium_tree_write_to_marker @ <>= procedure :: read_from_marker => muli_trapezium_tree_read_from_marker <>= subroutine muli_trapezium_tree_read_from_marker (this, marker, status) class(muli_trapezium_tree_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%pick_begin ("muli_trapezium_tree_t", status=status) call marker%pick_pointer ("list", ser) if (associated (ser)) then select type (ser) class is (muli_trapezium_list_t) call ser%to_tree (this) class default nullify (this%left) nullify (this%right) nullify (this%down) end select else nullify (this%left) nullify (this%right) nullify (this%down) end if call marker%pick_end ("muli_trapezium_tree_t", status) end subroutine muli_trapezium_tree_read_from_marker @ %def muli_trapezium_tree_read_from_marker @ <>= procedure :: print_to_unit => muli_trapezium_tree_print_to_unit <>= recursive subroutine muli_trapezium_tree_print_to_unit & (this, unit, parents, components, peers) class(muli_trapezium_tree_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser if (parents > 0) call muli_trapezium_print_to_unit & (this, unit, parents-1, components, peers) ser => this%down call serialize_print_peer_pointer (ser, unit, i_one, i_zero, i_one, "DOWN") if (associated (this%left)) then select type (sertmp => this%left) class is (muli_trapezium_list_t) ser => sertmp call serialize_print_peer_pointer & (ser, unit, parents, components, i_zero, "LEFT") class default call serialize_print_peer_pointer & (ser, unit, parents, components, peers, "LEFT") end select else write (unit, "(1x,A)") "Left is not associated." end if if (associated (this%right)) then select type (sertmp => this%right) class is (muli_trapezium_list_t) ser => sertmp call serialize_print_peer_pointer & (ser, unit, parents, components, i_zero, "RIGHT") class default call serialize_print_peer_pointer & (ser, unit, parents, components, peers, "RIGHT") end select else write (unit, "(1x,A)") "Right is not associated." end if end subroutine muli_trapezium_tree_print_to_unit @ %def muli_trapezium_tree_print_to_unit @ <>= procedure, nopass :: get_type => muli_trapezium_tree_get_type <>= pure subroutine muli_trapezium_tree_get_type (type) character(:),allocatable, intent(out) :: type allocate (type, source="muli_trapezium_tree_t") end subroutine muli_trapezium_tree_get_type @ %def muli_trapezium_tree_get_type @ <>= procedure, nopass :: verify_type => muli_trapezium_tree_verify_type <>= elemental logical function muli_trapezium_tree_verify_type (type) result (match) character(*), intent(in) :: type match = type == "muli_trapezium_tree_t" end function muli_trapezium_tree_verify_type @ %def muli_trapezium_tree_verify_type @ <>= procedure :: nullify => muli_trapezium_tree_nullify <>= subroutine muli_trapezium_tree_nullify (this) class(muli_trapezium_tree_t), intent(out) :: this call muli_trapezium_node_nullify (this) nullify (this%down) end subroutine muli_trapezium_tree_nullify @ %def muli_trapezium_tree_nullify @ <>= procedure :: finalize => muli_trapezium_tree_finalize <>= recursive subroutine muli_trapezium_tree_finalize (this) class(muli_trapezium_tree_t), intent(inout) :: this if (associated (this%right)) then call this%right%untangle () call this%right%finalize () deallocate (this%right) end if if (associated (this%left)) then call this%left%untangle () call this%left%finalize () deallocate (this%left) end if this%dim = 0 end subroutine muli_trapezium_tree_finalize @ %def muli_trapezium_tree_finalize @ <>= procedure :: decide_by_value => muli_trapezium_tree_decide_by_value <>= subroutine muli_trapezium_tree_decide_by_value (this, value, dim, record, node) class(muli_trapezium_tree_t), intent(in) :: this real(default), intent(in) :: value integer, intent(in) :: record, dim class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (this%down%values (dim, record) > value) then node => this%left else node => this%right end if end subroutine muli_trapezium_tree_decide_by_value @ %def muli_trapezium_tree_decide_by_value @ <>= procedure :: decide_by_position => muli_trapezium_tree_decide_by_position <>= subroutine muli_trapezium_tree_decide_by_position (this, position, node) class(muli_trapezium_tree_t), intent(in) :: this real(default), intent(in) :: position class(muli_trapezium_node_class_t), pointer, intent(out) :: node if (this%down%r_position > position) then node => this%left else node => this%right end if end subroutine muli_trapezium_tree_decide_by_position @ %def muli_trapezium_tree_decide_by_position <>= procedure :: decide_decreasing => muli_trapezium_tree_decide_decreasing <>= subroutine muli_trapezium_tree_decide_decreasing & (this, value, dim, record, node) class(muli_trapezium_tree_t), intent(in) :: this real(default), intent(in) :: value integer, intent(in) :: record, dim ! integer, save :: count=0 class(muli_trapezium_node_class_t), pointer, intent(out) :: node ! count = count + 1 if (this%down%values (dim, record) <= value) then ! print ('("Decide: value(",I2,",",I1,")=",E20.7," > ",E20.7, & ! ": go left.")'), dim, record, this%down%values(dim, record), value node => this%left else ! print ('("Decide: value(",I2,",",I1,")=",E20.7," <= ", & ! E20.7,": go right.")'), & ! dim, record, this%down%values(dim, record), value node => this%right end if end subroutine muli_trapezium_tree_decide_decreasing @ %def muli_trapezium_tree_decide_decreasing @ <>= procedure :: get_left_list => muli_trapezium_tree_get_left_list <>= subroutine muli_trapezium_tree_get_left_list (this, list) class(muli_trapezium_tree_t), intent(in) :: this class(muli_trapezium_list_t), pointer, intent(out) :: list class(muli_trapezium_node_class_t), pointer::node call this%get_leftmost (node) if (associated (node)) then select type (node) class is (muli_trapezium_list_t) list => node class default nullify (list) end select else nullify (list) end if end subroutine muli_trapezium_tree_get_left_list @ %def muli_trapezium_tree_get_left_list @ <>= procedure :: get_right_list => muli_trapezium_tree_get_right_list <>= subroutine muli_trapezium_tree_get_right_list (this, list) class(muli_trapezium_tree_t), intent(in) :: this class(muli_trapezium_list_t), pointer, intent(out) :: list class(muli_trapezium_node_class_t), pointer::node call this%get_rightmost (node) if (associated (node)) then select type (node) class is (muli_trapezium_list_t) list => node class default nullify (list) end select else nullify (list) end if end subroutine muli_trapezium_tree_get_right_list @ %def muli_trapezium_tree_get_right_list @ <>= generic :: find => find_by_value, find_by_position procedure :: find_by_value => muli_trapezium_tree_find_by_value procedure :: find_by_position => muli_trapezium_tree_find_by_position <>= subroutine muli_trapezium_tree_find_by_value (this, value, dim, record, node) class(muli_trapezium_tree_t), intent(in), target :: this real(default), intent(in) :: value integer, intent(in) :: record, dim class(muli_trapezium_node_class_t), pointer, intent(out) :: node node => this do while (.not. allocated (node%values)) call node%decide (value, dim, record, node) end do end subroutine muli_trapezium_tree_find_by_value @ %def muli_trapezium_tree_find_by_value @ <>= subroutine muli_trapezium_tree_find_by_position (this, position, node) class(muli_trapezium_tree_t), intent(in), target :: this real(default), intent(in) :: position class(muli_trapezium_node_class_t), pointer, intent(out) :: node node => this do while (.not. allocated (node%values)) call node%decide (position, node) end do end subroutine muli_trapezium_tree_find_by_position @ %def muli_trapezium_tree_find_by_position @ <>= procedure :: find_decreasing => muli_trapezium_tree_find_decreasing <>= subroutine muli_trapezium_tree_find_decreasing (this, value, dim, node) class(muli_trapezium_tree_t), intent(in), target :: this real(default), intent(in) :: value integer, intent(in) :: dim class(muli_trapezium_node_class_t), pointer, intent(out) :: node node => this do while (.not. allocated (node%values)) call node%decide_decreasing (value, dim, r_integral_index, node) end do end subroutine muli_trapezium_tree_find_decreasing @ %def muli_trapezium_tree_find_decreasing @ <>= procedure :: approx_by_integral => muli_trapezium_tree_approx_by_integral <>= subroutine muli_trapezium_tree_approx_by_integral & (this, int, dim, in_range, position, value, integral, content) class(muli_trapezium_tree_t), intent(in), target :: this real(default), intent(in) :: int integer, intent(in) :: dim logical, intent(out) :: in_range class(muli_trapezium_node_class_t), pointer, intent(out), optional :: content real(default), intent(out), optional :: position, value, integral integer :: i real(default) :: DINT !,l_prop,r_prop,d_prop real(default) :: RP, DP, RV, DV, RI !FC = gfortran class(muli_trapezium_node_class_t), pointer :: node node => this do while (.not. allocated (node%values)) call node%decide_decreasing(INT, dim, r_integral_index, node) end do if ( int<=node%values(dim,r_integral_index)-node%values(dim,d_integral_index)& &.and.& &int>=node%values(dim,r_integral_index)) then in_range=.true. ! associate(&!FC = nagfor ! &RP=>node%r_position,&!FC = nagfor ! &DP=>node%d_position,&!FC = nagfor ! &RV=>node%values(dim,r_value_index),&!FC = nagfor ! &DV=>node%values(dim,d_value_index),&!FC = nagfor ! &RI=>node%values(dim,r_integral_index))!FC = nagfor RP=node%r_position!FC = gfortran DP=node%d_position!FC = gfortran RV=node%values(dim,r_value_index)!FC = gfortran DV=node%values(dim,d_value_index)!FC = gfortran RI=node%values(dim,r_integral_index)!FC = gfortran if (present(position)) then DINT=(ri-int)*2D0*dv/dp position=rp-(dp/dv)*(rv-sqrt(dint+rv**2)) end if if (present(value)) then value=Sqrt(dp*(-2*dv*int + 2*dv*ri + dp*rv**2))/dp end if if (present(integral)) then integral=int end if if (present(content)) then content=>node end if ! end associate!FC = nagfor else in_range=.false. end if end subroutine muli_trapezium_tree_approx_by_integral @ %def muli_trapezium_tree_approx_by_integral @ <>= procedure :: approx_by_probability => muli_trapezium_tree_approx_by_probability <>= subroutine muli_trapezium_tree_approx_by_probability & (this, prop, dim, in_range, position, value, integral, content) class(muli_trapezium_tree_t), intent(in), target :: this real(default), intent(in) :: prop integer, intent(in) :: dim logical, intent(out) :: in_range class(muli_trapezium_node_class_t), pointer, intent(out), optional :: content real(default), intent(out), optional :: position, value, integral integer :: i real(default) :: int class(muli_trapezium_node_class_t), pointer :: node if (zero < prop .and. prop < one) then node => this int = -log (prop) call muli_trapezium_tree_approx_by_integral & (this, int, dim, in_range, position, value, integral, content) else in_range = .false. end if end subroutine muli_trapezium_tree_approx_by_probability @ %def muli_trapezium_tree_approx_by_probability @ <>= procedure :: to_tree => muli_trapezium_tree_to_tree <>= subroutine muli_trapezium_tree_to_tree (this, out_tree) class(muli_trapezium_tree_t), target, intent(in) :: this class(muli_trapezium_tree_t), intent(out) :: out_tree out_tree%left => this%left out_tree%right => this%right out_tree%down => this%down end subroutine muli_trapezium_tree_to_tree @ %def muli_trapezium_tree_to_tree @ <>= procedure :: append => muli_trapezium_tree_append <>= subroutine muli_trapezium_tree_append(this,right) class(muli_trapezium_tree_t), intent(inout), target :: this class(muli_trapezium_node_class_t), intent(inout), target :: right call msg_error ("muli_trapezium_tree_append: Not yet implemented.") end subroutine muli_trapezium_tree_append @ %def muli_trapezium_tree_append @ <>= procedure :: gnuplot => muli_trapezium_tree_gnuplot <>= subroutine muli_trapezium_tree_gnuplot (this, dir) class(muli_trapezium_tree_t), intent(in) :: this character(len=*), intent(in) :: dir class(muli_trapezium_list_t), pointer :: list call this%get_left_list (list) call list%gnuplot (dir) end subroutine muli_trapezium_tree_gnuplot @ %def muli_trapezium_tree_gnuplot @ <>= procedure :: write_to_marker => muli_trapezium_list_write_to_marker <>= recursive subroutine muli_trapezium_list_write_to_marker (this, marker, status) class(muli_trapezium_list_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%mark_begin ("muli_trapezium_list_t") call muli_trapezium_write_to_marker (this, marker, status) ser => this%right call marker%mark_pointer ("right", ser) call marker%mark_end ("muli_trapezium_list_t") end subroutine muli_trapezium_list_write_to_marker @ %def muli_trapezium_list_write_to_marker @ <>= procedure :: read_from_marker => muli_trapezium_list_read_from_marker <>= recursive subroutine muli_trapezium_list_read_from_marker (this, marker, status) class(muli_trapezium_list_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call msg_warning ("muli_trapezium_list_read_from_marker: " // & "You cannot deserialize a list with this subroutine.") call msg_error ("Use muli_trapezium_list_read_target_from_marker instead.") end subroutine muli_trapezium_list_read_from_marker @ %def muli_trapezium_list_read_from_marker @ <>= procedure :: read_target_from_marker => & muli_trapezium_list_read_target_from_marker <>= recursive subroutine muli_trapezium_list_read_target_from_marker & (this, marker, status) class(muli_trapezium_list_t), target, intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%pick_begin ("muli_trapezium_list_t", status=status) call muli_trapezium_read_from_marker (this, marker, status) call marker%pick_pointer ("right", ser) if (associated (ser)) then select type (ser) class is (muli_trapezium_list_t) this%right => ser ser%left => this class default nullify (this%right) call msg_error ("muli_trapezium_list_read_target_from_marker: " & // "Unexpected type for right component.") end select else nullify (this%right) end if call marker%pick_end ("muli_trapezium_list_t", status) end subroutine muli_trapezium_list_read_target_from_marker @ %def muli_trapezium_list_read_target_from_marker @ <>= procedure :: print_to_unit => muli_trapezium_list_print_to_unit <>= recursive subroutine muli_trapezium_list_print_to_unit & (this, unit, parents, components, peers) class(muli_trapezium_list_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser if (parents > 0) call muli_trapezium_print_to_unit & (this, unit, parents-1, components, peers) ser => this%left call serialize_print_peer_pointer & (ser, unit, -i_one, -i_one, -i_one, "LEFT") ser => this%right call serialize_print_peer_pointer & (ser, unit, parents, components, peers, "RIGHT") end subroutine muli_trapezium_list_print_to_unit @ %def muli_trapezium_list_print_to_unit @ <>= procedure, nopass :: get_type => muli_trapezium_list_get_type <>= pure subroutine muli_trapezium_list_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="muli_trapezium_list_t") end subroutine muli_trapezium_list_get_type @ %def muli_trapezium_list_get_type @ <>= procedure, nopass :: verify_type => muli_trapezium_list_verify_type @ <>= elemental logical function muli_trapezium_list_verify_type (type) result (match) character(*), intent(in) :: type match = type == "muli_trapezium_list_t" end function muli_trapezium_list_verify_type @ %def muli_trapezium_list_verify_type @ <>= procedure :: finalize => muli_trapezium_list_finalize @ <>= recursive subroutine muli_trapezium_list_finalize(this) class(muli_trapezium_list_t), intent(inout)::this if (associated(this%right)) then call this%right%finalize() deallocate(this%right) end if this%dim=0 end subroutine muli_trapezium_list_finalize @ %def muli_trapezium_list_finalize @ <>= generic :: insert_right => insert_right_a !, insert_right_b procedure :: insert_right_a => muli_trapezium_list_insert_right_a ! procedure :: insert_right_b => muli_trapezium_list_insert_right_b <>= subroutine muli_trapezium_list_insert_right_a (this, value, content, new_node) class(muli_trapezium_list_t), intent(inout), target :: this real(default), intent(in) :: value class(muli_trapezium_t), intent(in) :: content class(muli_trapezium_list_t), pointer, intent(out) :: new_node class(muli_trapezium_list_t), pointer :: tmp_list call content%to_node (value, list=tmp_list) if (associated (this%right)) then this%right%left => tmp_list tmp_list%right => this%right else nullify (tmp_list%right) end if this%right => tmp_list tmp_list%left => this new_node => tmp_list end subroutine muli_trapezium_list_insert_right_a @ %def muli_trapezium_list_insert_right_a @ <>= generic :: insert_left => insert_left_a !, insert_left_b procedure :: insert_left_a => muli_trapezium_list_insert_left_a ! procedure :: insert_left_b => muli_trapezium_list_insert_left_b @ <>= subroutine muli_trapezium_list_insert_left_a (this, value, content, new_node) class(muli_trapezium_list_t), intent(inout), target :: this real(default), intent(in) :: value class(muli_trapezium_t), intent(in) :: content class(muli_trapezium_list_t), pointer, intent(out) :: new_node call content%to_node (value, list=new_node) new_node%right => this if (associated (this%left)) then new_node%left => this%left this%left%right => new_node else nullify (new_node%left) end if this%left => new_node end subroutine muli_trapezium_list_insert_left_a @ %def muli_trapezium_list_insert_left_a @ <>= procedure :: to_tree => muli_trapezium_list_to_tree <>= subroutine muli_trapezium_list_to_tree (this, out_tree) class(muli_trapezium_list_t), target, intent(in) :: this class(muli_trapezium_tree_t), intent(out) :: out_tree type(muli_trapezium_tree_t),target :: do_list class(muli_trapezium_node_class_t),pointer :: this_entry,do_list_entry,node class(muli_trapezium_tree_t),pointer :: tree1,tree2 integer :: ite,log,n_deep,n_leaves n_leaves=0 this_entry => this count: do while(associated(this_entry)) n_leaves=n_leaves+1 this_entry=>this_entry%right end do count call ilog2(n_leaves,log,n_deep) this_entry => this do_list_entry => do_list deep: do ite=0,n_deep-1 allocate(tree1) tree1%down=>this_entry%right allocate(tree2) tree2%down=>this_entry tree2%left=>this_entry tree2%right=>this_entry%right tree1%left=>tree2 this_entry => this_entry%right%right do_list_entry%right=>tree1 do_list_entry=>tree1 end do deep rest: do while(associated(this_entry)) allocate(tree1) tree1%down=>this_entry tree1%left=>this_entry do_list_entry%right => tree1 do_list_entry => tree1 this_entry => this_entry%right ite=ite+1 end do rest tree: do while(ite>2) do_list_entry => do_list%right node=>do_list level: do while(associated(do_list_entry)) node%right=>do_list_entry%right node=>do_list_entry%right do_list_entry%right=>node%left node%left=>do_list_entry do_list_entry=>node%right ite=ite-1 end do level end do tree node=>do_list%right select type(node) type is (muli_trapezium_tree_t) call node%to_tree(out_tree) class default print *,"muli_trapezium_list_to_tree" print *,"unexpeted type for do_list%right" end select out_tree%right=>out_tree%right%left if (allocated(out_tree%values)) then deallocate(out_tree%values) end if deallocate(do_list%right%right) deallocate(do_list%right) end subroutine muli_trapezium_list_to_tree @ %def muli_trapezium_ @ <>= procedure :: gnuplot => muli_trapezium_list_gnuplot @ <>= subroutine muli_trapezium_list_gnuplot (this, dir) class(muli_trapezium_list_t), intent(in), target :: this character(len=*), intent(in) :: dir character(len=*), parameter :: val_file = "/value.plot" character(len=*), parameter :: int_file = "/integral.plot" character(len=*), parameter :: err_file = "/integral_error.plot" character(len=*), parameter :: pro_file = "/probability.plot" character(len=*), parameter :: den_file = "/density.plot" character(len=*), parameter :: fmt = "(ES20.10)" class(muli_trapezium_node_class_t), pointer :: list integer :: val_unit, err_unit, int_unit, pro_unit, den_unit list => this call generate_unit (val_unit, 100, 1000) open (val_unit, file = dir // val_file) call generate_unit (int_unit, 100, 1000) open (int_unit, file = dir // int_file) call generate_unit (err_unit, 100, 1000) open (err_unit, file = dir // err_file) call generate_unit (pro_unit, 100, 1000) open (pro_unit, file = dir // pro_file) call generate_unit (den_unit, 100, 1000) open (den_unit, file = dir // den_file) do while (associated (list)) ! print *,list%r_position,list%get_r_value() !!! !!! !!! gfortran 5.0.0 ICE ! write (val_unit, fmt, advance="no") list%r_position ! call write_array (val_unit, list%get_r_value_array(), fmt) ! write (int_unit,fmt,advance="no") list%r_position ! call write_array (int_unit, list%get_r_integral(), fmt) ! write (err_unit, fmt, advance="no") list%r_position ! call write_array (err_unit, list%get_error(), fmt) ! write (pro_unit, fmt, advance="no") list%r_position ! call write_array (pro_unit, list%get_r_probability(), fmt) ! write (den_unit, fmt, advance="no") list%r_position ! call write_array (den_unit, list%get_r_probability() * & ! list%get_r_value_array(), fmt) list => list%right end do close (val_unit) close (int_unit) close (err_unit) close (pro_unit) close (den_unit) contains subroutine write_array (unit, array, form) integer, intent(in) :: unit real(default), dimension(:), intent(in) :: array character(len=*), intent(in) :: form integer :: n do n = 1, size(array) write (unit, form, advance="no") array(n) flush (unit) end do write (unit, *) end subroutine write_array end subroutine muli_trapezium_list_gnuplot @ %def muli_trapezium_list_gnuplot @ <>= procedure :: integrate => muli_trapezium_list_integrate <>= subroutine muli_trapezium_list_integrate (this, integral_sum, error_sum) class(muli_trapezium_list_t), intent(in), target :: this real(default), intent(out) :: error_sum, integral_sum real(default), dimension(:), allocatable :: integral class(muli_trapezium_node_class_t), pointer :: node allocate (integral (0:this%dim-1)) call this%get_rightmost (node) integral = 0._default integral_sum = 0._default error_sum = 0._default integrate: do while (associated (node)) node%values(1,r_value_index) = sum(node%values(1:this%dim-1,r_value_index)) node%values(1,d_value_index) = sum(node%values(1:this%dim-1,d_value_index)) ! node%values (1, r_integral_index) = & ! sum (node%values (1:this%dim-1, r_integral_index)) ! node%values (1, d_integral_index) = & ! sum (node%values (1:this%dim-1, d_integral_index)) node%values(1, error_index) = sum (node%values(1:this%dim-1, error_index)) error_sum = error_sum + node%values (1, error_index) !!! !!! !!! gfortran 5.0.0 ICE ! call node%set_d_integral (node%get_d_position() * & ! (node%get_d_value() / 2 - node%get_r_value_array ())) call node%set_r_probability (exp (-integral)) call node%set_r_integral (integral) !!! !!! !!! gfortran 5.0.0 ICE ! integral = integral - node%get_d_integral() ! call node%set_d_probability (node%get_r_probability() - exp(-integral)) ! call muli_trapezium_write (node, output_unit) call node%get_left (node) end do integrate integral_sum = integral (1) end subroutine muli_trapezium_list_integrate @ %def muli_trapezium_list_integrate @ <>= procedure :: check => muli_trapezium_list_check <>= recursive subroutine muli_trapezium_list_check (this) class(muli_trapezium_list_t), intent(in),target :: this class(muli_trapezium_node_class_t), pointer :: tn, next real(default), parameter :: eps = 1E-10_default logical::test if (associated(this%right)) then next=>this%right test=(this%r_position.le.this%right%get_l_position()+eps) print *,"position check: ",test if (.not.test) then call this%print_parents() call next%print_parents() end if select type (next) class is (muli_trapezium_list_t) tn=>this print *,"structure check: ",associated(tn,next%left) print *,"class check: T" call next%check() class default print *,"class check: F" end select else print *,"end of list at ",this%r_position end if end subroutine muli_trapezium_list_check @ %def muli_trapezium_list_check @ <>= procedure :: apply => muli_trapezium_list_apply <>= recursive subroutine muli_trapezium_list_apply (this, proc) class(muli_trapezium_list_t), intent(inout) :: this interface subroutine proc (this) import muli_trapezium_node_class_t class(muli_trapezium_node_class_t), intent(inout) :: this end subroutine proc end interface if (associated (this%right))call this%right%apply (proc) call proc (this) end subroutine muli_trapezium_list_apply @ %def muli_trapezium_list_apply @ <>= ! subroutine muli_trapezium_list_insert_right_old & ! (this, value, content, new_node) ! class(muli_trapezium_list_t), intent(inout), target :: this ! real(default), intent(in) :: value ! class(muli_trapezium_t), intent(in) :: content ! class(muli_trapezium_list_t), pointer, intent(out) :: new_node ! call content%to_node (value, list=new_node) ! new_node%left => this ! if (associated (this%right)) then ! new_node%right => this%right ! this%right%left => new_node ! else ! nullify (new_node%right) ! end if ! this%right => new_node ! end subroutine muli_trapezium_list_insert_right_old @ %def muli_trapezium_list_insert_right_old @ <>= ! subroutine muli_trapezium_node_error_no_content (this) ! class(muli_trapezium_node_class_t), intent(in) :: this !! print ("muli_trapezium_node: Trying to access unallocated content.") !! call this%print() ! end subroutine muli_trapezium_node_error_no_content @ %def muli_trapezium_node_error_no_content @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Fibonacci trees} This file contains the module [[muli_fibonacci_tree]]. A fibonacci tree is a self-balancing binary tree. "Balanced" means that the depth of the left successor may differ from the depth of the right successor in any node by maximally one. The maximally unbalanced tree is maximally unbalanced in every node. So the number of leaves of a maximally unbalanced fibonacci tree of depth $n$ is precisely the $n$th fibonacci number. We use this tree for the adaptive quadrature. In every iteration of the algorithm, we have to pick the segment with largest integration error, cut it into pieces and calculate the new integration error for the pieces. A binary tree is obvioulsly a good choice for soring these segments. The problem is, that we always pick leaves from the same side of the tree. So the tree must decline at one side and grow at the other side. Sorting gets less efficient and finally most of the overall CPU time gets wasted for sorting. This tree outperforms a naive binary tree significantly in this particular job. <>= <<[[muli_fibonacci_tree.f90]]>>= module muli_fibonacci_tree <> use diagnostics use muli_base <> <> <> <> contains <> end module muli_fibonacci_tree @ %def muli_fibonacci_tree @ <>= character(*), parameter :: no_par = "edge=\noparent" character(*), parameter :: no_ret = "edge=\noreturn" character(*), parameter :: no_kid = "edge=\nochild" character(*), parameter :: le_kid = "edge=\childofleave" @ %def no_par no_ret no_kid le_kid @ <>= public :: fibonacci_node_t <>= type, extends (measure_class_t) :: fibonacci_node_t ! private class(fibonacci_node_t), pointer :: up => null() class(measure_class_t), pointer :: down => null() class(fibonacci_node_t), pointer :: left => null() class(fibonacci_node_t), pointer :: right => null() integer :: depth = 0 ! real(default) :: value contains <> end type fibonacci_node_t @ %def fibonacci_node_t @ <>= procedure :: write_to_marker => fibonacci_node_write_to_marker <>= recursive subroutine fibonacci_node_write_to_marker (this, marker, status) class(fibonacci_node_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%mark_begin ("fibonacci_node_t") ser => this%left call marker%mark_pointer ("left", ser) ser => this%right call marker%mark_pointer ("right", ser) ser => this%down call marker%mark_pointer ("down", ser) call marker%mark_end ("fibonacci_node_t") end subroutine fibonacci_node_write_to_marker @ %def fibonacci_node_wrote_to_marker @ <>= procedure :: read_from_marker => fibonacci_node_read_from_marker <>= recursive subroutine fibonacci_node_read_from_marker (this, marker, status) class(fibonacci_node_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call msg_warning ("fibonacci_node_read_from_marker: You cannot " // & "deserialize a list with this subroutine.") call msg_error ("Use fibonacci_node_read_target_from_marker instead.") end subroutine fibonacci_node_read_from_marker @ %def fibonacci_node_read_from_marker @ <>= procedure :: read_target_from_marker => fibonacci_node_read_target_from_marker <>= recursive subroutine fibonacci_node_read_target_from_marker & (this, marker, status) class(fibonacci_node_t), target, intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%pick_begin ("fibonacci_node_t", status=status) call marker%pick_pointer ("left", ser) if (status == 0) then select type (ser) class is (fibonacci_node_t) this%left => ser this%left%up => this end select end if call marker%pick_pointer ("right", ser) if (status == 0) then select type (ser) class is (fibonacci_node_t) this%right => ser this%right%up => this end select end if call marker%pick_pointer ("down", ser) if (status == 0) then select type (ser) class is (measure_class_t) this%down => ser end select end if call marker%pick_end ("fibonacci_node_t", status) end subroutine fibonacci_node_read_target_from_marker @ %def fibonacci_node_read_target_from_marker @ <>= procedure :: print_to_unit => fibonacci_node_print_to_unit <>= recursive subroutine fibonacci_node_print_to_unit & (this, unit, parents, components, peers) class(fibonacci_node_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser write (unit, "(1x,A)") "Components of fibonacci_node_t:" write (unit, "(3x,A,I22)") "Depth: ", this%depth write (unit, "(3x,A,E23.16)") "Value: ", this%measure () ser => this%up call serialize_print_comp_pointer & (ser, unit, parents, -i_one, -i_one, "Up: ") ser => this%left call serialize_print_peer_pointer & (ser, unit, parents, components, peers, "Left: ") ser => this%right call serialize_print_peer_pointer & (ser, unit, parents, components, peers, "Right: ") end subroutine fibonacci_node_print_to_unit @ %def fibonacci_node_print_to_unit @ <>= procedure, nopass :: get_type => fibonacci_node_get_type <>= pure subroutine fibonacci_node_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="fibonacci_node_t") end subroutine fibonacci_node_get_type @ %def fibonacci_node_get_type @ <>= procedure :: deserialize_from_marker => fibonacci_node_deserialize_from_marker <>= subroutine fibonacci_node_deserialize_from_marker (this, name, marker) class(fibonacci_node_t), intent(out) :: this character(*), intent(in) :: name class(marker_t), intent(inout) :: marker class(ser_class_t), pointer :: ser allocate (fibonacci_leave_t :: ser) call marker%push_reference (ser) allocate (fibonacci_node_t :: ser) call marker%push_reference (ser) call serializable_deserialize_from_marker (this, name, marker) call marker%pop_reference (ser) deallocate (ser) call marker%pop_reference (ser) deallocate (ser) end subroutine fibonacci_node_deserialize_from_marker @ %def fibonacci_node_deserialize_from_marker @ <>= procedure :: measure => fibonacci_node_measure <>= elemental function fibonacci_node_measure (this) class(fibonacci_node_t), intent(in) :: this real(default) :: fibonacci_node_measure fibonacci_node_measure = this%down%measure () end function fibonacci_node_measure @ %def fibonacci_node_measure @ <>= procedure :: deallocate_tree => fibonacci_node_deallocate_tree <>= recursive subroutine fibonacci_node_deallocate_tree (this) class(fibonacci_node_t), intent(inout) :: this if (associated (this%left)) then call this%left%deallocate_tree () deallocate (this%left) end if if (associated (this%right)) then call this%right%deallocate_tree () deallocate (this%right) end if call this%set_depth (0) end subroutine fibonacci_node_deallocate_tree @ %def fibonacci_node_deallocate_tree @ <>= procedure :: deallocate_all => fibonacci_node_deallocate_all <>= recursive subroutine fibonacci_node_deallocate_all (this) class(fibonacci_node_t), intent(inout) :: this if (associated (this%left)) then call this%left%deallocate_all () deallocate (this%left) end if if (associated (this%right)) then call this%right%deallocate_all () deallocate (this%right) end if call this%set_depth (0) end subroutine fibonacci_node_deallocate_all @ %def fibonacci_node_deallocate_all @ <>= procedure :: get_depth => fibonacci_node_get_depth <>= elemental function fibonacci_node_get_depth (this) class(fibonacci_node_t), intent(in) :: this integer :: fibonacci_node_get_depth fibonacci_node_get_depth = this%depth end function fibonacci_node_get_depth @ %def fibonacci_node_get_depth @ <>= procedure :: count_leaves => fibonacci_node_count_leaves <>= recursive subroutine fibonacci_node_count_leaves (this, n) class(fibonacci_node_t), intent(in) :: this integer, intent(out) :: n integer :: n1, n2 if (associated (this%left) .and. associated (this%right)) then call fibonacci_node_count_leaves (this%left, n1) call fibonacci_node_count_leaves (this%right, n2) n = n1 + n2 else n = 1 end if end subroutine fibonacci_node_count_leaves @ %def fibonacci_node_count_leaves @ <>= procedure,public,nopass :: is_leave => fibonacci_node_is_leave <>= elemental function fibonacci_node_is_leave () logical :: fibonacci_node_is_leave fibonacci_node_is_leave = .false. end function fibonacci_node_is_leave @ %def fibonacci_node_is_leave @ <>= procedure,public,nopass :: is_root => fibonacci_node_is_root <>= elemental function fibonacci_node_is_root () logical :: fibonacci_node_is_root fibonacci_node_is_root = .false. end function fibonacci_node_is_root @ %def fibonacci_node_is_root @ <>= procedure,public,nopass :: is_inner => fibonacci_node_is_inner <>= elemental function fibonacci_node_is_inner () logical :: fibonacci_node_is_inner fibonacci_node_is_inner = .true. end function fibonacci_node_is_inner @ %def fibonacci_node_is_inner @ <>= procedure :: write_association => fibonacci_node_write_association <>= subroutine fibonacci_node_write_association (this, that) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_node_t), intent(in), target :: that if (associated (that%left, this)) then write(*, "(A)") "This is left child of that" end if if (associated (that%right, this)) then write(*, "(A)") "This is right child of that" end if if (associated (that%up, this)) then write(*, "(A)") "This is parent of that" end if if (associated (this%left, that)) then write(*, "(A)") "That is left child of this" end if if (associated (this%right, that)) then write(*, "(A)") "That is right child of this" end if if (associated (this%up, that)) then write(*, "(A)") "That is parent of this" end if end subroutine fibonacci_node_write_association @ %def fibonacci_node_write_association @ <>= procedure :: write_contents => fibonacci_node_write_contents <>= subroutine fibonacci_node_write_contents (this, unit) class(fibonacci_node_t), intent(in), target :: this integer, intent(in), optional :: unit call this%apply_to_leaves (fibonacci_leave_write_content, unit) end subroutine fibonacci_node_write_contents @ %def fibonacci_node_write_contents @ <>= procedure :: write_values => fibonacci_node_write_values <>= subroutine fibonacci_node_write_values (this, unit) class(fibonacci_node_t), intent(in), target :: this integer, intent(in), optional :: unit call this%apply_to_leaves (fibonacci_leave_write_value, unit) end subroutine fibonacci_node_write_values @ %def fibonacci_node_write_values @ <>= procedure :: write_leaves => fibonacci_node_write_leaves <>= subroutine fibonacci_node_write_leaves (this, unit) class(fibonacci_node_t), intent(in), target :: this integer, intent(in),optional :: unit call this%apply_to_leaves (fibonacci_leave_write, unit) end subroutine fibonacci_node_write_leaves @ %def fibonacci_node_write_leaves @ <>= ! procedure :: write => fibonacci_node_write_contents @ <>= procedure :: write_pstricks => fibonacci_node_write_pstricks <>= recursive subroutine fibonacci_node_write_pstricks (this, unitnr) class(fibonacci_node_t), intent(in), target :: this integer, intent(in) :: unitnr if (associated (this%up)) then if (associated (this%up%left, this) .neqv. & (associated (this%up%right, this))) then ! write (unitnr,'("\begin{psTree}{\Toval{$",i3,"$}}")') int(this%depth) write (unitnr, & '("\begin{psTree}{\Toval{\node{",i3,"}{",f9.3,"}}}")') & int(this%depth), this%measure() else write (unitnr, & '("\begin{psTree}{\Toval[",a,"]{\node{",i3,"}{",f9.3,"}}}")') & no_ret, int(this%depth), this%measure() end if else write (unitnr, & '("\begin{psTree}{\Toval[",a,"]{\node{",i3,"}{",f9.3,"}}}")') & no_par, int(this%depth), this%measure() end if if (associated (this%left)) then call this%left%write_pstricks (unitnr) else write (unitnr,'("\Tr[edge=brokenline]{}")') end if if (associated (this%right)) then call this%right%write_pstricks (unitnr) else write (unitnr, '("\Tr[edge=brokenline]{}")') end if write (unitnr, '("\end{psTree}")') end subroutine fibonacci_node_write_pstricks @ %def fibonacci_node_write_pstricks @ <>= procedure :: copy_node => fibonacci_node_copy_node <>= subroutine fibonacci_node_copy_node (this, primitive) class(fibonacci_node_t), intent(out) :: this class(fibonacci_node_t), intent(in) :: primitive this%up => primitive%up this%left => primitive%left this%right => primitive%right this%depth = primitive%depth this%down => primitive%down end subroutine fibonacci_node_copy_node @ %def fibonacci_node_copy_node @ <>= procedure :: find_root => fibonacci_node_find_root <>= subroutine fibonacci_node_find_root (this, root) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_root_t), pointer, intent(out) :: root class(fibonacci_node_t), pointer :: node node => this do while (associated (node%up)) node => node%up end do select type (node) class is (fibonacci_root_t) root => node class default nullify (root) call msg_error ("fibonacci_node_find_root: root is not type " // & "compatible to fibonacci_root_t. Retured NULL().") end select end subroutine fibonacci_node_find_root @ %def fibonacci_node_find_root @ <>= procedure :: find_leftmost => fibonacci_node_find_leftmost <>= subroutine fibonacci_node_find_leftmost (this, leave) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave class(fibonacci_node_t), pointer :: node node => this do while (associated (node%left)) node => node%left end do select type (node) class is (fibonacci_leave_t) leave => node class default leave => null() end select end subroutine fibonacci_node_find_leftmost @ %def fibonacci_node_find_leftmost @ <>= procedure :: find_rightmost => fibonacci_node_find_rightmost <>= subroutine fibonacci_node_find_rightmost (this, leave) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave class(fibonacci_node_t), pointer :: node node => this do while (associated (node%right)) node => node%right end do select type (node) class is (fibonacci_leave_t) leave => node class default leave => null() end select end subroutine fibonacci_node_find_rightmost @ %def fibonacci_node_find_rightmost @ <>= procedure :: find => fibonacci_node_find <>= subroutine fibonacci_node_find (this, value, leave) class(fibonacci_node_t), intent(in), target :: this real(default), intent(in) :: value class(fibonacci_leave_t), pointer, intent(out) :: leave class(fibonacci_node_t), pointer :: node node => this do if (node >= value) then if (associated (node%left)) then node => node%left else call msg_warning ("fibonacci_node_find: broken tree!") leave => null() return end if else if (associated (node%right)) then node => node%right else call msg_warning ("fibonacci_node_find: broken tree!") leave => null() return end if end if select type (node) class is (fibonacci_leave_t) leave => node exit end select end do end subroutine fibonacci_node_find @ %def fibonacci_node_find @ <>= procedure :: find_left_leave => fibonacci_node_find_left_leave <>= subroutine fibonacci_node_find_left_leave (this, leave) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_node_t), pointer :: node class(fibonacci_leave_t), pointer, intent(out) :: leave nullify(leave) node => this do while (associated (node%up)) if (associated (node%up%right, node)) then node => node%up%left do while (associated (node%right)) node => node%right end do select type (node) class is (fibonacci_leave_t) leave => node end select exit end if node => node%up end do end subroutine fibonacci_node_find_left_leave @ %def fibonacci_node_find_left_leave @ <>= procedure :: find_right_leave => fibonacci_node_find_right_leave <>= subroutine fibonacci_node_find_right_leave (this, leave) class(fibonacci_node_t), intent(in), target :: this class(fibonacci_node_t), pointer :: node class(fibonacci_leave_t), pointer, intent(out) :: leave nullify (leave) node => this do while (associated (node%up)) if (associated (node%up%left, node)) then node => node%up%right do while (associated (node%left)) node => node%left end do select type (node) class is (fibonacci_leave_t) leave => node end select exit end if node => node%up end do end subroutine fibonacci_node_find_right_leave @ %def fibonacci_node_find_right_leave @ <>= procedure :: apply_to_leaves => fibonacci_node_apply_to_leaves <>= recursive subroutine fibonacci_node_apply_to_leaves (node, func, unit) class(fibonacci_node_t), intent(in), target :: node interface subroutine func (this, unit) import fibonacci_leave_t class(fibonacci_leave_t), intent(in), target :: this integer, intent(in), optional :: unit end subroutine func end interface integer, intent(in), optional :: unit select type (node) class is (fibonacci_leave_t) call func (node, unit) class default call node%left%apply_to_leaves (func, unit) call node%right%apply_to_leaves (func, unit) end select end subroutine fibonacci_node_apply_to_leaves @ %def fibonacci_node_apply_to_leaves @ <>= procedure :: apply_to_leaves_rl => fibonacci_node_apply_to_leaves_rl <>= recursive subroutine fibonacci_node_apply_to_leaves_rl (node, func, unit) class(fibonacci_node_t), intent(in), target :: node interface subroutine func (this, unit) import fibonacci_leave_t class(fibonacci_leave_t), intent(in), target :: this integer, intent(in), optional :: unit end subroutine func end interface integer, intent(in), optional :: unit select type (node) class is (fibonacci_leave_t) call func (node, unit) class default call node%right%apply_to_leaves_rl (func, unit) call node%left%apply_to_leaves_rl (func, unit) end select end subroutine fibonacci_node_apply_to_leaves_rl @ %def fibonacci_node_apply_to_leaves_rl @ <>= procedure :: set_depth => fibonacci_node_set_depth @ <>= subroutine fibonacci_node_set_depth (this, depth) class(fibonacci_node_t), intent(inout) :: this integer, intent(in) :: depth this%depth = depth end subroutine fibonacci_node_set_depth @ %def fibonacci_node_set_depth @ <>= procedure :: append_left => fibonacci_node_append_left <>= subroutine fibonacci_node_append_left(this,new_branch) class(fibonacci_node_t),target :: this class(fibonacci_node_t),target :: new_branch this%left => new_branch new_branch%up => this end subroutine fibonacci_node_append_left @ %def fibonacci_node_append_left @ <>= procedure :: append_right => fibonacci_node_append_right <>= subroutine fibonacci_node_append_right (this, new_branch) class(fibonacci_node_t), intent(inout), target :: this class(fibonacci_node_t), target :: new_branch this%right => new_branch new_branch%up => this end subroutine fibonacci_node_append_right @ %def fibonacci_node_append_right @ <>= procedure :: replace => fibonacci_node_replace <>= subroutine fibonacci_node_replace (this, old_node) class(fibonacci_node_t), intent(inout), target :: this class(fibonacci_node_t), target :: old_node if (associated (old_node%up)) then if (old_node%is_left_child ()) then old_node%up%left => this else if (old_node%is_right_child ()) then old_node%up%right => this end if end if this%up => old_node%up else nullify (this%up) end if end subroutine fibonacci_node_replace @ %def fibonacci_node_replace <>= procedure :: swap => fibonacci_node_swap_nodes <>= subroutine fibonacci_node_swap_nodes (left, right) class(fibonacci_node_t), target, intent(inout) :: left, right class(fibonacci_node_t), pointer :: left_left, right_right class(measure_class_t), pointer::down ! swap branches left_left => left%left right_right => right%right left%left => right%right right%right => left_left ! repair up components right_right%up => left left_left%up => right ! repair down components down => left%down left%down => right%down right%down => down end subroutine fibonacci_node_swap_nodes ! subroutine fibonacci_node_swap_nodes (this, that) ! class(fibonacci_node_t),target :: this ! class(fibonacci_node_t), pointer, intent(in) :: that ! class(fibonacci_node_t), pointer :: par_i, par_a ! par_i => this%up ! par_a => that%up ! if (associated (par_i%left, this)) then ! par_i%left => that ! else ! par_i%right => that ! end if ! if (associated (par_a%left, that)) then ! par_a%left => this ! else ! par_a%right => this ! end if ! this%up => par_a ! that%up => par_i ! end subroutine fibonacci_node_swap_nodes @ <>= procedure :: flip => fibonacci_node_flip_children <>= subroutine fibonacci_node_flip_children (this) class(fibonacci_node_t), intent(inout) :: this class(fibonacci_node_t), pointer :: child child => this%left this%left => this%right this%right => child end subroutine fibonacci_node_flip_children @ %def fibonacci_node_flip_children @ <>= procedure :: rip => fibonacci_node_rip <>= subroutine fibonacci_node_rip (this) class(fibonacci_node_t), intent(inout), target :: this if (this%is_left_child ()) then nullify (this%up%left) end if if (this%is_right_child ()) then nullify (this%up%right) end if nullify (this%up) end subroutine fibonacci_node_rip @ %def fibonacci_node_rip @ <>= procedure :: remove_and_keep_parent => fibonacci_node_remove_and_keep_parent <>= subroutine fibonacci_node_remove_and_keep_parent (this, pa) class(fibonacci_node_t), intent(inout), target :: this class(fibonacci_node_t), intent(out), pointer :: pa class(fibonacci_node_t), pointer :: twin if (.not. (this%is_root ())) then pa => this%up if (this%is_left_child ()) then twin => pa%right else twin => pa%left end if twin%up => pa%up if (associated (twin%left)) then twin%left%up => pa end if if (associated (twin%right)) then twin%right%up => pa end if call pa%copy_node (twin) select type (pa) class is (fibonacci_root_t) call pa%set_leftmost () call pa%set_rightmost () end select if (associated (this%right)) then this%right%left => this%left end if if (associated (this%left)) then this%left%right => this%right end if nullify (this%left) nullify (this%right) nullify (this%up) deallocate (twin) else pa => this end if end subroutine fibonacci_node_remove_and_keep_parent @ %def fibonacci_node_remove_and_keep_parent @ <>= procedure :: remove_and_keep_twin => fibonacci_node_remove_and_keep_twin <>= subroutine fibonacci_node_remove_and_keep_twin (this, twin) class(fibonacci_node_t), intent(inout), target :: this class(fibonacci_node_t), intent(out), pointer :: twin class(fibonacci_node_t), pointer :: pa if (.not. (this%is_root ())) then pa => this%up if (.not. pa%is_root ()) then if (this%is_left_child ()) then twin => pa%right else twin => pa%left end if if (pa%is_left_child ()) then pa%up%left => twin else pa%up%right => twin end if end if twin%up => pa%up if (associated (this%right)) then this%right%left => this%left end if if (associated (this%left)) then this%left%right => this%right end if nullify (this%left) nullify (this%right) nullify (this%up) deallocate (pa) end if end subroutine fibonacci_node_remove_and_keep_twin @ %def fibonacci_node_remove_and_keep_twin @ <>= procedure :: rotate_left => fibonacci_node_rotate_left <>= subroutine fibonacci_node_rotate_left (this) class(fibonacci_node_t), intent(inout), target :: this call this%swap (this%right) call this%right%flip () call this%right%update_depth_unsave () call this%flip () ! value = this%value ! this%value = this%left%value ! this%left%value = value end subroutine fibonacci_node_rotate_left @ %def fibonacci_node_rotate_left @ <>= procedure :: rotate_right => fibonacci_node_rotate_right <>= subroutine fibonacci_node_rotate_right (this) class(fibonacci_node_t), intent(inout), target :: this call this%left%swap (this) call this%left%flip () call this%left%update_depth_unsave () call this%flip () ! value = this%value ! this%value = this%right%value ! this%right%value = value end subroutine fibonacci_node_rotate_right @ %def fibonacci_node_rotate_right @ <>= procedure :: rotate => fibonacci_node_rotate <>= subroutine fibonacci_node_rotate (this) class(fibonacci_node_t), intent(inout), target :: this if (this%is_left_short ()) then call this%rotate_left () else if (this%is_right_short ()) then call this%rotate_right () end if end if end subroutine fibonacci_node_rotate @ %def fibonacci_node_rotate @ <>= procedure :: balance_node => fibonacci_node_balance_node <>= subroutine fibonacci_node_balance_node (this, changed) class(fibonacci_node_t), intent(inout), target :: this logical, intent(out) :: changed changed = .false. if (this%is_left_too_short ()) then if (this%right%is_right_short ()) then call this%right%rotate_right end if call this%rotate_left () changed = .true. else if (this%is_right_too_short ()) then if (this%left%is_left_short ()) then call this%left%rotate_left end if call this%rotate_right () changed = .true. end if end if end subroutine fibonacci_node_balance_node @ %def fibonacci_node_balance_node @ <>= procedure :: update_depth_save => fibonacci_node_update_depth_save @ <>= subroutine fibonacci_node_update_depth_save (this, updated) class(fibonacci_node_t), intent(inout) :: this logical, intent(out) :: updated integer :: left, right, new_depth if (associated (this%left)) then left = this%left%depth + 1 else left = -1 end if if (associated (this%right)) then right = this%right%depth + 1 else right = -1 end if new_depth = max(left, right) if (this%depth == new_depth) then updated = .false. else this%depth = new_depth updated = .true. end if end subroutine fibonacci_node_update_depth_save @ %def fibonacci_node_update_depth_save @ <>= procedure :: update_depth_unsave => fibonacci_node_update_depth_unsave @ <>= subroutine fibonacci_node_update_depth_unsave (this) class(fibonacci_node_t), intent(inout) :: this this%depth = max (this%left%depth+1, this%right%depth+1) end subroutine fibonacci_node_update_depth_unsave @ %def fibonacci_node_update_depth_unsave @ <>= procedure :: repair => fibonacci_node_repair <>= subroutine fibonacci_node_repair (this) class(fibonacci_node_t), intent(inout), target :: this class(fibonacci_node_t), pointer:: node logical :: new_depth, new_balance new_depth = .true. node => this do while ((new_depth .or. new_balance) .and. (associated (node))) call node%balance_node (new_balance) call node%update_depth_save (new_depth) node => node%up end do end subroutine fibonacci_node_repair @ %def fibonacci_node_repair @ <>= procedure :: is_left_short => fibonacci_node_is_left_short <>= elemental logical function fibonacci_node_is_left_short(this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_left_short = (this%left%depth < this%right%depth) end function fibonacci_node_is_left_short @ %def fibonacci_node_is_left_short @ <>= procedure :: is_right_short => fibonacci_node_is_right_short @ <>= elemental logical function fibonacci_node_is_right_short (this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_right_short = (this%right%depth < this%left%depth) end function fibonacci_node_is_right_short @ %def fibonacci_node_is_right_short @ <>= procedure :: is_unbalanced => fibonacci_node_is_unbalanced <>= elemental logical function fibonacci_node_is_unbalanced (this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_unbalanced = & (this%is_left_short () .or. this%is_right_short ()) end function fibonacci_node_is_unbalanced @ %def fibonacci_node_is_unbalanced @ <>= procedure :: is_left_too_short => fibonacci_node_is_left_too_short <>= elemental logical function fibonacci_node_is_left_too_short (this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_left_too_short = (this%left%depth+1 < this%right%depth) end function fibonacci_node_is_left_too_short @ %def fibonacci_node_is_left_too_short @ <>= procedure :: is_right_too_short => fibonacci_node_is_right_too_short <>= elemental logical function fibonacci_node_is_right_too_short (this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_right_too_short = (this%right%depth+1 < this%left%depth) end function fibonacci_node_is_right_too_short @ %def fibonacci_node_is_right_too_short @ <>= procedure :: is_too_unbalanced => fibonacci_node_is_too_unbalanced <>= elemental logical function fibonacci_node_is_too_unbalanced (this) class(fibonacci_node_t), intent(in) :: this fibonacci_node_is_too_unbalanced = & (this%is_left_too_short() .or. this%is_right_too_short()) end function fibonacci_node_is_too_unbalanced @ %def fibonacci_node_is_too_unbalanced @ <>= procedure :: is_left_child => fibonacci_node_is_left_child <>= elemental logical function fibonacci_node_is_left_child (this) class(fibonacci_node_t), intent(in),target :: this fibonacci_node_is_left_child = associated (this%up%left, this) end function fibonacci_node_is_left_child @ %def fibonacci_node_is_left_child @ <>= procedure :: is_right_child => fibonacci_node_is_right_child <>= elemental logical function fibonacci_node_is_right_child (this) class(fibonacci_node_t), intent(in),target :: this fibonacci_node_is_right_child = associated (this%up%right, this) end function fibonacci_node_is_right_child @ %def fibonacci_node_is_right_child @ <>= ! user ! node ! tree ! procedure :: balance ! procedure :: sort ! procedure :: merge ! procedure :: split @ <>= public :: fibonacci_leave_t <>= type, extends (fibonacci_node_t) :: fibonacci_leave_t ! class(measure_class_t), pointer :: content contains <> end type fibonacci_leave_t @ %def fibonacci_leave_t @ <>= ! procedure :: write_to_marker => fibonacci_leave_write_to_marker ! procedure :: read_from_marker => fibonacci_leave_read_from_marker procedure :: print_to_unit => fibonacci_leave_print_to_unit <>= subroutine fibonacci_leave_print_to_unit & (this, unit, parents, components, peers) class(fibonacci_leave_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser if (parents > 0) call fibonacci_node_print_to_unit & (this, unit, parents-i_one, components, -i_one) write(unit, "(A)") "Components of fibonacci_leave_t:" ser => this%down call serialize_print_comp_pointer & (ser, unit, parents, components, peers, "Content:") end subroutine fibonacci_leave_print_to_unit @ %def fibonacci_leave_print_to_unit @ <>= procedure, nopass :: get_type => fibonacci_leave_get_type <>= pure subroutine fibonacci_leave_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="fibonacci_leave_t") end subroutine fibonacci_leave_get_type @ %def fibonacci_leave_get_type @ <>= procedure :: deallocate_all => fibonacci_leave_deallocate_all <>= subroutine fibonacci_leave_deallocate_all (this) class(fibonacci_leave_t), intent(inout) :: this if (associated (this%down)) then deallocate (this%down) end if end subroutine fibonacci_leave_deallocate_all @ %def fibonacci_leave_deallocate_all @ <>= procedure :: pick => fibonacci_leave_pick @ <>= subroutine fibonacci_leave_pick (this) class(fibonacci_leave_t), target, intent(inout) :: this class(fibonacci_node_t), pointer :: other class(fibonacci_root_t), pointer :: root ! call this%up%print_parents() call this%find_root (root) if (associated (this%up, root)) then if (this%up%depth < 2) then call msg_error ("fibonacci_leave_pick: Cannot pick leave. " // & "Tree must have at least three leaves.") else call this%remove_and_keep_parent (other) call other%repair () end if else call this%remove_and_keep_twin (other) call other%up%repair () end if if (associated (root%leftmost, this)) call root%set_leftmost () if (associated (root%rightmost, this)) call root%set_rightmost () end subroutine fibonacci_leave_pick @ %def fibonacci_leave_pick @ <>= procedure :: get_left => fibonacci_leave_get_left @ <>= subroutine fibonacci_leave_get_left (this, leave) class(fibonacci_leave_t), intent(in) :: this class(fibonacci_leave_t), intent(out), pointer :: leave class(fibonacci_node_t), pointer :: node node => this%left select type (node) class is (fibonacci_leave_t) leave => node end select end subroutine fibonacci_leave_get_left @ %def fibonacci_leave_get_left @ <>= procedure :: get_right => fibonacci_leave_get_right <>= subroutine fibonacci_leave_get_right (this, leave) class(fibonacci_leave_t), intent(in) :: this class(fibonacci_leave_t), intent(out), pointer :: leave class(fibonacci_node_t), pointer :: node ! print *,"fibonacci_leave_get_right" ! call this%down%print_little if (associated (this%right)) then node => this%right ! call node%down%print_little select type (node) class is (fibonacci_leave_t) leave => node end select else ! print *,"no right leave" nullify (leave) end if end subroutine fibonacci_leave_get_right @ %def fibonacci_leave_get_right @ <>= procedure :: write_pstricks => fibonacci_leave_write_pstricks <>= subroutine fibonacci_leave_write_pstricks (this, unitnr) class(fibonacci_leave_t), intent(in), target :: this integer, intent(in) :: unitnr write (unitnr, "(A,I3,A,F9.3,A)") & "\begin{psTree}{\Toval[linecolor=green]{\node{", this%depth, "}{", & this%measure(), "}}}" if (associated (this%left)) then write (unitnr, "(A,A,A)") "\Tr[", le_kid, "]{}" end if if (associated (this%right)) then write (unitnr, "(A,A,A)") "\Tr[", le_kid, "]{}" end if write (unitnr, "(A)") "\end{psTree}" end subroutine fibonacci_leave_write_pstricks @ %def fibonacci_leave_write_pstricks @ <>= procedure :: copy_content => fibonacci_leave_copy_content <>= subroutine fibonacci_leave_copy_content (this, content) class(fibonacci_leave_t) :: this class(measure_class_t), intent(in) :: content allocate (this%down, source=content) end subroutine fibonacci_leave_copy_content @ %def fibonacci_leave_copy_content @ <>= procedure :: set_content => fibonacci_leave_set_content <>= subroutine fibonacci_leave_set_content (this, content) class(fibonacci_leave_t) :: this class(measure_class_t), target, intent(in) :: content this%down => content end subroutine fibonacci_leave_set_content @ %def fibonacci_leave_set_content @ <>= procedure :: get_content => fibonacci_leave_get_content <>= subroutine fibonacci_leave_get_content (this, content) class(fibonacci_leave_t), intent(in) :: this class(measure_class_t), pointer :: content content => this%down end subroutine fibonacci_leave_get_content @ %def fibonacci_leave_get_content @ <>= procedure, nopass :: is_inner => fibonacci_leave_is_inner <>= elemental logical function fibonacci_leave_is_inner () fibonacci_leave_is_inner = .false. end function fibonacci_leave_is_inner @ %def fibonacci_leave_is_inner @ <>= procedure, nopass :: is_leave => fibonacci_leave_is_leave <>= elemental logical function fibonacci_leave_is_leave () fibonacci_leave_is_leave = .true. end function fibonacci_leave_is_leave @ %def fibonacci_leave_is_leave @ <>= procedure :: insert_leave_by_node => fibonacci_leave_insert_leave_by_node <>= subroutine fibonacci_leave_insert_leave_by_node (this, new_leave) class(fibonacci_leave_t), target, intent(inout) :: this,new_leave class(fibonacci_node_t), pointer :: parent, new_node parent => this%up !print *, associated (this%left), associated (this%right) if (this < new_leave) then call fibonacci_node_spawn (new_node, this, new_leave, this%left, this%right) ! print *,"Repair! ",this%measure(),new_leave%measure() else call fibonacci_node_spawn (new_node, new_leave, this, this%left, this%right) end if if (associated (parent%left, this)) then call parent%append_left (new_node) else call parent%append_right (new_node) end if call parent%repair () end subroutine fibonacci_leave_insert_leave_by_node @ %def fibonacci_leave_insert_leave_by_node @ <>= procedure :: is_left_short => fibonacci_leave_is_left_short <>= elemental logical function fibonacci_leave_is_left_short (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_left_short = .false. end function fibonacci_leave_is_left_short @ %def fibonacci_leave_is_left_short @ <>= procedure :: is_right_short => fibonacci_leave_is_right_short <>= elemental logical function fibonacci_leave_is_right_short (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_right_short = .false. end function fibonacci_leave_is_right_short @ %def fibonacci_leave_is_right_short @ <>= procedure :: is_unbalanced => fibonacci_leave_is_unbalanced <>= elemental logical function fibonacci_leave_is_unbalanced (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_unbalanced = .false. end function fibonacci_leave_is_unbalanced @ %def fibonacci_leave_is_unbalanced @ <>= procedure :: is_left_too_short => fibonacci_leave_is_left_too_short <>= elemental logical function fibonacci_leave_is_left_too_short (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_left_too_short = .false. end function fibonacci_leave_is_left_too_short @ %def fibonacci_leave_is_left_too_short @ <>= procedure :: is_right_too_short => fibonacci_leave_is_right_too_short <>= elemental logical function fibonacci_leave_is_right_too_short (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_right_too_short = .false. end function fibonacci_leave_is_right_too_short @ %def fibonacci_leave_is_right_too_short @ <>= procedure :: is_too_unbalanced => fibonacci_leave_is_too_unbalanced <>= elemental logical function fibonacci_leave_is_too_unbalanced (this) class(fibonacci_leave_t), intent(in) :: this fibonacci_leave_is_too_unbalanced = .false. end function fibonacci_leave_is_too_unbalanced @ %def fibonacci_leave_is_too_unbalanced @ <>= public :: fibonacci_root_t <>= type, extends (fibonacci_node_t) :: fibonacci_root_t logical::is_valid_c=.false. class(fibonacci_leave_t),pointer :: leftmost => null() class(fibonacci_leave_t),pointer :: rightmost => null() contains <> procedure :: is_left_child => fibonacci_root_is_left_child procedure :: is_right_child => fibonacci_root_is_right_child end type fibonacci_root_t @ %def fibonacci_root_t @ <>= procedure :: write_to_marker => fibonacci_root_write_to_marker <>= subroutine fibonacci_root_write_to_marker (this, marker, status) class(fibonacci_root_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status ! call marker%mark_begin ("fibonacci_root_t") call fibonacci_node_write_to_marker (this, marker, status) ! marker%mark_end ("fibonacci_root_t") end subroutine fibonacci_root_write_to_marker <>= procedure :: read_target_from_marker => fibonacci_root_read_target_from_marker <>= subroutine fibonacci_root_read_target_from_marker (this, marker, status) class(fibonacci_root_t), target, intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status ! call marker%pick_begin ("fibonacci_root_t", status) call fibonacci_node_read_from_marker (this, marker, status) call this%find_leftmost (this%leftmost) call this%find_rightmost (this%rightmost) ! call marker%pick_end ("fibonacci_root_t", status) end subroutine fibonacci_root_read_target_from_marker @ %def fibonacci_root_read_target_from_marker @ <>= procedure :: print_to_unit => fibonacci_root_print_to_unit <>= subroutine fibonacci_root_print_to_unit (this, unit, parents, components, peers) class(fibonacci_root_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser if (parents > 0) call fibonacci_node_print_to_unit & (this, unit, parents-1, components, peers) write (unit, "(A)") "Components of fibonacci_root_t:" ser => this%leftmost call serialize_print_peer_pointer & (ser, unit, parents, components, min(peers, i_one), "Leftmost: ") ser => this%rightmost call serialize_print_peer_pointer & (ser, unit, parents, components, min(peers, i_one), "Rightmost:") end subroutine fibonacci_root_print_to_unit @ %def fibonacci_root_print_to_unit @ <>= elemental logical function fibonacci_root_is_left_child (this) class(fibonacci_root_t),target, intent(in) :: this fibonacci_root_is_left_child = .false. end function fibonacci_root_is_left_child @ %def fibonacci_root_is_left_child @ <>= elemental logical function fibonacci_root_is_right_child (this) class(fibonacci_root_t),target, intent(in) :: this fibonacci_root_is_right_child = .false. end function fibonacci_root_is_right_child @ %def fibonacci_root_is_right_child @ <>= procedure, nopass :: get_type => fibonacci_root_get_type @ <>= pure subroutine fibonacci_root_get_type (type) character(:),allocatable, intent(out) :: type allocate (type, source="fibonacci_root_t") end subroutine fibonacci_root_get_type @ %def fibonacci_root_get_type @ <>= procedure :: get_leftmost=>fibonacci_root_get_leftmost <>= subroutine fibonacci_root_get_leftmost (this, leftmost) class(fibonacci_root_t), intent(in) :: this class(fibonacci_leave_t), pointer :: leftmost leftmost => this%leftmost end subroutine fibonacci_root_get_leftmost @ %def fibonacci_root_get_leftmost @ <>= procedure :: get_rightmost=>fibonacci_root_get_rightmost <>= subroutine fibonacci_root_get_rightmost (this, rightmost) class(fibonacci_root_t), intent(in) :: this class(fibonacci_leave_t),pointer :: rightmost rightmost => this%rightmost end subroutine fibonacci_root_get_rightmost @ %def fibonacci_root_get_rightmost @ <>= procedure, nopass :: is_root => fibonacci_root_is_root <>= elemental function fibonacci_root_is_root () logical::fibonacci_root_is_root fibonacci_root_is_root = .true. end function fibonacci_root_is_root @ %def fibonacci_root_is_root @ <>= procedure, nopass :: is_inner => fibonacci_root_is_inner <>= elemental function fibonacci_root_is_inner () logical::fibonacci_root_is_inner fibonacci_root_is_inner = .false. end function fibonacci_root_is_inner @ %def fibonacci_root_is_inner @ <>= procedure :: is_valid => fibonacci_root_is_valid <>= elemental function fibonacci_root_is_valid (this) class(fibonacci_root_t), intent(in) :: this logical :: fibonacci_root_is_valid fibonacci_root_is_valid = this%is_valid_c end function fibonacci_root_is_valid @ %def fibonacci_root_is_valid @ <>= procedure :: count_leaves => fibonacci_root_count_leaves <>= subroutine fibonacci_root_count_leaves (this, n) class(fibonacci_root_t), intent(in) :: this integer, intent(out) :: n n = 0 call fibonacci_node_count_leaves (this, n) end subroutine fibonacci_root_count_leaves @ %def fibonacci_root_count_leaves @ <>= procedure :: write_pstricks => fibonacci_root_write_pstricks <>= subroutine fibonacci_root_write_pstricks (this, unitnr) class(fibonacci_root_t), intent(in), target :: this integer, intent(in) :: unitnr logical :: is_opened character :: is_sequential, is_formatted, is_writeable print *,"pstricks" inquire (unitnr, opened=is_opened, sequential=is_sequential, & formatted=is_formatted, write=is_writeable) if (is_opened) then if (is_sequential == "Y" .and. is_formatted == "Y " & .and. is_writeable == "Y") then ! write (unitnr, "(A,I3,A)") & ! "\begin{psTree}{\Toval[linecolor=blue]{$", int(this%depth), "$}}" write (unitnr, "(A,I3,A,F9.3,A)") & "\begin{psTree}{\Toval[linecolor=blue]{\node{", this%depth, & "}{", this%measure(), "}}}" if (associated (this%leftmost)) then call this%leftmost%write_pstricks (unitnr) else write (unitnr, "(A,A,A)") "\Tr[", no_kid, "]{}" end if if (associated (this%left)) then call this%left%write_pstricks (unitnr) else write (unitnr, "(A,A,A)") "\Tr[", no_kid, "]{}" end if if (associated (this%right)) then call this%right%write_pstricks (unitnr) else write (unitnr, "(A,A,A)") "\Tr[", no_kid, "]{}" end if if (associated (this%rightmost)) then call this%rightmost%write_pstricks (unitnr) else write(unitnr,'("\Tr[",a,"]{}")') no_kid end if write (unitnr, "(A)") "\end{psTree}" write (unitnr, "(A)") "\\" else write (*, "(A,I2,A)") & "fibonacci_node_write_pstricks: Unit ", unitnr, & " is not opened properly." write (*, "(A)") "No output is written to unit." end if else write (*, "(A,I2,A)") & "fibonacci_node_write_pstricks: Unit ", unitnr, & " is not opened." write (*, "(A)") "No output is written to unit." end if end subroutine fibonacci_root_write_pstricks @ %def fibonacci_root_write_pstricks @ <>= procedure :: copy_root => fibonacci_root_copy_root <>= subroutine fibonacci_root_copy_root (this, primitive) class(fibonacci_root_t), intent(out) :: this class(fibonacci_root_t), intent(in) :: primitive call fibonacci_node_copy_node (this, primitive) this%leftmost => primitive%leftmost this%rightmost => primitive%rightmost end subroutine fibonacci_root_copy_root @ %def fibonacci_root_copy_root @ <>= procedure :: push_by_content => fibonacci_root_push_by_content <>= subroutine fibonacci_root_push_by_content (this, content) class(fibonacci_root_t), target, intent(inout) :: this class(measure_class_t), target, intent(in) :: content class(fibonacci_leave_t), pointer :: node ! print *,"fibonacci_root_push_by_content: ",content%measure() allocate (node) node%down => content call this%push_by_leave (node) end subroutine fibonacci_root_push_by_content @ %def fibonacci_root_push_by_content @ This is a workaround for gfortran bug 44696. This subroutine is a merge of [[fibonacci_tree_push_by_node]], [[fibonacci_node_find]], and [[fibonacci_leave_insert_leave_by_node]]. <>= procedure :: push_by_leave => fibonacci_root_push_by_leave <>= subroutine fibonacci_root_push_by_leave (this, new_leave) class(fibonacci_root_t), target, intent(inout) :: this class(fibonacci_leave_t), pointer, intent(inout) :: new_leave class(fibonacci_leave_t), pointer :: old_leave class(fibonacci_node_t), pointer :: node, new_node, leave_c ! write (11, fmt=*) "push by leave(", new_leave%measure(), ")\\" !PSTRICKS ! flush(11) !PSTRICKS if (new_leave <= this%leftmost) then old_leave => this%leftmost this%leftmost => new_leave node => old_leave%up call fibonacci_node_spawn & (new_node, new_leave, old_leave, old_leave%left, old_leave%right) call node%append_left (new_node) else if (new_leave > this%rightmost) then old_leave => this%rightmost this%rightmost => new_leave node => old_leave%up call fibonacci_node_spawn & (new_node, old_leave, new_leave, old_leave%left, old_leave%right) call node%append_right (new_node) else node => this do if (new_leave <= node) then leave_c => node%left select type (leave_c) class is (fibonacci_leave_t) if (new_leave <= leave_c) then ! print *,"left left" call fibonacci_node_spawn (new_node, new_leave, & leave_c, leave_c%left, leave_c%right) else ! print *,"left right" call fibonacci_node_spawn (new_node, leave_c, & new_leave, leave_c%left, leave_c%right) end if call node%append_left (new_node) exit class default ! print *,"left" node => node%left end select else leave_c => node%right select type (leave_c) class is (fibonacci_leave_t) if (new_leave <= leave_c) then ! print *,"right left" call fibonacci_node_spawn (new_node, new_leave, & leave_c, leave_c%left, leave_c%right) else ! print *,"right right" call fibonacci_node_spawn (new_node, leave_c, & new_leave, leave_c%left, leave_c%right) end if call node%append_right (new_node) exit class default ! print *,"right" node => node%right end select end if end do end if end if ! call this%write_pstricks(11) ! PSTRICKS ! flush(11) ! PSTRICKS ! write(11,fmt=*)"repair\\" ! PSTRICKS call node%repair () ! call this%write_pstricks (11) !PSTRICKS ! flush(11) !PSTRICKS ! call node%update_value (right_value) ! call this%write_pstricks (11) ! print *, new_node%value, new_node%left%value, new_node%right%value end subroutine fibonacci_root_push_by_leave @ %def fibonacci_root_push_by_leave @ <>= procedure :: pop_left => fibonacci_root_pop_left <>= subroutine fibonacci_root_pop_left (this, leave) class(fibonacci_root_t), intent(inout), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave class(fibonacci_node_t), pointer :: parent, grand ! write (11,fmt=*) "fibonacci root pop left\\" ! PSTRICKS ! flush (11) ! PSTRICKS leave => this%leftmost if (this%left%depth >= 1) then parent => leave%up grand => parent%up grand%left => parent%right parent%right%up => grand deallocate (parent) parent => grand%left if (.not. parent%is_leave ()) then parent => parent%left end if select type (parent) class is (fibonacci_leave_t) this%leftmost => parent class default call parent%print_all() call msg_fatal ("fibonacci_root_pop_left: ERROR: leftmost is no leave.") end select ! call this%write_pstricks (11) ! PSTRICKS ! flush (11) ! PSTRICKS ! write (11,fmt=*) "fibonacci node repair\\" ! PSTRICKS ! flush (11) ! PSTRICKS call grand%repair () else if (this%left%depth == 0 .and. this%right%depth == 1) then parent => this%right parent%right%up => this parent%left%up => this this%left => parent%left this%right => parent%right this%depth = 1 deallocate (parent) parent => this%left select type (parent) class is (fibonacci_leave_t) this%leftmost => parent end select this%down => this%leftmost%down end if end if nullify (leave%right%left) nullify (leave%up) nullify (leave%right) nullify (this%leftmost%left) ! call this%write_pstricks (11) ! PSTRICKS ! flush (11) ! PSTRICKS end subroutine fibonacci_root_pop_left @ %def fibonacci_root_pop_left @ <>= procedure :: pop_right => fibonacci_root_pop_right <>= subroutine fibonacci_root_pop_right (this, leave) class(fibonacci_root_t), intent(inout), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave class(fibonacci_node_t), pointer :: parent, grand leave => this%rightmost if (this%right%depth >= 1) then parent => leave%up grand => parent%up grand%right => parent%left parent%left%up => grand deallocate (parent) parent => grand%right if (.not. parent%is_leave ()) then parent => parent%right end if select type (parent) class is (fibonacci_leave_t) this%rightmost => parent class default call parent%print_all() call msg_fatal ("fibonacci_root_pop_left: ERROR: leftmost is no leave.") end select call grand%repair () else if (this%right%depth == 0 .and. this%left%depth == 1) then parent => this%left parent%left%up => this parent%right%up => this this%right => parent%right this%left => parent%left this%depth = 1 deallocate (parent) parent => this%right select type (parent) class is (fibonacci_leave_t) this%rightmost => parent end select this%down => this%rightmost%down end if end if end subroutine fibonacci_root_pop_right @ %def fibonacci_root_pop_right @ <>= procedure :: list_to_tree => fibonacci_root_list_to_tree <>= subroutine fibonacci_root_list_to_tree (this, n_leaves, leave_list_target) class(fibonacci_root_t), target, intent(inout) :: this integer, intent(in) :: n_leaves type(fibonacci_leave_list_t), target, intent(in) :: leave_list_target ! class(fibonacci_root_t), pointer, intent(out) :: tree integer :: depth, n_deep, n_merge class(fibonacci_node_t), pointer :: node class(fibonacci_leave_list_t), pointer :: leave_list class(fibonacci_leave_t), pointer :: content real(default) :: up_value leave_list => leave_list_target call ilog2 (n_leaves, depth, n_deep) n_deep = n_deep * 2 n_merge = 0 this%depth = depth node => this OUTER: do do while (depth > 1) depth = depth - 1 allocate (node%left) node%left%up => node node => node%left node%depth = depth end do node%left => leave_list%leave node%down => leave_list%leave%down leave_list => leave_list%next node%right => leave_list%leave content => leave_list%leave leave_list => leave_list%next n_merge = n_merge + 2 INNER: do if (associated (node%up)) then if (node%is_left_child ()) then if (n_merge == n_deep .and. depth == 1) then node => node%up node%right => leave_list%leave node%right%up => node node%down => content%down content => leave_list%leave leave_list => leave_list%next n_merge = n_merge + 1 cycle end if exit INNER else node => node%up depth = depth + 1 end if else exit OUTER end if end do INNER node => node%up node%down => content%down allocate (node%right) node%right%up => node node => node%right if (n_deep == n_merge) then depth = depth - 1 end if node%depth = depth end do OUTER call this%set_leftmost call this%set_rightmost end subroutine fibonacci_root_list_to_tree @ %def fibonacci_root_list_to_tree @ This subroutine has neither been used nor revised for a long time, so it might be broken. <>= procedure :: merge => fibonacci_root_merge <>= subroutine fibonacci_root_merge(this_tree,that_tree,merge_tree) class(fibonacci_root_t), intent(in) :: this_tree class(fibonacci_root_t), intent(in) :: that_tree class(fibonacci_root_t), pointer, intent(out) :: merge_tree class(fibonacci_leave_t), pointer :: this_leave, that_leave, old_leave type(fibonacci_leave_list_t), target :: leave_list class(fibonacci_leave_list_t), pointer :: last_leave integer :: n_leaves if (associated (this_tree%leftmost) .and. associated (that_tree%leftmost)) then n_leaves = 1 this_leave => this_tree%leftmost that_leave => that_tree%leftmost if (this_leave < that_leave) then allocate (leave_list%leave, source=this_leave) call this_leave%find_right_leave (this_leave) else allocate (leave_list%leave, source=that_leave) call that_leave%find_right_leave (that_leave) end if last_leave => leave_list do while (associated (this_leave) .and. associated (that_leave)) if (this_leave < that_leave) then old_leave => this_leave call this_leave%find_right_leave (this_leave) else old_leave=>that_leave call that_leave%find_right_leave (that_leave) end if allocate (last_leave%next) last_leave => last_leave%next allocate (last_leave%leave, source=old_leave) n_leaves = n_leaves + 1 end do if (associated (this_leave)) then old_leave => this_leave else old_leave => that_leave end if do while (associated (old_leave)) allocate (last_leave%next) last_leave => last_leave%next allocate (last_leave%leave, source=old_leave) n_leaves = n_leaves + 1 call old_leave%find_right_leave (old_leave) end do allocate (merge_tree) call merge_tree%list_to_tree (n_leaves, leave_list) else n_leaves = 0 end if if (associated (leave_list%next)) then last_leave => leave_list%next do while (associated (last_leave%next)) leave_list%next => last_leave%next deallocate (last_leave) last_leave => leave_list%next end do deallocate (last_leave) end if end subroutine fibonacci_root_merge @ %def fibonacci_root_merge @ <>= procedure :: set_leftmost => fibonacci_root_set_leftmost <>= subroutine fibonacci_root_set_leftmost (this) class(fibonacci_root_t) :: this call this%find_leftmost (this%leftmost) end subroutine fibonacci_root_set_leftmost @ %def fibonacci_root_set_leftmost @ <>= procedure :: set_rightmost => fibonacci_root_set_rightmost <>= subroutine fibonacci_root_set_rightmost (this) class(fibonacci_root_t) :: this call this%find_rightmost (this%rightmost) end subroutine fibonacci_root_set_rightmost @ %def fibonacci_root_set_rightmost @ <>= procedure :: init_by_leave => fibonacci_root_init_by_leave <>= subroutine fibonacci_root_init_by_leave (this, left_leave, right_leave) class(fibonacci_root_t), target, intent(out) :: this class(fibonacci_leave_t), target, intent(in) :: left_leave, right_leave if (left_leave <= right_leave) then this%left => left_leave this%right => right_leave this%leftmost => left_leave this%rightmost => right_leave else this%left => right_leave this%right => left_leave this%leftmost => right_leave this%rightmost => left_leave end if this%left%up => this this%right%up => this this%down => this%leftmost%down this%depth = 1 this%leftmost%right => this%rightmost this%rightmost%left => this%leftmost this%is_valid_c = .true. end subroutine fibonacci_root_init_by_leave @ %def fibonacci_root_init_by_leave @ <>= procedure :: init_by_content => fibonacci_root_init_by_content <>= subroutine fibonacci_root_init_by_content (this, left_content, right_content) class(fibonacci_root_t), target, intent(out) :: this class(measure_class_t), intent(in), target :: left_content, right_content call this%reset () print *, "fibonacci_root_init_by_content: ", left_content%measure (), & right_content%measure () if (left_content < right_content) then call this%leftmost%set_content (left_content) call this%rightmost%set_content (right_content) else call this%leftmost%set_content (right_content) call this%rightmost%set_content (left_content) end if this%down => this%leftmost%down this%is_valid_c = .true. end subroutine fibonacci_root_init_by_content @ %def fibonacci_root_init_by_content @ <>= procedure :: reset => fibonacci_root_reset @ <>= subroutine fibonacci_root_reset (this) class(fibonacci_root_t), target, intent(inout) :: this call this%deallocate_tree () allocate (this%leftmost) allocate (this%rightmost) this%depth = 1 this%leftmost%depth = 0 this%rightmost%depth = 0 this%left => this%leftmost this%right => this%rightmost this%left%up => this this%right%up => this this%leftmost%right => this%rightmost this%rightmost%left => this%leftmost end subroutine fibonacci_root_reset @ %def fibonacci_root_reset @ <>= procedure :: deallocate_tree => fibonacci_root_deallocate_tree <>= recursive subroutine fibonacci_root_deallocate_tree (this) class(fibonacci_root_t), intent(inout) :: this call this%deallocate_tree () nullify (this%leftmost) nullify (this%rightmost) end subroutine fibonacci_root_deallocate_tree @ %def fibonacci_root_deallocate_tree @ <>= procedure :: deallocate_all => fibonacci_root_deallocate_all @ <>= recursive subroutine fibonacci_root_deallocate_all (this) class(fibonacci_root_t), intent(inout) :: this call this%deallocate_all () nullify (this%leftmost) nullify (this%rightmost) end subroutine fibonacci_root_deallocate_all @ %def fibonacci_root_deallocate_all @ <>= ! class(serializable_ref_type), pointer :: ref_list @ <>= type, extends (fibonacci_root_t) :: fibonacci_stub_t contains <> end type fibonacci_stub_t @ %def fibonacci_stub_t @ <>= procedure :: write_to_marker => fibonacci_stub_write_to_marker <>= subroutine fibonacci_stub_write_to_marker (this, marker, status) class(fibonacci_stub_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status end subroutine fibonacci_stub_write_to_marker @ %def fibonacci_stub_write_to_marker @ <>= procedure :: read_target_from_marker => fibonacci_stub_read_target_from_marker <>= subroutine fibonacci_stub_read_target_from_marker (this, marker, status) class(fibonacci_stub_t), target, intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status end subroutine fibonacci_stub_read_target_from_marker @ %def fibonacci_stub_read_target_from_marker @ <>= ! procedure :: print_to_unit => fibonacci_stub_print_to_unit @ <>= procedure, nopass :: get_type => fibonacci_stub_get_type @ <>= pure subroutine fibonacci_stub_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="fibonacci_stub_t") end subroutine fibonacci_stub_get_type @ %def fibonacci_stub_get_type @ <>= procedure :: push_by_content => fibonacci_stub_push_by_content <>= subroutine fibonacci_stub_push_by_content (this, content) class(fibonacci_stub_t), target, intent(inout) :: this class(measure_class_t), target, intent(in) :: content class(fibonacci_leave_t), pointer :: leave allocate (leave) call leave%set_content (content) call this%push_by_leave (leave) end subroutine fibonacci_stub_push_by_content @ %def fibonacci_stub_push_by_content @ <>= procedure :: push_by_leave => fibonacci_stub_push_by_leave <>= subroutine fibonacci_stub_push_by_leave (this, new_leave) class(fibonacci_stub_t), target, intent(inout) :: this class(fibonacci_leave_t), pointer, intent(inout) :: new_leave class(fibonacci_leave_t), pointer :: old_leave if (this%depth < 1) then if (associated (this%leftmost)) then old_leave => this%leftmost call this%init_by_leave (old_leave, new_leave) else this%leftmost => new_leave end if else call fibonacci_root_push_by_leave (this, new_leave) end if end subroutine fibonacci_stub_push_by_leave @ %def fibonacci_stub_push_by_leave @ <>= procedure :: pop_left => fibonacci_stub_pop_left <>= subroutine fibonacci_stub_pop_left (this, leave) class(fibonacci_stub_t), intent(inout), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave if (this%depth < 2) then if (this%depth == 1) then leave => this%leftmost this%leftmost => this%rightmost nullify (this%rightmost) nullify (this%right) nullify (this%left) this%depth = 0 this%is_valid_c = .false. else if (associated (this%leftmost)) then leave => this%leftmost nullify (this%leftmost) end if end if else call fibonacci_root_pop_left (this, leave) end if end subroutine fibonacci_stub_pop_left @ %def fibonacci_stub_pop_left @ <>= procedure :: pop_right => fibonacci_stub_pop_right <>= subroutine fibonacci_stub_pop_right (this, leave) class(fibonacci_stub_t), intent(inout), target :: this class(fibonacci_leave_t), pointer, intent(out) :: leave if (this%depth < 2) then if (this%depth == 1) then this%is_valid_c = .false. if (associated (this%rightmost)) then leave => this%rightmost nullify (this%rightmost) nullify (this%right) else if (associated (this%leftmost)) then leave => this%leftmost nullify (this%leftmost) nullify (this%left) else nullify (leave) end if end if end if else call fibonacci_root_pop_right (this, leave) end if end subroutine fibonacci_stub_pop_right @ %def fibonacci_stub_pop_right @ <>= public :: fibonacci_leave_list_t <>= type fibonacci_leave_list_t class(fibonacci_leave_t), pointer :: leave => null() class(fibonacci_leave_list_t), pointer :: next => null() end type fibonacci_leave_list_t @ %def fibonacci_leave_list_t @ <>= ! subroutine fibonacci_node_update_value (this, right_value) ! class(fibonacci_node_t), target :: this ! class(fibonacci_node_t), pointer:: node ! real(default), intent(in) :: right_value ! if (associated (this%left) .and. associated (this%right)) then ! node => this ! ! node%value = node%left%value ! ! right_value = node%right%value ! INNER: do while (associated (node%up)) ! if (node%is_right_child ()) then ! node => node%up ! else ! node%up%value = right_value ! exit ! end if ! end do INNER ! end if ! end subroutine fibonacci_node_update_value @ %def fibonacci_node_update_value @ <>= ! subroutine fibonacci_root_copy_node (this, primitive) ! class(fibonacci_root_t), intent(out) :: this ! type(fibonacci_node_t), intent(in) :: primitive ! call fibonacci_node_copy_node (this, primitive) ! call primitive%find_leftmost (this%leftmost) ! call primitive%find_rightmost (this%rightmost) ! end subroutine fibonacci_root_copy_node @ %def fibonacci_root_copy_node @ <>= ! subroutine fibonacci_root_push_by_node (this, new_leave) ! class(fibonacci_root_t), target, intent(inout) :: this ! class(fibonacci_leave_t), pointer, intent(inout) :: new_leave ! class(fibonacci_leave_t), pointer :: old_leave ! if (new_leave <= this%leftmost) then ! old_leave => this%leftmost ! this%leftmost => new_leave ! else ! if (new_leave > this%rightmost) then ! old_leave => this%rightmost ! this%rightmost => new_leave ! else ! call this%find (new_leave%measure(), old_leave) ! end if ! end if ! ! call old_leave%insert_leave_by_node (new_leave) ! call fibonacci_leave_insert_leave_by_node (old_leave, new_leave) ! call new_leave%up%repair () ! ! call new_leave%up%update_value () ! end subroutine fibonacci_root_push_by_node @ %def fibonacci_root_push_by_node @ <>= subroutine fibonacci_leave_write_content (this, unit) class(fibonacci_leave_t), intent(in), target :: this integer,optional, intent(in) :: unit call this%down%print_all (unit) end subroutine fibonacci_leave_write_content @ %def fibonacci_leave_write_content @ <>= subroutine fibonacci_leave_write (this, unit) class(fibonacci_leave_t), intent(in), target :: this integer,optional, intent(in) :: unit call this%print_all (unit) end subroutine fibonacci_leave_write @ %def fibonacci_leave_write @ <>= subroutine fibonacci_leave_write_value (this, unit) class(fibonacci_leave_t), intent(in), target :: this integer, intent(in), optional :: unit if (present (unit)) then write(unit, fmt=*) this%measure () else print *, this%measure () end if ! call this%print_little (unit) end subroutine fibonacci_leave_write_value @ %def fibonacci_leave_write_value @ <>= subroutine fibonacci_node_spawn (new_node, left_leave, right_leave, & left_left_leave, right_right_leave) class(fibonacci_node_t), pointer, intent(out) :: new_node class(fibonacci_leave_t), target, intent(inout) :: left_leave, right_leave class(fibonacci_node_t), pointer, intent(inout) :: left_left_leave, & right_right_leave allocate (new_node) new_node%depth = 1 if (associated (left_left_leave)) then left_left_leave%right => left_leave left_leave%left => left_left_leave else nullify (left_leave%left) end if if (associated (right_right_leave)) then right_right_leave%left => right_leave right_leave%right => right_right_leave else nullify (right_leave%right) end if new_node%left => left_leave new_node%right => right_leave new_node%down => left_leave%down new_node%depth = 1 left_leave%up => new_node right_leave%up => new_node left_leave%right => right_leave right_leave%left => left_leave end subroutine fibonacci_node_spawn @ %def fibonacci_node_spawn @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Adaptive Quadrature} This file contains the module [[muli_aq]] which is an acronym for adaptive quadrature. The abstract type [[aq_class]] is extended and the deferred procedure [[evaluate]] is defined. [[muli_aq]] calls [[evaluate]] to evaluate the integrand at any point in the given range. We have tried to use a procedure pointer instead of the deferred type-bound procedure, but no compiler was able to handle procedure pointers plus cuba was not able to handle parameters, to wit dimensions of the integrand that should not get integrated. So we switched to this odd way of using inheritance. Meanwhile these problems got solved and we could go for a more straightforward solution, but it works fine as it is. [[aq_class]] uses [[muli_trapezium]] to approximate the integral. It still has to do the subdivision of segments and has to check whether the precision goal is reached. Finally, the result is written do disc using the serialization framework defined in [[muli_base]]. Since QCD is not expected to change frequently, the only reason to regenerate this function is a change of the used PDF set. Then you can read the integral from disc each time you run a simulation with the same PDF set. <<[[muli_aq.f90]]>>= <> module muli_aq <> use constants use diagnostics use muli_base use muli_cuba use muli_trapezium use muli_fibonacci_tree <> <> <> <> contains <> end module muli_aq @ %def muli_aq @ The variables [[error_goal]], [[err_tree]] and [[int_list]] must be initialised before the main loop can be called. Additionaly, the nodes and segments should be preprocessed by [[first_run]] before the main loop is called. <>= public :: aq_class <>= type, extends (identified_t), abstract :: aq_class logical :: is_deferred_initialised = .false. logical :: is_error_tree_initialised = .false. logical :: is_goal_set = .false. logical :: is_initialised = .false. logical :: is_run = .false. logical :: is_goal_reached = .false. logical :: is_integrated = .false. integer(dik) :: n_nodes = 0 integer(dik) :: max_nodes = 10000 integer :: dim_integral = 1 real(default) :: abs_error_goal = 0._default real(default) :: rel_error_goal = 0.1_default real(default) :: scaled_error_goal = 0._default real(default) :: integral = 1._default real(default) :: integral_error = 0._default real(default), dimension(2) :: region = [0._default, 1._default] real(default), dimension(:,:), allocatable :: convergence real(default) :: total_time = 0 real(default) :: loop_time = 0 real(default) :: int_time = 0 real(default) :: cuba_time = 0 real(default) :: init_time = 0 real(default) :: cpu_time = 0 real(default) :: error_goal = 0._default class(fibonacci_root_t), pointer :: err_tree => null() class(muli_trapezium_list_t), pointer :: int_list => null() contains <> end type aq_class @ %def aq_class @ <>= procedure :: basic_write_to_marker => aq_write_to_marker procedure :: write_to_marker => aq_write_to_marker <>= subroutine aq_write_to_marker (this, marker, status) class(aq_class), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%mark_begin ("aq_class") call this%base_write_to_marker (marker, status) call marker%mark ("is_deferred_initialised", & this%is_deferred_initialised) call marker%mark ("is_error_tree_initialised", & this%is_error_tree_initialised) call marker%mark ("is_goal_set", this%is_goal_set) call marker%mark ("is_initialised", this%is_initialised) call marker%mark ("is_run", this%is_run) call marker%mark ("is_goal_reached", this%is_goal_reached) call marker%mark ("is_integrated", this%is_integrated) call marker%mark ("n_nodes", this%n_nodes) call marker%mark ("max_nodes", this%max_nodes) call marker%mark ("dim_integral", this%dim_integral) call marker%mark ("abs_error_goal", this%abs_error_goal) call marker%mark ("rel_error_goal", this%rel_error_goal) call marker%mark ("scaled_error_goal", this%scaled_error_goal) call marker%mark ("error_goal", this%error_goal) call marker%mark ("integral", this%integral) call marker%mark ("integral_error", this%integral_error) call marker%mark ("region", this%region(1:2)) ser => this%err_tree call marker%mark_pointer ("err_tree", ser) ser => this%int_list call marker%mark_pointer ("int_list", ser) call marker%mark_end ("aq_class") end subroutine aq_write_to_marker @ %def aq_write_to_marker @ <>= procedure :: basic_read_from_marker => aq_read_from_marker procedure :: read_from_marker => aq_read_from_marker <>= subroutine aq_read_from_marker (this, marker, status) class(aq_class), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%pick_begin ("aq_class", status=status) call this%base_read_from_marker (marker, status) call marker%pick ("is_deferred_initialised", & this%is_deferred_initialised, status) call marker%pick ("is_error_tree_initialised", & this%is_error_tree_initialised, status) call marker%pick ("is_goal_set", this%is_goal_set, status) call marker%pick ("is_initialised", this%is_initialised, status) call marker%pick ("is_run", this%is_run, status) call marker%pick ("is_goal_reached", this%is_goal_reached, status) call marker%pick ("is_integrated", this%is_integrated, status) call marker%pick ("n_nodes", this%n_nodes, status) call marker%pick ("max_nodes", this%max_nodes, status) call marker%pick ("dim_integral", this%dim_integral, status) call marker%pick ("abs_error_goal", this%abs_error_goal, status) call marker%pick ("rel_error_goal", this%rel_error_goal, status) call marker%pick ("scaled_error_goal", this%scaled_error_goal, status) call marker%pick ("error_goal", this%error_goal, status) call marker%pick ("integral", this%integral, status) call marker%pick ("integral_error", this%integral_error, status) call marker%pick ("region", this%region(1:2), status) call marker%pick_pointer ("err_tree", ser) if (associated (ser)) then select type (ser) class is (fibonacci_root_t) this%err_tree => ser class default nullify (this%err_tree) end select end if call marker%pick_pointer ("int_list", ser) if (associated (ser)) then select type (ser) class is (muli_trapezium_list_t) this%int_list => ser class default nullify (this%int_list) end select end if call marker%pick_end ("aq_class", status) end subroutine aq_read_from_marker @ %def aq_read_from_marker @ <>= procedure :: basic_print_to_unit => aq_print_to_unit procedure :: print_to_unit => aq_print_to_unit <>= subroutine aq_print_to_unit (this, unit, parents, components, peers) class(aq_class), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: ite class(ser_class_t), pointer :: ser if (parents > 0) call this%base_print_to_unit & (unit, parents-1, components, peers) write (unit, "(A)") "Components of aq_class" write (unit, "(A,L1)") "Deferred class initialised: ", & this%is_deferred_initialised write (unit, "(A,L1)") "Error tree initialised: ", & this%is_error_tree_initialised write (unit, "(A,L1)") "Accuracy goal set: ", this%is_goal_set write (unit, "(A,L1)") "Ready for run: ", this%is_initialised write (unit, "(A,L1)") "Is run: ", this%is_run write (unit, "(A,L1)") "Accuracy goal reached: ", this%is_goal_reached write (unit, "(A,L1)") "Integral calculated: ", this%is_integrated write (unit, "(A,I10)") "Number of nodes: ", this%n_nodes write (unit, "(A,I10)") "Maximal number of nodes: ", this%max_nodes write (unit, "(A,I10)") "Dimension of integral: ", this%dim_integral write (unit, "(A,E20.10)") "Given abs. error goal: ", this%abs_error_goal write (unit, "(A,E20.10)") "Given rel. error goal: ", this%rel_error_goal write (unit, "(A,E20.10)") "Guessed abs error goal:", this%scaled_error_goal write (unit, "(A,E20.10)") "Actual abs error goal: ", this%error_goal write (unit, "(A,E20.10)") "Integral ", this%integral write (unit, "(A,E20.10)") "Estimated abs. error: ", this%integral_error ! if (this%integral == 0) then ! write (unit, "(A,E20.10)") "Estimated rel. error: ", & ! this%integral_error / this%integral ! else ! write (unit, "(A,E20.10)") "Estimated rel. error: INF" ! end if write (unit, "(A,E10.5,A,E10.5,A)") "Integration region = (", & this%region(1), " : ", this%region(2), ")" ser => this%err_tree call serialize_print_comp_pointer & (ser, unit, parents, components, peers, "error tree") ser => this%int_list call serialize_print_comp_pointer & (ser, unit, parents, components, peers, "integral list") end subroutine aq_print_to_unit @ %def aq_print_to_unit @ <>= procedure, nopass :: get_type => aq_get_type <>= pure subroutine aq_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="aq_type") end subroutine aq_get_type @ %def aq_get_type @ <>= procedure :: deserialize_from_marker => aq_deserialize_from_marker <>= subroutine aq_deserialize_from_marker (this, name, marker) class(aq_class), intent(out) :: this character(*), intent(in) :: name class(marker_t), intent(inout) :: marker class(ser_class_t), pointer :: ser allocate (muli_trapezium_t :: ser) call marker%push_reference (ser) allocate (fibonacci_root_t :: ser) call marker%push_reference (ser) allocate (fibonacci_leave_t :: ser) call marker%push_reference (ser) allocate (fibonacci_node_t :: ser) call marker%push_reference (ser) call serializable_deserialize_from_marker (this, name, marker) call marker%pop_reference (ser) deallocate (ser) call marker%pop_reference (ser) deallocate (ser) call marker%pop_reference (ser) deallocate (ser) call marker%pop_reference (ser) deallocate (ser) end subroutine aq_deserialize_from_marker @ %def aq_deserialize_from_marker @ The relative error goal is supposed to be $10^{-4}$. <>= generic :: initialize => aq_initialize procedure :: aq_initialize <>= subroutine aq_initialize (this, id, name, goal, max_nodes, dim, init) class(aq_class), intent(out) :: this integer(dik), intent(in) :: id, max_nodes integer, intent(in) :: dim character, intent(in) :: name real(default) :: goal real(default), dimension(:), intent(in) :: init call this%initialize (id, name) this%rel_error_goal = goal this%max_nodes = max_nodes call this%init_error_tree (dim, init) end subroutine aq_initialize @ %def aq_initialize @ <>= procedure :: print_times => aq_print_times <>= subroutine aq_print_times (this) class(aq_class), intent(in) :: this write (*, "(A,E20.10)") "Initialization time: ", this%init_time write (*, "(A,E20.10)") "Main loop time: ", this%loop_time write (*, "(A,E20.10)") "Integration time: ", this%int_time write (*, "(A,E20.10)") "Overall run time: ", this%total_time write (*, "(A,E20.10)") "Cuba integration time:", this%cuba_time end subroutine aq_print_times @ <>= procedure :: write_convergence => aq_write_convergence <>= subroutine aq_write_convergence (this, unit) class(aq_class), intent(in) :: this integer, intent(in) :: unit integer, dimension(2) :: s integer :: node if (allocated (this%convergence)) then s = shape (this%convergence) do node = 1, s(2) write (unit, *) node, this%convergence (1:2, node) end do end if end subroutine aq_write_convergence @ %def aq_write_convergence @ <>= procedure :: reset => aq_reset <>= subroutine aq_reset (this) class(aq_class) :: this this%is_deferred_initialised = .false. this%is_error_tree_initialised = .false. this%is_goal_set = .false. this%is_initialised = .false. this%is_run = .false. this%is_goal_reached = .false. this%is_integrated = .false. this%n_nodes = 0 this%max_nodes = 10000 this%dim_integral = 1 this%abs_error_goal = 1._default this%rel_error_goal = 0.1_default this%scaled_error_goal = 0.0_default this%error_goal = 0.0_default this%integral = 0.0_default this%integral_error = 0.0_default this%region = [ 0.0_default, 1._default ] this%total_time = 0 this%loop_time = 0 this%int_time = 0 this%init_time = 0 call this%dealloc_trees () end subroutine aq_reset @ %def aq_reset @ <>= procedure :: dealloc_trees => aq_dealloc_trees procedure :: finalize => aq_dealloc_trees <>= subroutine aq_dealloc_trees (this) class(aq_class) :: this if (associated (this%err_tree)) then call this%err_tree%deallocate_all () deallocate (this%err_tree) end if if (associated (this%int_list)) then call this%int_list%finalize () deallocate (this%int_list) end if end subroutine aq_dealloc_trees @ %def aq_dealloc_trees @ <>= procedure :: init_error_tree => aq_init_error_tree <>= subroutine aq_init_error_tree (this, dim_integral, x_array) class(aq_class) :: this integer, intent(in) :: dim_integral real(default), dimension(:), intent(in) :: x_array real(default) :: center real(default), dimension(:), allocatable :: l_val, c_val, r_val class(muli_trapezium_t), pointer :: left_node => null() class(muli_trapezium_t), pointer :: right_node => null() integer :: x_size, pos ! print '("Entermarker aq_init_error_tree...")' call cpu_time (this%init_time) this%is_initialised = .false. this%integral = 0._default this%dim_integral = dim_integral x_size = size(x_array) if (x_size < 2) then call msg_error ("aq_init_error_tree: I need at least two real values") else allocate (l_val (0:dim_integral-1)) allocate (c_val (0:dim_integral-1)) allocate (r_val (0:dim_integral-1)) this%region = [x_array(1), x_array(x_size)] if (x_size < 3) then center = (x_array(2) - x_array(1)) / 2._default call this%evaluate (x_array(1), l_val) call this%evaluate (center, c_val) call this%evaluate (x_array(2), r_val) allocate (left_node) call left_node%initialize (dim=dim_integral, & r_position=center, d_position=center-x_array(1)) call left_node%set_r_value (c_val) call left_node%set_d_value (c_val - l_val) allocate (right_node) call right_node%initialize (dim=dim_integral, & r_position=x_array(2), d_position=x_array(2)-center) call right_node%set_r_value (r_val) call right_node%set_d_value (r_val - c_val) else call this%evaluate (x_array(1), l_val) call this%evaluate (x_array(2), c_val) call this%evaluate (x_array(3), r_val) allocate (left_node) call left_node%initialize (dim=dim_integral, & r_position=x_array(2), d_position=x_array(2)-x_array(1)) call left_node%set_r_value (c_val) call left_node%set_d_value (c_val - l_val) allocate (right_node) call right_node%initialize (dim=dim_integral, & r_position=x_array(3), d_position=x_array(3)-x_array(2)) call right_node%set_r_value (r_val) call right_node%set_d_value (r_val - c_val) end if call left_node%update () call right_node%update () this%integral = sum (left_node%get_d_integral () + & right_node%get_d_integral ()) if (.not. associated (this%err_tree)) then allocate(this%err_tree) end if print *, left_node%measure () print *, right_node%measure () call this%err_tree%init_by_content (left_node, right_node) ! call this%err_tree%write_pstricks (11) if (x_size > 3) then do pos = 4, x_size print *, "aq_init_error_tree", pos, "/", x_size l_val = right_node%get_r_value_array () call this%evaluate (x_array(pos), r_val) c_val = r_val - l_val allocate (right_node) call right_node%initialize (dim=dim_integral, & r_position=x_array(pos), & d_position=x_array(pos)-x_array(pos-1)) call right_node%set_r_value (r_val) call right_node%set_d_value (c_val) call right_node%update () call this%err_tree%push_by_content (right_node) ! call this%err_tree%write_pstricks (11) this%integral = this%integral + sum (right_node%get_d_integral()) end do this%n_nodes = x_size end if this%is_error_tree_initialised = .true. end if call this%set_goal () this%is_initialised = .true. call cpu_time (this%cpu_time) this%init_time = this%cpu_time - this%init_time this%cuba_time = this%init_time allocate (this%convergence (2, this%n_nodes:this%max_nodes)) end subroutine aq_init_error_tree @ <>= procedure :: set_rel_goal => aq_set_rel_goal <>= subroutine aq_set_rel_goal (this, goal) class(aq_class) :: this real(default) :: goal this%rel_error_goal = goal call this%set_goal end subroutine aq_set_rel_goal @ %def aq_set_rel_goal @ <>= procedure :: set_abs_goal => aq_set_abs_goal <>= subroutine aq_set_abs_goal (this, goal) class(aq_class) :: this real(default) :: goal this%abs_error_goal = goal call this%set_goal end subroutine aq_set_abs_goal @ %def aq_set_abs_goal @ <>= procedure :: set_goal => aq_set_goal <>= subroutine aq_set_goal (this) class(aq_class) :: this this%scaled_error_goal = this%rel_error_goal * abs(this%integral) if ((this%scaled_error_goal == zero) .and. & (this%abs_error_goal == zero)) then this%is_goal_set = .false. this%error_goal = zero else if (this%scaled_error_goal == zero) then this%error_goal = this%abs_error_goal else if (this%abs_error_goal == zero) then this%error_goal = this%scaled_error_goal else this%error_goal = max(this%scaled_error_goal, & this%abs_error_goal) end if end if if (this%error_goal > zero) then this%is_goal_set = .true. else this%is_goal_set = .false. end if end if end subroutine aq_set_goal @ %def aq_set_goal @ <>= procedure :: check_init => aq_check_init <>= subroutine aq_check_init (this) class(aq_class) :: this this%is_initialised = this%is_error_tree_initialised .and. & this%is_deferred_initialised end subroutine aq_check_init @ %def aq_check_init @ This routine is unsafe, when [[n_nodes]] $< 4$. <>= procedure :: main_loop => aq_main_loop <>= subroutine aq_main_loop (this) class(aq_class) :: this class(fibonacci_leave_t), pointer :: rightmost class(measure_class_t), pointer :: content class(muli_trapezium_t), pointer :: new_node !,debug logical :: limit = .false. real(default) :: center real(default), dimension(:), allocatable :: c_val allocate (c_val (0:this%dim_integral-1)) LOOP: do call this%err_tree%pop_right (rightmost) if (rightmost < this%error_goal / this%n_nodes) then this%is_goal_reached = .true. exit LOOP else call rightmost%get_content (content) select type (content) class is (muli_trapezium_t) write (*, "(A,I5,A,E14.7,A,E14.7,A,E14.7,A,E14.7)") & "nodes: ", this%n_nodes, " error: ", & rightmost%measure() * this%n_nodes, & " goal: ", this%error_goal, " node at: ", & content%get_l_position(), "-", content%get_r_position() this%convergence (1, this%n_nodes) = this%error_goal / this%n_nodes this%convergence (2, this%n_nodes) = rightmost%measure () center = content%get_r_position () - & content%get_d_position () / two call cpu_time (this%cpu_time) this%cuba_time = this%cuba_time - this%cpu_time call this%evaluate (center, c_val) call cpu_time (this%cpu_time) this%cuba_time = this%cuba_time + this%cpu_time call content%split (c_val, center, new_node) call this%err_tree%push_by_leave (rightmost) call this%err_tree%push_by_content (new_node) end select this%n_nodes = this%n_nodes + 1 if (this%n_nodes > this%max_nodes) then limit = .true. exit LOOP end if end if end do LOOP call this%err_tree%push_by_leave (rightmost) end subroutine aq_main_loop @ %def aq_main_loop @ <>= procedure :: run => aq_run <>= subroutine aq_run (this) class(aq_class) :: this call cpu_time (this%total_time) if (.not. this%is_error_tree_initialised) then call this%init_error_tree (this%dim_integral, this%region) end if this%is_run = .false. this%is_goal_reached = .false. call this%main_loop () this%is_run = .true. call cpu_time (this%cpu_time) this%total_time = this%cpu_time - this%total_time end subroutine aq_run @ %def aq_run @ <>= procedure :: integrate => aq_integrate <>= subroutine aq_integrate (this, int_tree) class(aq_class) :: this class(muli_trapezium_node_class_t), pointer :: node type(muli_trapezium_tree_t), intent(out) :: int_tree real(default) :: sum this%is_integrated = .false. this%integral_error = zero if (this%is_run) then call cpu_time (this%int_time) call fibonacci_tree_resort_and_convert_to_trapezium_list & (this%err_tree, this%int_list) ! call this%int_list%print_all () call this%int_list%integrate (this%integral, this%integral_error) call this%int_list%to_tree (int_tree) this%is_integrated = .true. call cpu_time (this%cpu_time) this%int_time = this%cpu_time - this%int_time end if end subroutine aq_integrate @ %def aq_integrate @ <>= procedure(evaluate_if), deferred :: evaluate ! procedure(evaluate_ratios_if), deferred :: evaluate_ratios <>= @ Usually, the tree is sorted by the sum of errors. Now it shall be sorted by the right position. When at least one branch of the tree is itself a tree, i.e. each branch has got at least two leaves, then process each branch and merge the results. Now we got two sorted lists. Which one's leftmost node has got the lowest value of [[r_position]]? That one shall be the beginning of the merged list [[lin_list]]. Everything is prepared for the algorithm: [[lin_list]] is the beginning of the sorted list, [[last_node]] is its end. [[left_node]] and [[right_node]] are the leftmost nodes of the remainders of [[left_list]] and [[right_list]]. The latter will get stripped from left to right, until one of them ends. Then, either [[left_list]] or [[right_list]] is completely merged into [[lin_list]]. The other one gets appended to [[lin_list]]. In the second part of the big if clause, the tree has got two leaves at most. Is it more than one? There, [[fib_tree]] is a single leave with an allocated "[[content]]" component of type [[muli_trapezium_t]]. If "[[content]]" is not type-compatible with [[muli_trapezium_t]], then this whole conversion cannot succeed. We allocate a new node of type [[muli_trapezium_list_t]]. This list does not contain the content of [[fib_tree]], it {\em is} a copy of the content, for [[muli_trapezium_list_t]] is an extension of [[muli_trapezium_t]]. In the next step, each branch of [[fib_tree]] is a single leave. We could call this soubroutine for each branch, but we do copy and paste for each branch instead. Finally we append one list to the other, the lowest value of [[r_position]] comes first. <>= recursive subroutine fibonacci_tree_resort_and_convert_to_trapezium_list & (fib_tree, lin_list) class(fibonacci_node_t), intent(in) :: fib_tree class(fibonacci_node_t),pointer :: leave class(muli_trapezium_list_t), pointer, intent(out) :: lin_list class(muli_trapezium_list_t), pointer :: left_list, right_list class(muli_trapezium_node_class_t), pointer :: & left_node, right_node, last_node class(measure_class_t), pointer :: content if (fib_tree%depth > 1) then ! print *,"3A" call fibonacci_tree_resort_and_convert_to_trapezium_list & (fib_tree%left, left_list) call fibonacci_tree_resort_and_convert_to_trapezium_list & (fib_tree%right, right_list) if (left_list%is_left_of (right_list)) then lin_list => left_list call left_list%get_right (left_node) right_node => right_list else lin_list => right_list left_node => left_list call right_list%get_right (right_node) end if last_node => lin_list do while (associated (left_node) .and. associated (right_node)) if (left_node%is_left_of (right_node)) then call last_node%append (left_node) call last_node%get_right (last_node) call left_node%get_right (left_node) else call last_node%append (right_node) call last_node%get_right (last_node) call right_node%get_right (right_node) end if end do if (associated (left_node)) then call last_node%append (left_node) else call last_node%append (right_node) end if !!! It's done. ! print *,"3E" else if (fib_tree%depth == 0) then ! print *,"1A" select type (fib_tree) class is (fibonacci_leave_t) call fib_tree%get_content (content) select type (content) class is (muli_trapezium_t) call content%to_node (content%get_r_position(), list=lin_list) class default call msg_fatal & ("fibonacci_tree_resort_and_convert_to_trapezium_list: " // & "Content of fibonacci_tree is not type compatible " // & "to muli_trapezium_t") end select end select ! print *,"1E" else ! print *,"2A" leave => fib_tree%left select type (leave) class is (fibonacci_leave_t) call leave%get_content (content) select type (content) class is (muli_trapezium_t) call content%to_node (content%get_r_position(), list=left_list) class default call msg_fatal & ("fibonacci_tree_resort_and_convert_to_trapezium_list: " // & "Content of fibonacci_tree is not type compatible " // & "to muli_trapezium_t") end select end select leave => fib_tree%right select type (leave) class is (fibonacci_leave_t) call leave%get_content (content) select type (content) class is (muli_trapezium_t) call content%to_node (content%get_r_position(), list=right_list) class default call msg_fatal & ("fibonacci_tree_resort_and_convert_to_trapezium_list: " // & "Content of fibonacci_tree is not type compatible " // & "to muli_trapezium_t") end select end select if (left_list%is_left_of (right_list)) then call left_list%append (right_list) lin_list => left_list else call right_list%append (left_list) lin_list => right_list end if ! print *,"2E" end if end if ! call lin_list%print_all () ! call lin_list%check () end subroutine fibonacci_tree_resort_and_convert_to_trapezium_list @ %def fibonacci_tree_resort_and_convert_to_trapezium_list @ <>= interface subroutine evaluate_if (this, x, y) use kinds !NODEP! import aq_class class(aq_class), intent(inout) :: this real(default), intent(in) :: x real(default), intent(out) , dimension(:) :: y end subroutine evaluate_if ! subroutine evaluate_ratios_if (this, cont) ! use kinds ! use lin_approx_tree_module, only: muli_trapezium_t ! import aq_class ! class(aq_class) :: this ! class(muli_trapezium_t), intent(inout), pointer :: cont ! end subroutine evaluate_ratios_if end interface @ %def evaluate_if evaluate_ratios_if @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<[[muli_parameters.f90]]>>= ! This is a dummy for muli_parameters_module module muli_parameters_module end module muli_parameters_module @ %def muli_parameters_module @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Integrands for Multiple Interactions} This file contains the module [[muli_dsigma]]. Its only type [[muli_dsigma_t]] provides an integrand to [[aq_class]]. The actual integrand is the normalized differential cross section of a QCD $2\to 2$ process $1/\sigma_0 \times d^3 \sigma / ( d p_T^2 d x_1 d x_2)$. We need a root function of this integrand in terms of $p_T$, so we have to integrate out $x_1$ and $x_2$ and have to approximate the root function of the leftover variable $p_T$. Integration of $x_1$ and $x_2$ is done by CUBA, the root function is approximated by [[muli_aq]]. <<[[muli_dsigma.f90]]>>= <> module muli_dsigma <> use constants use muli_base use muli_momentum use muli_interactions use muli_cuba use muli_trapezium use muli_aq <> <> <> <> contains <> end module muli_dsigma @ %def muli_dsigma @ <>= integer, parameter :: dim_f = 17 @ %def dim_f @ <>= public :: muli_dsigma_t <>= type, extends (aq_class) :: muli_dsigma_t private type(transverse_mom_t) :: pt type(cuba_divonne_t) :: cuba_int contains <> end type muli_dsigma_t @ %def muli_dsigma_t @ <>= procedure :: write_to_marker => muli_dsigma_write_to_marker <>= subroutine muli_dsigma_write_to_marker (this, marker, status) class(muli_dsigma_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status class(ser_class_t), pointer :: ser call marker%mark_begin ("muli_dsigma_t") call this%basic_write_to_marker (marker, status) call this%cuba_int%serialize (marker, "cuba_int") call marker%mark_end ("muli_dsigma_t") end subroutine muli_dsigma_write_to_marker @ %def muli_dsigma_write_to_marker @ <>= procedure :: read_from_marker => muli_dsigma_read_from_marker <>= subroutine muli_dsigma_read_from_marker (this, marker, status) class(muli_dsigma_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("muli_dsigma_t", status=status) call this%basic_read_from_marker (marker, status) call this%cuba_int%deserialize ("cuba_int", marker) call marker%pick_end ("muli_dsigma_t", status) end subroutine muli_dsigma_read_from_marker @ %def muli_dsigma_read_from_marker @ <>= procedure :: print_to_unit => muli_dsigma_print_to_unit <>= subroutine muli_dsigma_print_to_unit & (this, unit, parents, components, peers) class(muli_dsigma_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: ite if (parents > 0) call this%basic_print_to_unit & (unit, parents-1, components, peers) write (unit, "(A)") "Components of muli_dsigma_t" if (components > 0) then write (unit, "(A)") "Printing components of cuba_int:" call this%cuba_int%print_to_unit (unit, parents, components-1, peers) else write (unit, "(A)") "Skipping components of cuba_int:" end if end subroutine muli_dsigma_print_to_unit @ %def muli_dsigma_print_to_unit @ <>= procedure, nopass :: get_type => muli_dsigma_get_type @ <>= pure subroutine muli_dsigma_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="muli_dsigma_t") end subroutine muli_dsigma_get_type @ %def muli_dsigma_get_type @ <>= procedure :: generate => muli_dsigma_generate <>= subroutine muli_dsigma_generate (this, gev2_scale_cutoff, gev2_s, int_tree) class(muli_dsigma_t), intent(inout) :: this real(default), intent(in) :: gev2_scale_cutoff, gev2_s type(muli_trapezium_tree_t), intent(out) :: int_tree real(default), dimension(ceiling (log (gev2_s/gev2_scale_cutoff)/two)) :: & initial_values integer :: n print *, gev2_s/gev2_scale_cutoff, & ceiling (log (gev2_s/gev2_scale_cutoff)/two) ! allocate (initial_values (ceiling (-log (gev2_scale_cutoff))/2)) ! allocate (real(default), & ! dimension (ceiling (log(gev2_scale_cutoff))/2) :: initial_values) initial_values(1) = sqrt(gev2_scale_cutoff/gev2_s) * two do n = 2, size(initial_values) - 1 initial_values(n) = initial_values(n-1) * euler end do initial_values(n) = one print *, initial_values ! stop call this%initialize (i_one, "dsigma") call this%pt%initialize (gev2_s) this%abs_error_goal = zero this%rel_error_goal = scale(one, -12) !-12 this%max_nodes = 1000 call this%cuba_int%set_common (dim_f=dim_f, dim_x=2, & eps_rel=scale(this%rel_error_goal,-8), flags = 0) call this%cuba_int%set_deferred (xgiven_flat = [1.E-2_default, & 5.E-1_default + epsilon(1._default), 1.E-2_default, & 5.E-1_default - epsilon(1._default)]) print *, "muli_dsigma_generate:" ! print *, "Cuba Error Goal: ", this%cuba_int%eps_rel print *, "Overall Error Goal: ", this%rel_error_goal call this%init_error_tree (dim_f, initial_values) call this%run () call this%integrate (int_tree) call this%err_tree%deallocate_all () deallocate (this%err_tree) nullify (this%int_list) end subroutine muli_dsigma_generate @ %def muli_dsigma_generate @ <>= procedure :: evaluate => muli_dsigma_evaluate <>= subroutine muli_dsigma_evaluate (this, x, y) class(muli_dsigma_t), intent(inout) :: this real(default), intent(in) :: x real(default), intent(out), dimension(:):: y call this%pt%set_unit_scale (x) ! print *, "muli_dsigma_evaluate x=", x ! call this%cuba_int%integrate_userdata & ! (interactions_proton_proton_integrand_param_17_reg, this%pt) ! if (this%cuba_int%fail == 0) then ! call this%cuba_int%print_all () call this%cuba_int%get_integral_array (y) ! else ! print *, "muli_dsigma_evaluate: failed." ! stop ! end if end subroutine muli_dsigma_evaluate @ %def muli_dsigma_evaluate @ <>= generic :: initialize => muli_dsigma_initialize procedure :: muli_dsigma_initialize <>= subroutine muli_dsigma_initialize & (this, id, name, goal, max_nodes, dim, cuba_goal) class(muli_dsigma_t), intent(inout) :: this integer(dik), intent(in) :: id, max_nodes integer, intent(in) :: dim character(*), intent(in) :: name real(default), intent(in) :: goal, cuba_goal call this%initialize (id,name) ! 1E-4 this%rel_error_goal = goal this%max_nodes = max_nodes call this%cuba_int%set_common (dim_f=dim, dim_x=2, & ! 1E-6 eps_rel=cuba_goal, flags = 0) call this%cuba_int%set_deferred (xgiven_flat = [1.E-2_default, & 5.E-1_default + epsilon(1._default), & 1.E-2_default, 5.E-1_default - epsilon(1._default)]) ! call aq_initialize (this, id, name, d_goal, max_nodes, dim_f, & ! [8E-1_default/7E3_default, 2E-3_default, 1E-2_default, & ! 1E-1_default, one]) call this%init_error_tree (dim, [8.E-1_default/7.E3_default, & 2.E-3_default, 1.E-2_default, 1.E-1_default, & 1._default]) this%is_deferred_initialised = .true. end subroutine muli_dsigma_initialize @ %def muli_dsigma_initialize @ <>= ! procedure :: reset => muli_dsigma_reset <>= ! subroutine muli_dsigma_reset (this) ! class(muli_dsigma_t), intent(inout) :: this ! call aq_reset (this) ! call this%initialize & ! (id, name, d_goal, max_nodes, dim_f, init, cuba_goal) ! end subroutine muli_dsigma_reset @ %def muli_dsigma_reset @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{MC Integrations for QCD $2\to 2$ processes} This file contains the module [[muli_mcint]] which is the Monte Carlo generator for QCD $2\to 2$ interactions at given evolution parameter and given stratus. While [[muli_t]] takes care of generating the evolution parameter and the stratus, this module is about bookkeeping the strati and implementing a downstream importance sampling. The evolution parameter is a measure of transferred momentum and a ``stratus'' is a PDF category or, to be more precise, is whether the incoming partons are gluons or sea quarks or valence quarks. The importance sampling then subdivides the phase space of variables $\left\{ x_1, x_2, p_T \right\}$ into $n^3$ regions such that each region holds approximately $n$ interactions. Thus, we can generate a phase space point very quickly just by randomly picking a region, randomly picking a point within this region and comparing its exact cross section with the mean cross section for this actual evolution parameter and the actual stratus times the area of the picked phase space region. The mean values must be generated in the module [[muli_dsigma]] before and are given to the procedure [[sample_inclusive_generate_hit]]. Finally the generated subregions should be written to a file via [[write_to_marker]] and then reused for each later \whizard\ run. The type [[sample_inclusive_t]] holds the 16 strati, while the type [[sample_int_kind_t]] represents a single stratus, [[sample_3d_t]] is the whole $\left\{ x_1, x_2, p_T \right\}$ phase space for each stratus, [[sample_2d_t]] is the $\left\{ x_1, x_2 \right\}$ plane with a slice of $p_T$ and [[sample_region_t]] finally is a phase space region. <<[[muli_mcint.f90]]>>= <> module muli_mcint <> use constants use muli_base use tao_random_numbers !NODEP! use muli_interactions <> <> <> <> contains <> end module muli_mcint @ %def muli_mcint @ <>= integer, parameter :: max_n = 2**30 <>= real(default), parameter :: max_d = one * max_n <>= real(default), parameter, dimension(2,2) :: & unit_square = reshape([zero,zero,one,one], [2,2]) @ %def max_n max_d unit_square @ <>= public :: sample_region_t <>= type, extends (ser_class_t) :: sample_region_t integer :: n_hits = 0 integer :: n_alloc = 0 real(default), dimension(2,2) :: corners = unit_square real(default), dimension(:,:), allocatable :: hyp_hits contains <> end type sample_region_t @ %def sample_region_t @ <>= procedure :: write_to_marker => sample_region_write_to_marker <>= subroutine sample_region_write_to_marker (this, marker, status) class(sample_region_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%mark_begin ("sample_region_t") call marker%mark ("n_hits", this%n_hits) call marker%mark ("n_alloc", this%n_alloc) call marker%mark ("lower_corner", this%corners(1:2,1)) call marker%mark ("upper_corner", this%corners(1:2,2)) if (allocated (this%hyp_hits)) then call marker%mark ("hyp_hits", this%hyp_hits (1:3,:this%n_hits)) else call marker%mark_nothing ("hyp_hits") end if call marker%mark_end ("sample_region_t") end subroutine sample_region_write_to_marker @ %def sample_region_write_to_marker @ <>= procedure :: read_from_marker => sample_region_read_from_marker <>= subroutine sample_region_read_from_marker (this, marker, status) class(sample_region_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%pick_begin ("sample_region_t", status=status) call marker%pick ("n_hits", this%n_hits, status) call marker%pick ("n_alloc", this%n_alloc, status) call marker%pick ("lower_corner", this%corners(1:2,1), status) call marker%pick ("upper_corner", this%corners(1:2,2), status) if (allocated (this%hyp_hits)) deallocate (this%hyp_hits) call marker%verify_nothing ("hyp_hits", status) if (.not. status == serialize_nothing) then allocate (this%hyp_hits (3,this%n_alloc)) call marker%pick ("hyp_hits", this%hyp_hits (1:3,:this%n_hits), status) end if call marker%pick_end ("sample_region_t", status) end subroutine sample_region_read_from_marker @ %def sample_region_read_from_marker @ <>= procedure :: print_to_unit => sample_region_print_to_unit <>= subroutine sample_region_print_to_unit & (this, unit, parents, components, peers) class(sample_region_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "components of sample_region_t" write (unit, "(3x,A,I10)") "n_hits: ", this%n_hits write (unit, "(3x,A,I10)") "n_alloc: ", this%n_alloc write (unit, "(3x,4(E20.10))") "corners: ", this%corners if (allocated (this%hyp_hits) .and. this%n_hits > 0) then if (components > 0) then write (unit,"(3x,A)") "hits:" print *, shape (this%hyp_hits) write (unit, "(3(e20.10))") this%hyp_hits (1:3, this%n_hits) else write (unit, "(3x,A)") "skipping hits." end if else write (unit, "(3x,A)") "hits are not allocated." end if end subroutine sample_region_print_to_unit @ %def sample_region_print_to_unit @ <>= procedure, nopass :: get_type => sample_region_get_type <>= pure subroutine sample_region_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="sample_region_t") end subroutine sample_region_get_type @ %def sample_region_get_type @ <>= procedure :: initialize => sample_region_initialize <>= subroutine sample_region_initialize (this, n_alloc) class(sample_region_t), intent(out) :: this integer, intent(in) :: n_alloc if (allocated (this%hyp_hits)) deallocate (this%hyp_hits) allocate (this%hyp_hits (3,n_alloc)) this%n_alloc = n_alloc end subroutine sample_region_initialize @ %def sample_region_initialize @ <>= procedure :: generate_hit => sample_region_generate_hit <>= pure subroutine sample_region_generate_hit (this, rnd, area, hit) class(sample_region_t), intent(in) :: this integer, intent(in), dimension(2) :: rnd real(default), dimension(2), intent(out) :: hit real(default), intent(out) :: area call muli_mcint_generate_hit (rnd, this%corners, hit) area = this%area () end subroutine sample_region_generate_hit @ %def sample_region_generate_hit @ <>= procedure :: confirm_hit => sample_region_confirm_hit <>= subroutine sample_region_confirm_hit (this, hit) class(sample_region_t), intent(inout) :: this real(default), dimension(3), intent(in) :: hit ! print *,"sample_region_confirm_hit: ", this%n_hits, this%n_alloc, hit this%n_hits = this%n_hits + 1 if (this%n_hits <= this%n_alloc) then this%hyp_hits (1:3, this%n_hits) = hit else print *, "sample_region_confirm_hit: Region is already full." end if end subroutine sample_region_confirm_hit @ %def sample_region_confirm_hit @ <>= procedure :: split => sample_region_split <>= subroutine sample_region_split (this, pos, dimX, n_alloc, lower, upper) class(sample_region_t), intent(in) :: this type(sample_region_t), intent(out) :: lower, upper real(default), dimension(3) :: hit real(default), intent(in) :: pos integer, intent(in) :: dimX, n_alloc integer :: n_hit call lower%initialize (n_alloc) call upper%initialize (n_alloc) do n_hit = 1, this%n_hits hit = this%hyp_hits (1:3, n_hit) if (hit(dimX) < pos) then call lower%confirm_hit (hit) else call upper%confirm_hit (hit) end if end do lower%corners = this%corners upper%corners = this%corners if (dimX < 3) then lower%corners(dimX,2) = pos upper%corners(dimX,1) = pos end if end subroutine sample_region_split @ %def sample_region_split @ <>= procedure :: write_hits => sample_region_write_hits <>= subroutine sample_region_write_hits (this, unit) class(sample_region_t), intent(in) :: this integer, intent(in) :: unit integer :: n do n = 1, this%n_hits write (unit, *) this%hyp_hits (1:3,n) end do end subroutine sample_region_write_hits @ %def sample_region_write_hits @ <>= procedure :: is_full => sample_region_is_full <>= elemental logical function sample_region_is_full (this) class(sample_region_t), intent(in) :: this sample_region_is_full = this%n_alloc == this%n_hits end function sample_region_is_full @ %def sample_region_is_full @ <>= procedure :: move_components => sample_region_move_components <>= subroutine sample_region_move_components (this, that) class(sample_region_t), intent(inout) :: this class(sample_region_t), intent(out) :: that that%n_alloc = this%n_alloc that%n_hits = this%n_hits that%corners = this%corners call move_alloc (this%hyp_hits, that%hyp_hits) this%n_alloc = 0 this%n_hits = 0 end subroutine sample_region_move_components @ %def sample_region_move_components @ <>= procedure :: mean => sample_region_mean <>= elemental function sample_region_mean (this, dim) real(default) :: sample_region_mean class(sample_region_t), intent(in) :: this integer, intent(in) :: dim sample_region_mean = sum (this%hyp_hits (dim,1:this%n_hits)) / this%n_hits end function sample_region_mean @ %def sample_region_mean @ <>= procedure :: area => sample_region_area <>= elemental function sample_region_area (this) real(default) :: sample_region_area class(sample_region_t), intent(in) :: this sample_region_area = product (this%corners(1:2,2) - this%corners(1:2,1)) end function sample_region_area @ %def sample_region_area @ <>= procedure :: density => sample_region_density <>= elemental function sample_region_density (this) real(default) :: sample_region_density class(sample_region_t), intent(in) :: this sample_region_density = this%n_hits / this%area () end function sample_region_density @ %def sample_region_density @ <>= procedure :: contains => sample_region_contains <>= pure logical function sample_region_contains (this, hit) class(sample_region_t), intent(in) :: this real(default), intent(in), dimension(3) :: hit sample_region_contains = (this%corners(1,1) <= hit(1) .and. & hit(1) <= this%corners(1,2) .and. & this%corners(2,1) <= hit(2) .and. & hit(2) <= this%corners(2,2)) end function sample_region_contains @ %def sample_region_contains @ <>= procedure :: to_generator => sample_region_to_generator <>= subroutine sample_region_to_generator (this) class(sample_region_t), intent(inout) :: this if (allocated (this%hyp_hits)) deallocate (this%hyp_hits) this%n_alloc = 0 end subroutine sample_region_to_generator @ %def sample_region_to_generator @ <>= public :: sample_2d_t <>= type, extends (ser_class_t) :: sample_2d_t integer :: n_regions = 0 integer :: n_alloc = 0 integer :: n_hits = 0 real(default), dimension(2) :: range = [0,1] type(sample_region_t), dimension(:), allocatable :: regions contains <> end type sample_2d_t @ %def sample_2d_t @ <>= procedure :: write_to_marker => sample_2d_write_to_marker <>= subroutine sample_2d_write_to_marker (this, marker, status) class(sample_2d_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%mark_begin ("sample_2d_t") call marker%mark ("n_regions", this%n_regions) call marker%mark ("n_alloc", this%n_alloc) call marker%mark ("n_hits", this%n_hits) call marker%mark ("range", this%range) if (this%n_regions > 0) then call marker%mark_instance_begin & (this%regions(1), name="sample_2d_t", shape=shape (this%regions)) do n = 1, this%n_regions call sample_region_write_to_marker (this%regions(n), marker, status) end do call marker%mark_instance_end () end if call marker%mark_end ("sample_2d_t") end subroutine sample_2d_write_to_marker @ %def sample_2d_write_to_marker @ <>= procedure :: read_from_marker => sample_2d_read_from_marker <>= subroutine sample_2d_read_from_marker (this, marker, status) class(sample_2d_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%pick_begin ("sample_2d_t", status=status) call marker%pick ("n_regions", this%n_regions, status) call marker%pick ("n_alloc", this%n_alloc, status) call marker%pick ("n_hits", this%n_hits, status) call marker%pick ("range", this%range, status) if (this%n_regions > 0) then call marker%pick_begin ("regions", status=status) allocate (this%regions (this%n_regions)) do n = 1, this%n_regions call sample_region_read_from_marker (this%regions(n), marker, status) end do call marker%pick_end ("regions", status) end if call marker%pick_end ("sample_2d_t", status) end subroutine sample_2d_read_from_marker @ %def sample_2d_read_from_marker @ <>= procedure :: print_to_unit => sample_2d_print_to_unit <>= subroutine sample_2d_print_to_unit (this, unit, parents, components, peers) class(sample_2d_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: n write (unit, "(1x,A)") "components of sample_2d_t" write (unit, "(3x,A,I10)") "n_regions: ", this%n_regions write (unit, "(3x,A,I10)") "n_alloc: ", this%n_alloc write (unit, "(3x,A,2(E20.10))") "range: ", this%range if (allocated (this%regions)) then if (components > 0) then write (unit, "(3x,A)") "regions:" do n = 1, this%n_regions call this%regions(n)%print_to_unit & (unit, parents, components-1, peers) end do else write (unit, "(3x,A)") "skipping regions." end if else write (unit, "(3x,A)") "regions are not allocated." end if end subroutine sample_2d_print_to_unit @ %def sample_2d_print_to_unit @ <>= procedure, nopass :: get_type => sample_2d_get_type <>= pure subroutine sample_2d_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="sample_2d_t") end subroutine sample_2d_get_type @ %def sample_2d_get_type @ <>= procedure :: initialize => sample_2d_initialize <>= subroutine sample_2d_initialize (this, n_alloc) class(sample_2d_t), intent(out) :: this integer, intent(in) :: n_alloc integer :: n if (allocated (this%regions)) deallocate (this%regions) allocate (this%regions (n_alloc)) this%n_alloc = n_alloc this%n_regions = 1 call this%regions(1)%initialize (n_alloc) ! do n = 1, n_alloc ! call this%regions(n)%initialize (n_alloc) ! end do end subroutine sample_2d_initialize @ %def sample_2d_initialize @ <>= procedure :: contains => sample_2d_contains <>= pure logical function sample_2d_contains (this, pts2) class(sample_2d_t), intent(in) :: this real(default), intent(in) :: pts2 sample_2d_contains = this%range(1) <= pts2 .and. pts2 <= this%range(2) end function sample_2d_contains @ %def sample_2d_contains @ <>= procedure :: generate_hit => sample_2d_generate_hit <>= pure subroutine sample_2d_generate_hit (this, rnd, boost, hit, region) class(sample_2d_t), intent(in) :: this integer, dimension(3), intent(in) :: rnd integer, intent(out) :: region integer :: n, sum real(default), dimension(2), intent(out) :: hit real(default), intent(out) :: boost if (0 < this%n_hits .and. this%n_hits < 10) then !!! this should be improved sum = modulo(rnd(1),this%n_hits) + 1 region = 0 do while (sum > 0) region = region + 1 sum = sum - this%regions(region)%n_hits end do call this%regions(region)%generate_hit (rnd(2:3), boost, hit) boost = boost * this%n_hits / this%regions(region)%n_hits else if (this%n_regions > 1) then !!! this should be improved region = modulo(rnd(1), this%n_regions) + 1 call this%regions(region)%generate_hit (rnd(2:3), boost, hit) boost = boost * this%n_regions else region = 1 call this%regions(1)%generate_hit (rnd(2:3), boost, hit) end if end if end subroutine sample_2d_generate_hit ! pure subroutine sample_2d_generate_hit (this, rnd, boost, hit, region) ! class(sample_2d_t), intent(in) :: this ! integer, dimension(3), intent(in) :: rnd ! integer, intent(out) :: region ! real(double), dimension(2), intent(out) :: hit ! real(double), intent(out) :: boost ! region = modulo(rnd(1), this%n_regions) + 1 !!! this should be improved ! call this%regions(region)%generate_hit (rnd(2:3), boost, hit) ! boost = boost * this%n_regions ! end subroutine sample_2d_generate_hit @ %def sample_2d_generate_hit @ <>= procedure :: confirm_hit => sample_2d_confirm_hit <>= subroutine sample_2d_confirm_hit (this, hit, region, full) class(sample_2d_t), intent(inout) :: this integer, intent(in) :: region real(default), dimension(3), intent(in) :: hit type(sample_region_t), allocatable :: old_region real(default), dimension(2) :: mean, var, diff, cm, cv, c integer :: n, n_alloc, dim logical, intent(out) :: full this%n_hits = this%n_hits + 1 if (region <= this%n_alloc) then full = .false. call this%regions(region)%confirm_hit (hit) n_alloc = this%regions(region)%n_alloc if (this%regions(region)%is_full()) then if (this%is_full()) then full = .true. else this%n_regions = this%n_regions + 1 allocate (old_region) call this%regions(region)%move_components (old_region) mean = sum (old_region%hyp_hits(1:2,:), dim=2) / n_alloc var = 0 do n = 1, n_alloc var = var + abs(mean-old_region%hyp_hits(1:2,n)) end do var = var / n_alloc diff = old_region%corners(1:2,2) - old_region%corners(1:2,1) cm = abs ([0.5_default,0.5_default] - & (old_region%corners(1:2,2) - mean) / diff) cv = abs(2*([0.25_default,0.25_default] - var / diff)) c = max(cm,cv) if (c(1) < c(2)) then dim = 2 else dim = 1 end if call old_region%split (mean(dim), dim, this%n_alloc, & this%regions(region), this%regions(this%n_regions)) end if end if else write (*,*) "sample_2d_confirm_hit: Region ", region, & " not allocated." end if end subroutine sample_2d_confirm_hit @ %def sample_2d_confirm_hit @ <>= procedure :: split => sample_2d_split <>= recursive subroutine sample_2d_split (this, n_alloc, pos, lower, upper) class(sample_2d_t), intent(in) :: this integer, intent(in) :: n_alloc real(default), intent(in) :: pos type(sample_2d_t), intent(out) :: lower, upper integer :: n_r, n_h real(default), dimension(3) :: hit ! print *,"sample_2d_split: ", pos, this%range call lower%initialize (4*n_alloc) call upper%initialize (4*n_alloc) do n_r = this%n_regions, 1, -1 do n_h = 1, this%regions(n_r)%n_hits hit = this%regions(n_r)%hyp_hits (1:3,n_h) if (hit(3) > pos) then call upper%push (hit) else call lower%push (hit) end if end do end do lower%range = [this%range(1), pos] upper%range = [pos, this%range(2)] end subroutine sample_2d_split ! subroutine sample_2d_split (this, n_alloc, pos, lower, upper) ! class(sample_2d_t), intent(in) :: this ! integer, intent(in) :: n_alloc ! real(default), intent(in) :: pos ! type(sample_2d_t), intent(out) :: lower, upper ! integer :: n, n_hit ! real(default), dimension(3) :: hit ! allocate (lower%regions (n_alloc)) ! allocate (upper%regions (n_alloc)) ! !$OMP PARALLEL DO FIRSTPRIVATE (this, pos, n_alloc) SHARED (lower, upper) ! do n = 1, this%n_regions ! call sample_region_split (this%regions(n), pos, 3, n_alloc, & ! lower%regions(n),upper%regions(n)) ! end do ! !$OMP END PARALLEL DO ! lower%n_regions = this%n_regions ! upper%n_regions = this%n_regions ! lower%n_alloc = n_alloc ! upper%n_alloc = n_alloc ! lower%range = [this%range(1), pos] ! upper%range = [pos, this%range(2)] ! end subroutine sample_2d_split @ %def sample_2d_split @ <>= procedure :: push => sample_2d_push <>= subroutine sample_2d_push (this, hit) class(sample_2d_t), intent(inout) :: this real(default), dimension(3), intent(in) :: hit integer :: region logical :: full do region = 1, this%n_regions if (this%regions(region)%contains (hit)) then call this%confirm_hit (hit, region, full) ! call this%regions(region)%confirm_hit (hit) if (full) print *,"sample_2d_push: region is full now" exit end if end do if (region > this%n_regions) & print *, "sample_2d_push: no region contains ", hit end subroutine sample_2d_push @ %def sample_2d_push @ <>= procedure :: write_hits => sample_2d_write_hits <>= subroutine sample_2d_write_hits (this, unit) class(sample_2d_t), intent(in) :: this integer, intent(in) :: unit integer :: n do n = 1, this%n_regions call this%regions(n)%write_hits (unit) end do end subroutine sample_2d_write_hits @ %def sample_2d_write_hits @ <>= procedure :: is_full => sample_2d_is_full <>= elemental logical function sample_2d_is_full (this) class(sample_2d_t), intent(in) :: this sample_2d_is_full = this%n_alloc == this%n_regions end function sample_2d_is_full @ %def sample_2d_is_full @ <>= procedure :: move_components => sample_2d_move_components <>= subroutine sample_2d_move_components (this, that) class(sample_2d_t), intent(inout) :: this class(sample_2d_t), intent(out) :: that that%n_alloc = this%n_alloc that%n_regions = this%n_regions that%n_hits = this%n_hits that%range = this%range call move_alloc (this%regions, that%regions) this%n_alloc = 0 this%n_regions = 0 this%n_hits = 0 this%range = [zero,zero] end subroutine sample_2d_move_components @ %def sample_2d_move_components @ <>= procedure :: thickness => sample_2d_thickness <>= elemental function sample_2d_thickness (this) class(sample_2d_t), intent(in) :: this real(default) :: sample_2d_thickness sample_2d_thickness = this%range(2) - this%range(1) end function sample_2d_thickness @ <>= procedure :: analyse => sample_2d_analyse <>= subroutine sample_2d_analyse (this, dir, file) class(sample_2d_t), intent(in) :: this character(*), intent(in) :: dir, file integer :: u real(default), dimension(1:2,0:100,0:100) :: grid integer, dimension(0:100,0:100) :: i_grid integer :: r, x, y integer, dimension(2,2) :: i call generate_unit (u) print *, "sample_2d_analyse: ", dir // "/" // file open (u, file=dir//"/"//file) do x = 0, 100 do y = 0, 100 grid(1:2,x,y) = [-one,-one] end do end do do r = 1, this%n_regions i = int(this%regions(r)%corners*1E2_default) do x = i(1,1), i(1,2) do y = i(2,1), i(2,2) i_grid(x,y) = this%regions(r)%n_hits grid(1,x,y) = one / this%regions(r)%area () grid(2,x,y) = this%regions(r)%density () end do end do end do do x = 0, 100 do y = 0, 100 write (u, *) x, y, i_grid(x,y), grid(1:2,x,y) end do write (u, *) end do close (u) end subroutine sample_2d_analyse @ %def sample_2d_analyse @ <>= procedure :: to_generator => sample_2d_to_generator <>= subroutine sample_2d_to_generator (this) class(sample_2d_t), intent(inout) :: this integer :: region do region = 1, this%n_regions call this%regions(region)%to_generator () end do end subroutine sample_2d_to_generator @ %def sample_2d_to_generator @ <>= procedure :: mean => sample_2d_mean <>= elemental function sample_2d_mean (this, dim) result (mean) class(sample_2d_t), intent(in) :: this integer, intent(in) :: dim real(default) :: mean integer :: region, hit mean = zero do region = 1, this%n_regions do hit = 1, this%regions(region)%n_hits mean = mean + this%regions(region)%hyp_hits (dim, hit) end do end do mean = mean / this%n_hits end function sample_2d_mean @ %def sample_2d_mean @ <>= public :: sample_3d_t <>= type, extends (ser_class_t) :: sample_3d_t integer::n_slices=0 integer::n_alloc=0 type(sample_2d_t), dimension(:),allocatable::slices contains <> end type sample_3d_t @ %def sample_3d_t @ <>= procedure :: write_to_marker => sample_3d_write_to_marker <>= subroutine sample_3d_write_to_marker (this, marker, status) class(sample_3d_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%mark_begin ("sample_3d_t") call marker%mark ("n_slices", this%n_slices) call marker%mark ("n_alloc", this%n_alloc) if (this%n_slices > 0) then call marker%mark_instance_begin & (this%slices(1), "slices", shape=shape(this%slices)) do n = 1, this%n_slices call sample_2d_write_to_marker (this%slices(n), marker, status) end do call marker%mark_instance_end () end if call marker%mark_end ("sample_3d_t") end subroutine sample_3d_write_to_marker @ %def sample_3d_write_to_marker @ <>= procedure :: read_from_marker => sample_3d_read_from_marker <>= subroutine sample_3d_read_from_marker (this, marker, status) class(sample_3d_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%pick_begin ("sample_3d_t", status=status) call marker%pick ("n_slices", this%n_slices, status) call marker%pick ("n_alloc", this%n_alloc, status) if (this%n_slices > 0) then call marker%pick_instance_begin ("slices", status=status) allocate(this%slices (this%n_slices)) do n = 1, this%n_slices call sample_2d_read_from_marker (this%slices(n), marker, status) end do call marker%pick_instance_end (status) end if call marker%pick_end ("sample_3d_t", status) end subroutine sample_3d_read_from_marker @ %def sample_3d_read_from_marker @ <>= procedure :: print_to_unit => sample_3d_print_to_unit <>= subroutine sample_3d_print_to_unit (this, unit, parents, components, peers) class(sample_3d_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: n write (unit, "(1x,A)") "components of sample_3d_t" write (unit, "(3x,A,I10)") "n_slices: ", this%n_slices write (unit, "(3x,A,I10)") "n_alloc: ", this%n_alloc if (allocated (this%slices)) then if (components > 0) then do n = 1, this%n_slices call this%slices(n)%print_to_unit (unit, parents, components-1, peers) end do else write (unit, "(3x,A)") "skipping slices." end if else write (unit, "(3x,A)") "slices are not allocated." end if end subroutine sample_3d_print_to_unit @ %def sample_3d_print_to_unit @ <>= procedure, nopass :: get_type => sample_3d_get_type <>= pure subroutine sample_3d_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="sample_3d_t") end subroutine sample_3d_get_type @ %def sample_3d_get_type @ <>= procedure :: measure => sample_3d_measure <>= elemental function sample_3d_measure (this) real(default) :: sample_3d_measure class(sample_3d_t), intent(in) :: this sample_3d_measure = one end function sample_3d_measure @ %def sample_3d_measure @ <>= procedure :: to_generator => sample_3d_to_generator <>= subroutine sample_3d_to_generator(this) class(sample_3d_t), intent(inout)::this integer::slice do slice=1,this%n_slices call this%slices(slice)%to_generator() end do end subroutine sample_3d_to_generator @ %def sample_3d_to_generator @ <>= generic :: initialize => sample_3d_initialize procedure :: sample_3d_initialize <>= subroutine sample_3d_initialize (this, n_alloc) class(sample_3d_t), intent(out) :: this integer, intent(in) :: n_alloc if (allocated (this%slices)) deallocate (this%slices) if (n_alloc > 0) then allocate (this%slices (n_alloc)) this%n_alloc = n_alloc this%n_slices = 1 call this%slices(1)%initialize (n_alloc) else this%n_alloc = 0 end if end subroutine sample_3d_initialize @ %def sample_3d_initialize @ <>= procedure :: sample_3d_generate_hit generic :: generate_hit => sample_3d_generate_hit <>= pure subroutine sample_3d_generate_hit & (this, rnd, pts2, boost, hit, region, slice) class(sample_3d_t), intent(in) :: this integer, intent(in), dimension(3) :: rnd real(default), intent(in) :: pts2 integer, intent(out) :: slice, region real(default), dimension(3), intent(out) :: hit real(default), intent(out) :: boost if (this%n_slices == 0) then call muli_mcint_generate_hit (rnd, unit_square, hit(1:2)) boost = 1._default slice = 1 region = 1 else do slice = 1, this%n_slices if (this%slices(slice)%contains (pts2)) exit end do call this%slices(slice)%generate_hit (rnd, boost, hit(1:2), region) end if hit(3) = pts2 end subroutine sample_3d_generate_hit @ %def sample_3d_generate_hit @ <>= procedure :: sample_3d_confirm_hit generic :: confirm_hit => sample_3d_confirm_hit <>= subroutine sample_3d_confirm_hit (this, hit, region, slice) class(sample_3d_t), intent(inout) :: this integer, intent(in) :: slice, region real(default), intent(in), dimension(3) :: hit type(sample_2d_t), allocatable :: old_slice integer :: n logical :: full if (this%n_alloc < slice) then print *, "sample_3d_confirm_hit: Slice ", slice, " not allocated." else ! if (.not. allocated (this%slices)) call this%initialize (2) call this%slices(slice)%confirm_hit (hit, region, full) if (full) then if (this%n_alloc == this%n_slices) call this%enlarge () this%n_slices = this%n_slices + 1 allocate (old_slice) call this%slices(slice)%move_components (old_slice) call sample_2d_split (old_slice, this%n_alloc, & old_slice%mean(3), this%slices(slice), & this%slices(this%n_slices)) end if end if end subroutine sample_3d_confirm_hit @ %def sample_3d_confirm_hit @ <>= procedure :: enlarge => sample_3d_enlarge <>= subroutine sample_3d_enlarge (this) class(sample_3d_t), intent(inout) :: this type(sample_2d_t), allocatable, dimension(:) :: old_slices integer :: n print *, "sample_3d_enlarge" call move_alloc (this%slices, old_slices) this%n_alloc = this%n_alloc * 2 allocate (this%slices (this%n_alloc)) do n = 1, size(old_slices) call old_slices(n)%move_components(this%slices(n)) end do end subroutine sample_3d_enlarge @ %def sample_3d_enlarge @ <>= public :: sample_int_kind_t <>= type, extends (sample_3d_t) :: sample_int_kind_t integer :: n_proc = 0 integer(kind=i64) :: n_tries = 0 integer :: n_hits = 0 integer :: n_over = 0 integer, dimension(:), allocatable :: hits, weights, processes real(default) :: overall_boost = 1E-1_default contains <> end type sample_int_kind_t @ %def sample_int_kind_t @ <>= procedure :: write_to_marker => sample_int_kind_write_to_marker <>= subroutine sample_int_kind_write_to_marker (this, marker, status) class(sample_int_kind_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("sample_int_kind_t") call sample_3d_write_to_marker (this, marker, status) call marker%mark ("n_hits", this%n_hits) call marker%mark ("n_proc", this%n_proc) call marker%mark ("boost", this%overall_boost) if (this%n_hits > 0) then call marker%mark ("hits", this%hits) end if if (this%n_proc > 0) then call marker%mark ("processes", this%processes) call marker%mark ("weights", this%weights) end if call marker%mark_end ("sample_int_kind_t") end subroutine sample_int_kind_write_to_marker @ %def sample_int_kind_write_to_marker @ <>= procedure :: read_from_marker => sample_int_kind_read_from_marker <>= subroutine sample_int_kind_read_from_marker (this, marker, status) class(sample_int_kind_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("sample_int_kind_t", status=status) call sample_3d_read_from_marker (this, marker, status) call marker%pick ("n_hits", this%n_hits, status) call marker%pick ("n_proc", this%n_proc, status) call marker%pick ("boost", this%overall_boost, status) if (this%n_hits > 0) then allocate (this%hits (this%n_hits)) call marker%pick ("hits", this%hits, status) end if if (this%n_proc > 0) then allocate (this%processes (this%n_proc)) call marker%pick ("processes", this%processes, status) allocate (this%weights (this%n_proc)) call marker%pick ("weights", this%weights, status) end if call marker%pick_end ("sample_int_kind_t", status) end subroutine sample_int_kind_read_from_marker @ %def sample_int_kind_read_from_marker @ <>= procedure :: print_to_unit => sample_int_kind_print_to_unit <>= subroutine sample_int_kind_print_to_unit (this, unit, parents, components, peers) class(sample_int_kind_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: n if (parents > 0) call sample_3d_print_to_unit & (this, unit, parents, components, peers) write (unit, "(1x,A)") "components of sample_int_kind_t" write (unit, "(3x,A,I10)") "n_hits: ", this%n_hits write (unit, "(3x,A,I10)") "n_proc: ", this%n_proc write (unit, "(3x,A,E14.7)") "overall_boost: ", this%overall_boost write (unit, "(3x,A)") "hits:" write (unit, "(3x,10(I0,1x))") this%hits(1:this%n_hits) write (unit, "(3x,A)") "weights:" write (unit, "(3x,10(I0,1x))") this%weights write (unit, "(3x,A)") "processes:" write (unit, "(3x,2(I0,1x))") this%processes end subroutine sample_int_kind_print_to_unit @ %def sample_int_kind_print_to_unit @ <>= procedure, nopass :: get_type => sample_int_kind_get_type <>= pure subroutine sample_int_kind_get_type (type) character(:),allocatable, intent(out) :: type allocate (type, source="sample_int_kind_t") end subroutine sample_int_kind_get_type @ %def sample_int_kind_get_type @ <>= procedure :: to_generator => sample_int_kind_to_generator <>= subroutine sample_int_kind_to_generator(this) class(sample_int_kind_t), intent(inout)::this integer::int_kind if (allocated(this%hits))deallocate(this%hits) call sample_3d_to_generator(this) end subroutine sample_int_kind_to_generator @ %def sample_int_kind_to_generator @ <>= procedure :: process_id => sample_int_kind_process_id <>= elemental integer function sample_int_kind_process_id (this, subprocess) class(sample_int_kind_t), intent(in) :: this integer, intent(in) :: subprocess sample_int_kind_process_id = this%processes(subprocess) end function sample_int_kind_process_id @ %def sample_int_kind_process_id @ <>= procedure :: sample_int_kind_initialize generic :: initialize => sample_int_kind_initialize <>= subroutine sample_int_kind_initialize (this, n_alloc, processes, overall_boost) class(sample_int_kind_t), intent(out) :: this integer, intent(in) :: n_alloc integer, intent(in), dimension(:) :: processes real(default), optional, intent(in) :: overall_boost integer :: s, n s = size(processes) call sample_3d_initialize (this, n_alloc) if (allocated (this%hits)) deallocate (this%hits) allocate (this%hits (n_alloc)) if (allocated (this%weights)) deallocate (this%weights) allocate (this%weights(s)) if (allocated (this%processes)) deallocate (this%processes) allocate (this%processes(s), source=processes) do n = 1, s this%weights(n) = 0 end do this%n_alloc = n_alloc this%n_hits = 0 this%n_proc = s if (present (overall_boost)) this%overall_boost = overall_boost this%overall_boost = this%overall_boost * this%n_proc ! print *, this%weights end subroutine sample_int_kind_initialize @ %sample_int_kind_initialize @ <>= procedure :: sample_int_kind_generate_hit <>= pure subroutine sample_int_kind_generate_hit & (this, rnd, pts2, boost, hit, region, slice, subprocess) class(sample_int_kind_t), intent(in) :: this integer, dimension(4), intent(in) :: rnd real(default), intent(in) :: pts2 real(default), dimension(3), intent(out) :: hit integer, intent(out) :: region, slice, subprocess real(default), intent(out) :: boost integer :: n_n ! print *, rnd, pts2, boost, hit, region, slice, subprocess call sample_3d_generate_hit & (this, rnd(2:4), pts2, boost, hit, region, slice) n_n = modulo(rnd(1), this%n_hits + size(this%weights)) + 1 if (n_n > this%n_hits) then subprocess = n_n - this%n_hits else subprocess = this%hits(n_n) end if boost = boost * this%overall_boost * (this%n_proc + this%n_hits) / & (this%n_proc * (this%weights(subprocess) + 1)) end subroutine sample_int_kind_generate_hit @ %def sample_int_kind_generate_hit @ <>= procedure :: mcgenerate_hit => sample_int_kind_mcgenerate_hit generic :: generate_hit => sample_int_kind_generate_hit <>= subroutine sample_int_kind_mcgenerate_hit (this, pts2, mean, & integrand_kind, tao_rnd, process_id, cart_hit) class(sample_int_kind_t), intent(inout) :: this integer, intent(in) :: integrand_kind real(default), intent(in) :: pts2, mean type(tao_random_state), intent(inout) :: tao_rnd real(default), dimension(3), intent(out) :: cart_hit integer, intent(out) :: process_id real(default) :: boost integer :: region, slice, subprocess integer, dimension(4) :: i_rnd real(default) :: dddsigma, d_rnd real(default), dimension(3) :: hyp_hit MC: do this%n_tries = this%n_tries + 1 call tao_random_number (tao_rnd, i_rnd) call tao_random_number (tao_rnd, d_rnd) ! print *, pts2, mean, integrand_kind, process_id, cart_hit call this%generate_hit (i_rnd, pts2, boost, hyp_hit, region, & slice, subprocess) process_id = this%process_id(subprocess) call interactions_dddsigma_reg (process_id, integrand_kind, & hyp_hit, cart_hit, dddsigma) dddsigma = dddsigma * boost if (d_rnd*mean < dddsigma) then exit MC end if end do MC if (mean < dddsigma) then call this%confirm_hit (hyp_hit, region, slice, subprocess, .true.) else call this%confirm_hit (hyp_hit, region, slice, subprocess, .false.) end if end subroutine sample_int_kind_mcgenerate_hit @ %def sample_int_kind_mcgenerate_hit @ <>= procedure :: sample_int_kind_confirm_hit generic :: confirm_hit => sample_int_kind_confirm_hit <>= subroutine sample_int_kind_confirm_hit & (this, hit, region, slice, subprocess, over) class(sample_int_kind_t), intent(inout) :: this real(default), dimension(3), intent(in) :: hit integer, intent(in) :: region, slice, subprocess integer, dimension(:), allocatable :: tmp_hits logical, optional, intent(in) :: over this%n_hits = this%n_hits + 1 if (present(over)) then if (over) then this%n_over = this%n_over + 1 this%overall_boost = this%overall_boost / 1.1_default else this%overall_boost = this%overall_boost * 1.0001_default end if end if if (0 < size(this%hits)) then if (this%n_hits > size(this%hits)) then call move_alloc (this%hits, tmp_hits) allocate (this%hits (2*size(tmp_hits))) this%hits (1:size(tmp_hits)) = tmp_hits end if this%hits(this%n_hits) = subprocess end if this%weights(subprocess) = this%weights(subprocess) + 1 call sample_3d_confirm_hit (this, hit, region, slice) end subroutine sample_int_kind_confirm_hit @ %def sample_int_kind_confirm_hit @ <>= procedure :: analyse => sample_int_kind_analyse <>= subroutine sample_int_kind_analyse (this, dir, prefix) class(sample_int_kind_t), intent(in) :: this character(*), intent(in) :: dir, prefix integer :: slices_unit, subprocs_unit integer :: n, slice character(3) :: slice_name integer, dimension(:), allocatable :: int_a real(default), dimension(:), allocatable :: real_a call generate_unit (slices_unit) print *, "sample_int_kind_analyse: ", dir // "/" // prefix // & "slice_distribution.plot" open (slices_unit, file=dir // "/" // prefix // "slice_distribution.plot") call generate_unit (subprocs_unit) print *, "sample_int_kind_analyse: ", dir // "/" // prefix // & "subproc_distribution.plot" open (subprocs_unit, file=dir // "/" // prefix // & "subproc_distribution.plot") allocate (real_a (this%n_slices)) allocate (int_a (this%n_slices)) do n = 1, this%n_slices real_a(n) = this%slices(n)%range(1) end do call misc_sort (real_a, int_a) do n = 1, size (this%weights) if (this%n_hits > 0) then write (subprocs_unit, fmt=*) real(this%weights(n)), & real(this%weights(n)+1) / this%n_hits else write (subprocs_unit, fmt=*) 0, 0 end if end do do n = 1, this%n_slices slice = int_a (n) call integer_with_leading_zeros (n, 3, slice_name) call sample_2d_analyse (this%slices(slice), dir, prefix // & slice_name // ".plot") print *, this%n_hits, this%slices(slice)%range(2) - & this%slices(slice)%range(1) if (this%n_hits > 0) then write (slices_unit, *) this%slices(slice)%range(1), & this%slices(slice)%range(2), this%slices(slice)%n_hits, & real (this%slices(slice)%n_hits) / (this%n_hits * & (this%slices(slice)%range(2) - this%slices(slice)%range(1))) else write (slices_unit, *) this%slices(slice)%range(1), & this%slices(slice)%range(2), this%slices(slice)%n_hits, zero end if end do write (slices_unit, *) one, zero, zero, zero close (slices_unit) close (subprocs_unit) end subroutine sample_int_kind_analyse @ %def sample_int_kind_analyse @ <>= public :: sample_inclusive_t <>= type, extends (ser_class_t) :: sample_inclusive_t integer :: n_alloc = 0 integer(kind=i64) :: n_tries_sum = i_zero integer(kind=i64) :: n_over_sum = i_zero integer(kind=i64) :: n_hits_sum = i_zero type(sample_int_kind_t), dimension(:), allocatable :: int_kinds contains <> end type sample_inclusive_t @ %def sample_inclusive_t @ <>= procedure :: write_to_marker => sample_inclusive_write_to_marker <>= subroutine sample_inclusive_write_to_marker (this, marker, status) class(sample_inclusive_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n call marker%mark_begin ("sample_inclusive_t") call marker%mark ("n_alloc", this%n_alloc) if (allocated (this%int_kinds)) then call marker%mark_begin (tag="int_kinds", shape=shape(this%int_kinds)) do n = 1, size(this%int_kinds) call this%int_kinds(n)%write_to_marker (marker, status) end do call marker%mark_instance_end () else call marker%mark_empty (tag="int_kinds", shape=[0]) end if call marker%mark_end ("sample_inclusive_t") end subroutine sample_inclusive_write_to_marker @ %def sample_inclusive_write_to_marker @ <>= procedure :: read_from_marker => sample_inclusive_read_from_marker <>= subroutine sample_inclusive_read_from_marker (this, marker, status) class(sample_inclusive_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status integer :: n integer, dimension(:), allocatable :: s call marker%pick_begin ("sample_inclusive_t", status=status) call marker%pick ("n_alloc", this%n_alloc, status) call marker%pick_begin ("int_kinds", shape=s, status=status) if (s(1) > 0) then do n = 1, size(this%int_kinds) call this%int_kinds(n)%read_from_marker (marker, status) end do call marker%pick_end ("int_kinds",status) end if call marker%pick_end ("sample_inclusive_t", status) end subroutine sample_inclusive_read_from_marker @ %def sample_inclusive_read_from_marker @ <>= procedure :: print_to_unit => sample_inclusive_print_to_unit <>= subroutine sample_inclusive_print_to_unit (this, unit, parents, components, peers) class(sample_inclusive_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer :: n write (unit, "(1x,A)") "components of sample_inclusive_t" write (unit, "(3x,A,I10)") "n_alloc: ", this%n_alloc if (allocated (this%int_kinds)) then if (components > 0) then write (unit, "(3x,A)") "int_kinds:" do n = 1, this%n_alloc call this%int_kinds(n)%print_to_unit & (unit, parents, components-1, peers) end do else write (unit, "(3x,A)") "skipping int_kinds." end if else write (unit, "(3x,A)") "int_kinds are not allocated." end if end subroutine sample_inclusive_print_to_unit @ %def sample_inclusive_print_to_unit @ <>= procedure, nopass :: get_type => sample_inclusive_get_type <>= pure subroutine sample_inclusive_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source = "sample_inclusive_t") end subroutine sample_inclusive_get_type @ %def sample_inclusive_get_type @ <>= procedure :: process_id => sample_inclusive_process_id <>= elemental integer function sample_inclusive_process_id & (this, subprocess, int_kind) class(sample_inclusive_t), intent(in) :: this integer, intent(in) :: subprocess, int_kind sample_inclusive_process_id = & this%int_kinds(int_kind)%processes (subprocess) end function sample_inclusive_process_id @ %def sample_inclusive_process_id @ <>= procedure :: initialize => sample_inclusive_initialize <>= subroutine sample_inclusive_initialize & (this, n_alloc, sizes, processes, overall_boost) class(sample_inclusive_t), intent(out) :: this integer, intent(in) :: n_alloc integer, dimension(:), intent(in) :: sizes, processes real(default), optional, intent(in) :: overall_boost integer :: n, sum this%n_tries_sum = i_zero this%n_over_sum = 0 this%n_alloc = size(sizes) if (allocated(this%int_kinds)) deallocate (this%int_kinds) allocate (this%int_kinds (this%n_alloc)) sum = 0 do n = 1, this%n_alloc call this%int_kinds(n)%initialize (n_alloc, & processes(sum+1:sum+sizes(n)), overall_boost) sum = sum + sizes(n) end do end subroutine sample_inclusive_initialize @ %def sample_inclusive_initialize @ <>= procedure :: finalize => sample_inclusive_finalize <>= subroutine sample_inclusive_finalize (this) class(sample_inclusive_t), intent(inout) :: this deallocate (this%int_kinds) this%n_alloc = 0 end subroutine sample_inclusive_finalize @ %def sample_inclusive_finalize @ <>= procedure :: generate_hit => sample_inclusive_generate_hit <>= pure subroutine sample_inclusive_generate_hit & (this, rnd, pts2, int_kind, hit, region, boost, slice, process) class(sample_inclusive_t), intent(in) :: this integer, dimension(4), intent(in) :: rnd real(default), intent(in) :: pts2 integer, intent(in) :: int_kind real(default), dimension(3), intent(out) :: hit integer, intent(out) :: region, slice, process real(default), intent(out) :: boost call this%int_kinds(int_kind)%generate_hit & (rnd, pts2, boost, hit, region, slice, process) end subroutine sample_inclusive_generate_hit @ %def sample_inclusive_generate_hit @ <>= procedure :: mcgenerate_hit => sample_inclusive_mcgenerate_hit <>= subroutine sample_inclusive_mcgenerate_hit & (this, pts2, mean, integrand_kind, tao_rnd, process_id, cart_hit) class(sample_inclusive_t), intent(inout) :: this real(default), intent(in) :: pts2, mean integer, intent(in) :: integrand_kind type(tao_random_state), intent(inout) :: tao_rnd real(default), dimension(3), intent(out) :: cart_hit integer, intent(out) :: process_id ! print *, "sample_inclusive_mcgenerate_hit & ! (this,",pts2,mean,integrand_kind,process_id,cart_hit,")" ! print *, allocated (this%int_kinds) call sample_int_kind_mcgenerate_hit (this%int_kinds(integrand_kind), & pts2, mean, integrand_kind, tao_rnd, process_id, cart_hit) end subroutine sample_inclusive_mcgenerate_hit @ %def sample_inclusive_mcgenerate_hit @ <>= procedure :: confirm_hit => sample_inclusive_confirm_hit <>= subroutine sample_inclusive_confirm_hit & (this, hit, int_kind, region, slice, process, over) class(sample_inclusive_t), intent(inout) :: this real(default), dimension(3), intent(in) :: hit integer, intent(in) :: int_kind, region, slice, process logical, optional, intent(in) :: over call this%int_kinds(int_kind)%confirm_hit & (hit, region, slice, process, over) end subroutine sample_inclusive_confirm_hit @ %def sample_inclusive_confirm_hit @ <>= procedure :: sum_up => sample_inclusive_sum_up <>= subroutine sample_inclusive_sum_up (this) class(sample_inclusive_t), intent(inout) :: this integer :: n this%n_tries_sum = i_zero this%n_hits_sum = i_zero this%n_over_sum = i_zero do n = 1, this%n_alloc this%n_tries_sum = this%n_tries_sum+this%int_kinds(n)%n_tries this%n_hits_sum = this%n_hits_sum+this%int_kinds(n)%n_hits this%n_over_sum = this%n_over_sum+this%int_kinds(n)%n_over end do end subroutine sample_inclusive_sum_up @ %def sample_inclusive_sum_up @ <>= procedure :: analyse => sample_inclusive_analyse <>= subroutine sample_inclusive_analyse (this, dir, subdirs) class(sample_inclusive_t), intent(in) :: this character(*), intent(in) :: dir logical, intent(in) :: subdirs integer :: inclusive_unit integer :: n, n_hits character(2) :: sample_name call generate_unit (inclusive_unit) open (inclusive_unit, file = dir // "/int_kinds.plot") n_hits = 0 do n = 1, size(this%int_kinds) n_hits = n_hits + this%int_kinds(n)%n_hits end do do n = 1, size(this%int_kinds) write (inclusive_unit, *) n, real(this%int_kinds(n)%n_hits) / n_hits call integer_with_leading_zeros (n, 2, sample_name) if (subdirs) then call sample_int_kind_analyse (this%int_kinds(n), & dir // "/" // sample_name, "") else call sample_int_kind_analyse (this%int_kinds(n), & dir, sample_name // "_") end if end do close (inclusive_unit) end subroutine sample_inclusive_analyse @ %def sample_inclusive_analyse @ <>= procedure :: to_generator => sample_inclusive_to_generator <>= subroutine sample_inclusive_to_generator (this) class(sample_inclusive_t), intent(inout) :: this integer :: int_kind do int_kind = 1, size(this%int_kinds) call this%int_kinds(int_kind)%to_generator () end do end subroutine sample_inclusive_to_generator @ %def sample_inclusive_to_generator @ <>= procedure :: allocate => sample_inclusive_allocate <>= subroutine sample_inclusive_allocate (this, n_alloc) class(sample_inclusive_t), intent(out) :: this integer, intent(in) :: n_alloc allocate (this%int_kinds (n_alloc)) this%n_alloc = n_alloc end subroutine sample_inclusive_allocate @ %def sample_inclusive_allocate @ <>= pure subroutine muli_mcint_generate_hit (rnd, corners, hit) real(default), dimension(2), intent(out) :: hit integer, intent(in), dimension(2) :: rnd real(default), dimension(2,2), intent(in) :: corners ! print *, hit ! print *, corners ! print *, (corners(1:2,2) - corners(1:2,1)) hit = (rnd / max_d) * (corners(1:2,2) - corners(1:2,1)) + corners(1:2,1) end subroutine muli_mcint_generate_hit @ %def muli_mcint_generate_hit @ <>= subroutine plot_pstvue3d (unit, corners, density) integer, intent(in) :: unit real(default), dimension(2,2), intent(in) :: corners real(default), intent(in) :: density real(default), dimension(2) :: width, mean real(default), dimension(3,3) :: plot width = (corners(:,2) - corners(:,1)) / two mean = (corners(:,1) + corners(:,2)) / two plot(1,1) = width(1) plot(2,1) = width(2) plot(3,1) = density / two plot(1,2) = mean(1) plot(2,2) = mean(2) plot(3,2) = density / two call log_color_code (density, plot(1:3,3)) if (density > one) then write (unit, fmt='("\mybigcube{",F14.7,"}{",F14.7,"}{",F14.7,"} & & {",F14.7,"}{",F14.7,"}{",F14.7,"}{",F14.7,"}{",F14.7,"} & & {",F14.7,"}")') plot return end if write (unit, fmt='("\mycube{",F14.7,"}{",F14.7,"}{",F14.7,"} & & {",F14.7,"}{",F14.7,"}{",F14.7,"}{",F14.7,"}{",F14.7,"} & & {",F14.7,"}")') plot end subroutine plot_pstvue3d @ %def plot_pstvue3d @ <>= subroutine log_color_code (number, rgb) real(default), intent(in) :: number real(default), dimension(3), intent(out) :: rgb if (number < exp(-five)) then rgb = [zero, zero, exp(five)*number] else if (number < exp(-four)) then rgb = [zero, (number-exp(-five))/(exp(-four)-exp(-five)), one] else if (number < exp(-three)) then rgb = [zero, one, one-((number-exp(-four))/(exp(-three)-exp(-four)))] else if (number < exp(-two)) then rgb = [(number-exp(-three))/(exp(-two)-exp(-three)), one, zero] else if (number < exp(-one)) then rgb = [one, one-(number-exp(-two))/(exp(-one)-exp(-two)), zero] else if (number < one) then rgb = [one, zero, (number-exp(-three))/(one-exp(-three))] else rgb = [exp(one), one, one] * exp(-number) return end if end if end if end if end if end if end subroutine log_color_code @ %def log_color_code @ <>= recursive subroutine misc_sort (in, out) real(default), dimension(:), intent(in) :: in integer, dimension(:), intent(out) :: out integer, dimension(:), allocatable :: tmp integer :: n, k, l, cut if (size(in) == 1) then out = [1] else if (size(in) == 2) then if (in(1) <= in(2)) then out = [1,2] else out = [2,1] end if else cut = size(in) / 2 k = 1 l = cut + 1 allocate (tmp (size(in))) call misc_sort (in(1:cut), tmp(1:cut)) call misc_sort (in(cut+1:), tmp(cut+1:)) do n = cut + 1, size(in) tmp(n) = tmp(n) + cut end do do n = 1, size(in) if (k > cut) then out(n) = tmp(l) l = l + 1 else if (l > size(tmp)) then out(n) = tmp(k) k = k + 1 else if (in(tmp(k)) < in(tmp(l))) then out(n) = tmp(k) k = k + 1 else out(n) = tmp(l) l = l + 1 end if end if end if end do end if end if end subroutine misc_sort @ %def misc_sort @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Proton remnants} This file contains the module [[muli_remnant]]. All bookkeeping of the proton remnants and twin quarks is done here. Furthermore, reweighting of the PDFs to derive remnant PDFs is done here. <<[[muli_remnant.f90]]>>= <> module muli_remnant use, intrinsic :: iso_fortran_env <> <> use string_utils use constants use diagnostics use pdf_builtin !NODEP! use tao_random_numbers !NODEP! use muli_base use muli_interactions use muli_momentum ! use sf_lhapdf !NODEP! <> <> <> <> <> contains <> end module muli_remnant @ %def muli_remnant @ <>= public :: pdfnorm_t <>= type, extends (ser_class_t) :: pdfnorm_t real(default) :: qmin, qmax, dq real(default), dimension(-6:6, 0:nq) :: pdf_int real(default), dimension(0:4, 0:nq) :: pdf_norm contains <> end type pdfnorm_t @ %def pdfnorm_t @ <>= procedure :: write_to_marker => pdfnorm_write_to_marker <>= subroutine pdfnorm_write_to_marker (this, marker, status) class(pdfnorm_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("pdfnorm_t") call marker%mark ("qmin", this%qmin) call marker%mark ("qmax", this%qmax) call marker%mark ("dq", this%dq) call marker%mark ("pdf_int", this%pdf_int) call marker%mark ("pdf_norm", this%pdf_norm) call marker%mark_end ("pdfnorm_t") end subroutine pdfnorm_write_to_marker @ %def pdfnorm_write_to_marker @ <>= procedure :: read_from_marker => pdfnorm_read_from_marker <>= subroutine pdfnorm_read_from_marker (this, marker, status) class(pdfnorm_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status character(:), allocatable :: name call marker%pick_begin ("pdfnorm_t", status=status) call marker%pick ("qmin", this%qmin, status) call marker%pick ("qmax", this%qmax, status) call marker%pick ("dq", this%dq, status) call marker%pick ("pdf_int", this%pdf_int, status) call marker%pick ("pdf_norm", this%pdf_norm, status) call marker%pick_end ("pdfnorm_t", status=status) end subroutine pdfnorm_read_from_marker @ %def pdfnorm_read_from_marker @ <>= procedure :: print_to_unit => pdfnorm_print_to_unit <>= recursive subroutine pdfnorm_print_to_unit & (this, unit, parents, components, peers) class(pdfnorm_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "Components of pdfnorm_t:" write (unit, "(3x,A,F7.6)") "qmin: ", this%qmin write (unit, "(3x,A,F7.6)") "qmax: ", this%qmax write (unit, "(3x,A,F7.6)") "dq: ", this%dq if (components > 0) then write(unit, "(3x,A,13(F8.6,1x))") "pdf_int: ", this%pdf_int write(unit, "(3x,A,5(F8.6,1x))") "pdf_norm: ", this%pdf_norm else write(unit, "(3x,A)") "Skipping pdf_int" write(unit, "(3x,A)") "Skipping pdf_norm" end if end subroutine pdfnorm_print_to_unit @ %def pdfnorm_print_to_unit @ <>= @ <>= procedure, nopass :: get_type => pdfnorm_get_type <>= pure subroutine pdfnorm_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="pdfnorm_t") end subroutine pdfnorm_get_type @ %def pdfnorm_get_type @ <>= procedure, nopass :: verify_type => pdfnorm_verify_type <>= elemental logical function pdfnorm_verify_type (type) result (match) character(*), intent(in) :: type match = type == "pdfnorm_t" end function pdfnorm_verify_type @ %def pdfnorm_verify_type @ <>= procedure :: scan => pdfnorm_scan <>= subroutine pdfnorm_scan (this) class(pdfnorm_t), intent(out) :: this integer :: ix, iq real(double) :: xmin, xmax, dx real(double) :: q, q2min, q2max real(double), dimension(-6:6) :: f real(double), dimension(0:2) :: x call getxmin (0, xmin) call getxmax (0, xmax) call getq2min (0, q2min) call getq2max (0, q2max) this%qmin = sqrt(sqrt(q2min)) this%qmax = sqrt(sqrt(q2max)) this%dq = (this%qmax - this%qmin) / nq xmin = sqrt(xmin) xmax = sqrt(xmax) dx= (xmax - xmin) / nx do iq = 0, nq print *, "iq=", iq, "/", nq q = (this%qmin + iq * this%dq)**2 x(0) = xmin**2 x(1) = (xmin+dx)**2 call evolvePDF (x(0), q, f) f(1) = f(1) - f(-1) f(2) = f(2) - f(-2) this%pdf_int(:,iq) = (x(1) - x(0)) * f do ix = 2, nx x(2) = (xmin + ix*dx)**2 call evolvePDF (x(1), q, f) f(1) = f(1) - f(-1) f(2) = f(2) - f(-2) this%pdf_int(:,iq) = this%pdf_int(:,iq) + f*(x(2) - x(0)) x(0) = x(1) x(1) = x(2) end do call evolvePDF (x(1), q, f) f(1) = f(1) - f(-1) f(2) = f(2) - f(-2) this%pdf_int(:,iq) = (this%pdf_int(:,iq) + f*(x(1)-x(0))) / two this%pdf_norm(4,iq) = this%pdf_int(2,iq) this%pdf_norm(3,iq) = this%pdf_int(1,iq) this%pdf_int(2,iq) = this%pdf_int(2,iq) + this%pdf_int(-2,iq) this%pdf_int(1,iq) = this%pdf_int(1,iq) + this%pdf_int(-1,iq) this%pdf_norm(1,iq) = this%pdf_int(0,iq) this%pdf_norm(2,iq) = sum (this%pdf_int(-6:-1,iq)) + & sum(this%pdf_int(-2:-1,iq)) + sum(this%pdf_int(3:6,iq)) this%pdf_norm(0,iq) = sum(this%pdf_int(:,iq)) this%pdf_norm(1,iq) = this%pdf_norm(1,iq) / this%pdf_norm(0,iq) this%pdf_norm(2,iq) = this%pdf_norm(2,iq) / this%pdf_norm(0,iq) this%pdf_norm(3,iq) = this%pdf_norm(3,iq) / this%pdf_norm(0,iq) this%pdf_norm(4,iq) = this%pdf_norm(4,iq) / this%pdf_norm(0,iq) ! print *, this%pdf_norm(0,iq) - one end do end subroutine pdfnorm_scan @ %def pdfnorm_scan @ <>= procedure :: get_norm => pdfnorm_get_norm <>= subroutine pdfnorm_get_norm (this, gev_q, dim, kind, norm) class(pdfnorm_t), intent(in) :: this real(default), intent(in) :: gev_q integer, intent(in) :: dim, kind real(default), intent(out)::norm integer :: iq real(default) :: x,q , z0, z1, z2, z3, z4 norm = -one q = sqrt(gev_q) - this%qmin iq = floor(q / this%dq) x = q / this%dq - iq if (iq < 0) then print *, "pdfnorm_getnorm: q < q_min ", gev_q, this%qmin**2 norm = this%pdf_norm (kind, 0) else if (iq >= nq) then print *, "pdfnorm_getnorm: q >= q_max ", gev_q, this%qmax**2 norm = this%pdf_norm (kind, nq) else select case (dim) case (0) norm = this%pdf_norm (kind, iq) case (1) norm = this%pdf_norm(kind,iq) * (one - x) + & this%pdf_norm(kind,iq+1) * x case (2) x = x + mod(iq,2) iq = iq - mod(iq,2) z0 = this%pdf_norm(kind, iq) z1 = this%pdf_norm(kind, iq+1) z2 = this%pdf_norm(kind, iq+2) norm = ((z0 - 2D0*z1 + z2) * x - (three*z0 - four*z1 + z2)) * & x / two + z0 case (3) x = x + mod(iq,3) iq = iq - mod(iq,3) z0 = this%pdf_norm(kind, iq) z1 = this%pdf_norm(kind, iq+1) z2 = this%pdf_norm(kind, iq+2) z3 = this%pdf_norm(kind, iq+3) norm = (( - (z0 - 3*z1 + 3*z2 -z3) * x + 3 * (2*z0 - & 5*z1 + 4*z2 - z3))*x - (11*z0 - 18*z1 + 9*z2 - 2*z3)) * & x / 6._default + z0 case (4) x = x + mod(iq,4) iq = iq - mod(iq,4) z0 = this%pdf_norm(kind, iq) z1 = this%pdf_norm(kind, iq+1) z2 = this%pdf_norm(kind, iq+2) z3 = this%pdf_norm(kind, iq+3) z4 = this%pdf_norm(kind, iq+4) norm = (((((z0 - 4*z1 + 6*z2 - 4*z3 + z4) * x & -2 * (5*z0 - 18*z1 + 24*z2 - 14*z3 + 3*z4)) * x & + (35*z0 - 104*z1 + 114*z2 - 56*z3 + 11*z4)) * x & -2 * (25*z0 - 48*z1 + 36*z2 - 16*z3 + 3*z4)) * x) / & 24._default + z0 case default norm = this%pdf_norm(kind, iq) * (one - x) + & this%pdf_norm(kind, iq+1) * x end select ! print *, iq, x, norm end if end if end subroutine pdfnorm_get_norm @ %def pdfnorm_get_norm @ <>= integer, parameter :: nx = 10000000 <>= integer, parameter :: nq = 60 <>= public :: remnant_weight_model <>= integer :: remnant_weight_model = 2 <>= integer :: gluon_exp = 4 @ %def nx nq remnant_weight_model gluon_exp @ <>= public :: muli_parton_t <>= type, extends (ser_class_t) :: muli_parton_t private integer :: id = -1 integer :: lha_flavor real(default) :: momentum = -1 class(muli_parton_t), pointer :: twin => null() class(muli_parton_t), pointer :: next => null() contains <> end type muli_parton_t @ %def muli_parton_t @ <>= procedure :: write_to_marker => parton_write_to_marker <>= subroutine parton_write_to_marker (this, marker, status) class(muli_parton_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("muli_parton_t") call marker%mark ("id", this%id) call marker%mark ("lha", this%lha_flavor) call marker%mark ("momentum", this%momentum) call marker%mark_end ("muli_parton_t") end subroutine parton_write_to_marker @ %def parton_write_to_marker @ <>= procedure :: read_from_marker => parton_read_from_marker <>= subroutine parton_read_from_marker (this, marker, status) class(muli_parton_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status character(:), allocatable :: name call marker%pick_begin ("muli_parton_t", status=status) call marker%pick ("id", this%id, status) call marker%pick ("lha", this%lha_flavor, status) call marker%pick ("momentum", this%momentum, status) call marker%pick_end ("muli_parton_t", status=status) end subroutine parton_read_from_marker @ %def parton_read_from_marker @ <>= procedure :: print_to_unit => parton_print_to_unit <>= recursive subroutine parton_print_to_unit & (this, unit, parents, components, peers) class(muli_parton_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers class(ser_class_t), pointer :: ser write (unit, "(1x,A)") "Components of muli_parton_t:" write (unit, "(3x,A,I7)") "id: ", this%id write (unit, "(3x,A,I7)") "lha flavor: ", this%lha_flavor write (unit, "(3x,A,F7.6)") "momentum: ", this%momentum ser => this%next call serialize_print_peer_pointer & (ser, unit, parents, components, peers-i_one, "next") ser => this%twin call serialize_print_comp_pointer & (ser, unit, parents, components, peers-i_one, "twin") end subroutine parton_print_to_unit @ %def parton_print_to_unit @ <>= procedure, nopass :: get_type => parton_get_type <>= pure subroutine parton_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="muli_parton_t") end subroutine parton_get_type @ %def parton_get_type @ <>= procedure :: unweighted_pdf => twin_unweighted_pdf <>= pure function twin_unweighted_pdf (this, momentum_fraction) result (pdf) !parton pdf class(muli_parton_t), intent(in) :: this real(default), intent(in) :: momentum_fraction real(default) :: pdf if (momentum_fraction + this%twin%momentum < one) then pdf = remnant_twin_pdf_p (momentum_fraction, & this%twin%momentum, gluon_exp) else pdf = zero end if end function twin_unweighted_pdf @ %def twin_unweighted_pdf @ <>= procedure :: deallocate => twin_deallocate <>= recursive subroutine twin_deallocate (this) class(muli_parton_t) :: this if (associated (this%next)) then call this%next%deallocate deallocate (this%next) end if end subroutine twin_deallocate @ %def twin_deallocate @ <>= procedure :: push => parton_push <>= subroutine parton_push (this, parton) class(muli_parton_t), intent(inout) :: this class(muli_parton_t), intent(inout), pointer :: parton ! print *, "parton_push ", parton%id parton%next => this%next this%next => parton end subroutine parton_push @ %def parton_push @ <>= generic :: pop => pop_by_id, pop_by_association procedure :: pop_by_id => parton_pop_by_id procedure :: pop_by_association => parton_pop_by_association <>= subroutine parton_pop_by_id (this, id, parton) class(muli_parton_t), target, intent(inout) :: this integer, intent(in) :: id class(muli_parton_t), intent(out), pointer :: parton class(muli_parton_t), pointer :: tmp_parton tmp_parton => this do while (associated (tmp_parton%next)) if (tmp_parton%next%id == id) exit tmp_parton => tmp_parton%next end do if (associated (tmp_parton%next)) then parton => tmp_parton%next tmp_parton%next => parton%next nullify (parton%next) ! print *,"parton_pop ",id,parton%id else nullify (parton) print *,"parton_pop ", id, "NULL" end if end subroutine parton_pop_by_id @ %def parton_pop_by_id @ <>= subroutine parton_pop_by_association (this, parton) class(muli_parton_t), target, intent(inout) :: this class(muli_parton_t), intent(inout), target :: parton class(muli_parton_t), pointer :: tmp_parton tmp_parton => this do while (associated (tmp_parton%next)) if (associated (tmp_parton%next, parton)) exit tmp_parton=>tmp_parton%next end do if (associated(tmp_parton%next)) then tmp_parton%next => parton%next nullify (parton%next) ! print *,"parton_pop ", parton%id else print *, "parton_pop NULL" end if end subroutine parton_pop_by_association @ %def parton_pop_by_association @ <>= public :: proton_remnant_t <>= type, extends (ser_class_t) :: proton_remnant_t private integer, dimension(2) :: valence_content = [1,2] integer :: n_twins = 0 !!! [gluon, sea quark, valence down, valence up, twin] real(default), dimension(5) :: pdf_int_weight = [one, one, one, one, one] real(default) :: momentum_fraction = one real(default) :: twin_norm = one type(muli_parton_t) :: twin_partons type(muli_parton_t) :: is_partons type(muli_parton_t) :: fs_partons !!! These pointers shall not be allocated, deallocated, !!! serialized or deserialized explicitly. class(pdfnorm_t), pointer :: pdf_norm => null() contains <> end type proton_remnant_t @ %def proton_remnant_t @ <>= procedure :: remove_valence_quark => proton_remnant_remove_valence_quark <>= subroutine proton_remnant_remove_valence_quark & (this, id, GeV_scale, momentum_fraction, lha_flavor) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor !!! d=1, u=2 if (lha_flavor == 1 .or. lha_flavor == 2) then associate (q => this%valence_content (lha_flavor)) if (q > 0) then q = q - 1 call this%push_is_parton (id, lha_flavor, momentum_fraction) this%momentum_fraction = this%momentum_fraction * (one - momentum_fraction) call this%calculate_weight (GeV_scale) else write (*, "(1x,A,I2,A)") "proton_remnant_remove_valence_quark: " // & "Cannot remove parton ", lha_flavor, ": There are no such " // & "partons left." call this%print_all () end if end associate else write (*, "(1x,A,I2,A)") "proton_remnant_remove_valence_quark: Cannot " // & "remove parton ", lha_flavor, ": There are no such valence partons." end if end subroutine proton_remnant_remove_valence_quark @ %def proton_remnant_remove_valence_quark @ <>= procedure :: remove_sea_quark => proton_remnant_remove_sea_quark <>= subroutine proton_remnant_remove_sea_quark & (this, id, GeV_scale, momentum_fraction, lha_flavor) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor ! print *, "proton_remnant_remove_sea_quark", momentum_fraction if (lha_flavor > -6 .and. lha_flavor < 6 .and. lha_flavor .ne. 0) then this%momentum_fraction = this%momentum_fraction * & (one - momentum_fraction) call this%push_twin (id, lha_flavor, momentum_fraction, GeV_scale) end if end subroutine proton_remnant_remove_sea_quark @ %def proton_remnant_remove_sea_quark @ <>= procedure :: remove_gluon => proton_remnant_remove_gluon <>= subroutine proton_remnant_remove_gluon & (this, id, GeV_scale, momentum_fraction) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale, momentum_fraction this%momentum_fraction = this%momentum_fraction * (one - momentum_fraction) call this%push_is_parton (id, LHA_FLAVOR_g, momentum_fraction) end subroutine proton_remnant_remove_gluon @ %def proton_remnant_remove_gluon @ <>= procedure :: remove_valence_up_quark => proton_remnant_remove_valence_up_quark <>= subroutine proton_remnant_remove_valence_up_quark & (this, id, GeV_scale, momentum_fraction) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale, momentum_fraction associate (q => this%valence_content (LHA_FLAVOR_u)) if (q > 0) then q = q - 1 call this%push_is_parton (id, LHA_FLAVOR_u, momentum_fraction) this%momentum_fraction = this%momentum_fraction * (one - momentum_fraction) call this%calculate_weight (GeV_scale) else write (*, "(1x,A,I2,A)") "proton_remnant_remove_valence_up_quark: " // & "Cannot remove parton ", LHA_FLAVOR_u, ": There are no such " // & "partons left." call this%print_all end if end associate end subroutine proton_remnant_remove_valence_up_quark @ %def proton_remnant_remove_valence_up_quark @ <>= procedure :: remove_valence_down_quark => & proton_remnant_remove_valence_down_quark <>= subroutine proton_remnant_remove_valence_down_quark & (this, id, GeV_scale, momentum_fraction) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale, momentum_fraction associate (q => this%valence_content(LHA_FLAVOR_d)) if (q > 0) then q = q - 1 call this%push_is_parton (id, LHA_FLAVOR_d, momentum_fraction) this%momentum_fraction = this%momentum_fraction * & (one - momentum_fraction) call this%calculate_weight (GeV_scale) else write (*, "(1x,A,I2,A)") "proton_remnant_remove_valence_down_quark:" // & "Cannot remove parton ", LHA_FLAVOR_d, ": There are no " // & "such partons left." call this%print_all end if end associate end subroutine proton_remnant_remove_valence_down_quark @ %def proton_remnant_remove_valence_down_quark @ <>= procedure :: remove_twin => proton_remnant_remove_twin <>= subroutine proton_remnant_remove_twin (this, id, GeV_scale) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id real(default), intent(in) :: GeV_scale class(muli_parton_t), pointer :: twin call this%twin_partons%pop (id, twin) call this%fs_partons%push (twin) this%twin_norm = this%twin_norm - twin%momentum this%n_twins = this%n_twins - 1 call this%calculate_weight (GeV_scale) end subroutine proton_remnant_remove_twin @ %def proton_remnant_remove_twin @ <>= procedure :: momentum_twin_pdf => proton_remnant_momentum_twin_pdf <>= subroutine proton_remnant_momentum_twin_pdf & (this, lha_flavor, momentum_fraction,pdf) class(proton_remnant_t), intent(in) :: this integer, intent(in) :: lha_flavor real(default), intent(in) :: momentum_fraction real(default), intent(out) :: pdf call this%parton_twin_pdf (lha_flavor, momentum_fraction, pdf) pdf = pdf * momentum_fraction end subroutine proton_remnant_momentum_twin_pdf @ %def proton_remnant_momentum_twin_pdf @ <>= procedure :: momentum_twin_pdf_array => proton_remnant_momentum_twin_pdf_array <>= subroutine proton_remnant_momentum_twin_pdf_array & (this, momentum_fraction, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: momentum_fraction real(default), dimension(this%n_twins), intent(out) :: pdf call this%parton_twin_pdf_array (momentum_fraction, pdf) pdf = pdf * momentum_fraction end subroutine proton_remnant_momentum_twin_pdf_array @ %def proton_remnant_momentum_twin_pdf_array @ <>= procedure :: momentum_kind_pdf => proton_remnant_momentum_kind_pdf <>= subroutine proton_remnant_momentum_kind_pdf (this, GeV_scale, & momentum_fraction, lha_flavor, valence_pdf, sea_pdf, twin_pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor !!! g, u, d, etc. real(default), intent(out) :: valence_pdf, sea_pdf, twin_pdf real(double), dimension(-6:6) :: pdf_array - call evolvePDF (momentum_fraction, GeV_scale, pdf_array) + call evolvePDF (dble (momentum_fraction), dble (GeV_scale), pdf_array) select case (lha_flavor) case (0) !!! gluon valence_pdf = zero sea_pdf=pdf_array(0) case (1) !!! down valence_pdf = this%get_valence_down_weight() * (pdf_array(1) - pdf_array(-1)) sea_pdf = pdf_array(-1) case (2) !!! up valence_pdf = this%get_valence_up_weight() * (pdf_array(2) - pdf_array(-2)) sea_pdf = pdf_array(-2) case default valence_pdf = zero sea_pdf = pdf_array (lha_flavor) end select sea_pdf = sea_pdf * this%get_sea_weight() call this%momentum_twin_pdf (lha_flavor, momentum_fraction, twin_pdf) end subroutine proton_remnant_momentum_kind_pdf @ %def proton_remnant_momentum_kind_pdf @ <>= procedure :: momentum_flavor_pdf => proton_remnant_momentum_flavor_pdf <>= subroutine proton_remnant_momentum_flavor_pdf (this, GeV_scale, & momentum_fraction, lha_flavor, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor !!! g, u, d, etc. real(default), intent(out) :: pdf real(default) :: valence_pdf, sea_pdf, twin_pdf call this%momentum_kind_pdf (GeV_scale, momentum_fraction, & lha_flavor, valence_pdf, sea_pdf, twin_pdf) pdf = valence_pdf + sea_pdf + twin_pdf end subroutine proton_remnant_momentum_flavor_pdf @ %def proton_remnant_momentum_flavor_pdf @ <>= procedure :: momentum_kind_pdf_array => & proton_remnant_momentum_kind_pdf_array <>= subroutine proton_remnant_momentum_kind_pdf_array (this, GeV_scale, & momentum_fraction, valence_pdf, sea_pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction real(default), dimension(2), intent(out) :: valence_pdf real(double), dimension(-6:6), intent(out) :: sea_pdf - call evolvePDF (momentum_fraction, GeV_scale, sea_pdf) + call evolvePDF (dble (momentum_fraction), dble (GeV_scale), sea_pdf) valence_pdf(1) = (sea_pdf(1) - sea_pdf(-1)) * & this%pdf_int_weight (PDF_VALENCE_DOWN) valence_pdf(2) = (sea_pdf(2) - sea_pdf(-2)) * & this%pdf_int_weight (PDF_VALENCE_UP) sea_pdf(1) = sea_pdf(-1) sea_pdf(2) = sea_pdf(-2) sea_pdf = sea_pdf * this%get_sea_weight() !!! no twin yet end subroutine proton_remnant_momentum_kind_pdf_array @ %def proton_remnant_momentum_kind_pdf_array @ <>= procedure :: momentum_flavor_pdf_array => proton_remnant_momentum_flavor_pdf_array <>= subroutine proton_remnant_momentum_flavor_pdf_array & (this, GeV_scale, momentum_fraction, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction real(double), dimension(-6:6), intent(out) :: pdf real(default), dimension(2) :: valence_pdf call this%momentum_kind_pdf_array & (GeV_scale, momentum_fraction, valence_pdf, pdf) pdf(1:2) = pdf(1:2) + valence_pdf !!! no twin yet end subroutine proton_remnant_momentum_flavor_pdf_array @ %def proton_remnant_momentum_flavor_pdf_array @ <>= procedure :: parton_twin_pdf => proton_remnant_parton_twin_pdf <>= subroutine proton_remnant_parton_twin_pdf & (this, lha_flavor, momentum_fraction, pdf) class(proton_remnant_t), intent(in) :: this integer, intent(in) :: lha_flavor real(default), intent(in) :: momentum_fraction real(default) :: pdf class(muli_parton_t), pointer :: tmp_twin pdf = 0D0 tmp_twin => this%twin_partons%next do while (associated (tmp_twin)) if (tmp_twin%lha_flavor == lha_flavor) pdf = pdf & + tmp_twin%unweighted_pdf (momentum_fraction) tmp_twin => tmp_twin%next end do pdf = pdf * this%get_twin_weight () end subroutine proton_remnant_parton_twin_pdf @ %def proton_remnant_parton_twin_pdf @ <>= procedure :: parton_twin_pdf_array => proton_remnant_parton_twin_pdf_array <>= subroutine proton_remnant_parton_twin_pdf_array & (this, momentum_fraction, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: momentum_fraction real(default), dimension(this%n_twins), intent(out) :: pdf class(muli_parton_t), pointer :: tmp_twin integer :: l tmp_twin => this%twin_partons%next l = 0 do while (associated (tmp_twin)) l = l + 1 pdf(l) = tmp_twin%unweighted_pdf (momentum_fraction) * this%twin_norm tmp_twin => tmp_twin%next end do end subroutine proton_remnant_parton_twin_pdf_array @ %def proton_remnant_parton_twin_pdf_array @ <>= procedure :: parton_kind_pdf => proton_remnant_parton_kind_pdf <>= subroutine proton_remnant_parton_kind_pdf (this, GeV_scale, momentum_fraction, & lha_flavor, valence_pdf, sea_pdf, twin_pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor !!! g, u, d, etc. real(default), intent(out) :: valence_pdf, sea_pdf, twin_pdf call this%momentum_kind_pdf (GeV_scale, momentum_fraction, & lha_flavor, valence_pdf, sea_pdf, twin_pdf) valence_pdf = valence_pdf / momentum_fraction sea_pdf = sea_pdf / momentum_fraction twin_pdf = twin_pdf / momentum_fraction end subroutine proton_remnant_parton_kind_pdf @ %def proton_remnant_parton_kind_pdf @ <>= procedure :: parton_flavor_pdf => proton_remnant_parton_flavor_pdf <>= subroutine proton_remnant_parton_flavor_pdf (this, GeV_scale, & momentum_fraction, lha_flavor, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction integer, intent(in) :: lha_flavor !g,u,d,etc. real(default), intent(out) :: pdf call this%momentum_flavor_pdf (GeV_scale, momentum_fraction, & lha_flavor, pdf) pdf = pdf / momentum_fraction end subroutine proton_remnant_parton_flavor_pdf @ %def proton_remnant_parton_flavor_pdf @ <>= procedure :: parton_kind_pdf_array => proton_remnant_parton_kind_pdf_array <>= subroutine proton_remnant_parton_kind_pdf_array & (this, GeV_scale, momentum_fraction, valence_pdf, sea_pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction real(default), dimension(2), intent(out) :: valence_pdf real(double), dimension(-6:6), intent(out) :: sea_pdf - call evolvePDF (momentum_fraction, GeV_scale, sea_pdf) + call evolvePDF (dble (momentum_fraction), dble (GeV_scale), sea_pdf) sea_pdf = sea_pdf / momentum_fraction valence_pdf(1) = (sea_pdf(1) - sea_pdf(-1)) * this%valence_content(1) valence_pdf(2) = (sea_pdf(2) - sea_pdf(-2)) * (this%valence_content(2) / two) sea_pdf(1) = sea_pdf(-1) sea_pdf(2) = sea_pdf(-2) valence_pdf = valence_pdf * this%get_valence_weight() sea_pdf = sea_pdf * this%get_sea_weight() !!! no twin yet end subroutine proton_remnant_parton_kind_pdf_array @ %def proton_remnant_parton_kind_pdf_array @ <>= procedure :: parton_flavor_pdf_array => proton_remnant_parton_flavor_pdf_array <>= subroutine proton_remnant_parton_flavor_pdf_array & (this, GeV_scale, momentum_fraction, pdf) class(proton_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum_fraction real(double), dimension(-6:6), intent(out) :: pdf real(double), dimension(2) :: valence_pdf real(double), dimension(-6:6) :: twin_pdf call msg_error ("proton_remnant_flavor_pdf_array: Not yet implemented.") end subroutine proton_remnant_parton_flavor_pdf_array @ %def proton_remnant_parton_flavor_pdf_array @ <>= procedure :: get_pdf_int_weight => proton_remnant_get_pdf_int_weight <>= pure function proton_remnant_get_pdf_int_weight (this) result(weight) class(proton_remnant_t), intent(in) :: this real(default), dimension(5) :: weight weight = this%pdf_int_weight end function proton_remnant_get_pdf_int_weight @ %def proton_remnant_get_pdf_int_weight @ <>= procedure :: get_valence_down_weight => proton_remnant_get_valence_down_weight <>= elemental function proton_remnant_get_valence_down_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default) :: weight weight = this%pdf_int_weight (PDF_VALENCE_DOWN) end function proton_remnant_get_valence_down_weight @ %def proton_remnant_get_valence_down_weight @ <>= procedure :: get_valence_up_weight => proton_remnant_get_valence_up_weight <>= elemental function proton_remnant_get_valence_up_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default) :: weight weight = this%pdf_int_weight (PDF_VALENCE_UP) end function proton_remnant_get_valence_up_weight @ %def proton_remnant_get_valence_up_weight @ <>= procedure :: get_valence_weight => proton_remnant_get_valence_weight <>= pure function proton_remnant_get_valence_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default), dimension(2) :: weight weight = this%pdf_int_weight(3:4) end function proton_remnant_get_valence_weight @ %def proton_remnant_get_valence_weight @ <>= procedure :: get_gluon_weight => proton_remnant_get_gluon_weight <>= elemental function proton_remnant_get_gluon_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default) :: weight weight = this%pdf_int_weight (PDF_GLUON) end function proton_remnant_get_gluon_weight @ %def proton_remnant_get_gluon_weight @ <>= procedure :: get_sea_weight => proton_remnant_get_sea_weight <>= elemental function proton_remnant_get_sea_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default) :: weight weight = this%pdf_int_weight (PDF_SEA) end function proton_remnant_get_sea_weight @ %def proton_remnant_get_sea_weight @ <>= procedure :: get_twin_weight => proton_remnant_get_twin_weight @ <>= elemental function proton_remnant_get_twin_weight (this) result (weight) class(proton_remnant_t), intent(in) :: this real(default) :: weight weight = this%pdf_int_weight (PDF_TWIN) end function proton_remnant_get_twin_weight @ %def proton_remnant_get_twin_weight @ <>= procedure :: get_valence_content => proton_remnant_get_valence_content <>= pure function proton_remnant_get_valence_content (this) result (valence) class(proton_remnant_t), intent(in) :: this integer, dimension(2) :: valence valence = this%valence_content end function proton_remnant_get_valence_content @ %def proton_remnant_get_valence_content @ <>= procedure :: get_momentum_fraction => proton_remnant_get_momentum_fraction <>= elemental function proton_remnant_get_momentum_fraction (this) result (momentum) class(proton_remnant_t), intent(in) :: this real(default) :: momentum momentum = this%momentum_fraction end function proton_remnant_get_momentum_fraction @ %def proton_remnant_get_momentum_fraction @ <>= procedure :: deallocate => proton_remnant_deallocate <>= subroutine proton_remnant_deallocate (this) class(proton_remnant_t), intent(inout) :: this call this%is_partons%deallocate call this%fs_partons%deallocate call this%twin_partons%deallocate this%twin_norm = zero this%n_twins = 0 end subroutine proton_remnant_deallocate @ %def proton_remnant_deallocate @ <>= procedure :: initialize => proton_remnant_initialize <>= subroutine proton_remnant_initialize (this, pdf_norm) class(proton_remnant_t), intent(out) :: this class(pdfnorm_t),target, intent(in) :: pdf_norm this%pdf_norm => pdf_norm end subroutine proton_remnant_initialize @ %def proton_remnant_initialize @ <>= procedure :: finalize => proton_remnant_finalize <>= subroutine proton_remnant_finalize (this) class(proton_remnant_t), intent(inout) :: this call this%deallocate () nullify (this%pdf_norm) end subroutine proton_remnant_finalize @ %def proton_remnant_finalize @ <>= procedure :: apply_initial_splitting => proton_remnant_apply_initial_splitting <>= subroutine proton_remnant_apply_initial_splitting & (this, id, pdg_flavor, x, gev_scale, rnd) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id, pdg_flavor real(default), intent(in) :: x, gev_scale, rnd real(default) :: valence_pdf, sea_pdf, twin_pdf select case (pdg_flavor) case (PDG_FLAVOR_g) call this%remove_gluon (id, gev_scale, x) case (PDG_FLAVOR_u) call this%parton_kind_pdf (gev_scale, x, pdg_flavor, & valence_pdf, sea_pdf, twin_pdf) if (valence_pdf / (valence_pdf + sea_pdf) < rnd) then call this%remove_sea_quark (id, gev_scale, x, pdg_flavor) else call this%remove_valence_up_quark (id, gev_scale, x) end if case (PDG_FLAVOR_d) call this%parton_kind_pdf (gev_scale, x, & pdg_flavor, valence_pdf, sea_pdf, twin_pdf) if (valence_pdf / (valence_pdf + sea_pdf) < rnd) then call this%remove_sea_quark (id, gev_scale, x, pdg_flavor) else call this%remove_valence_down_quark (id, gev_scale, x) end if case default call this%remove_sea_quark (id, gev_scale, x, pdg_flavor) end select this%momentum_fraction = (one - x) end subroutine proton_remnant_apply_initial_splitting @ %def proton_remnant_apply_initial_splitting @ <>= procedure :: reset => proton_remnant_reset <>= subroutine proton_remnant_reset (this) class(proton_remnant_t), intent(inout) :: this call this%deallocate () this%valence_content = [1, 2] this%pdf_int_weight = [one, one, one, one, one] this%momentum_fraction = one end subroutine proton_remnant_reset @ %def proton_remnant_reset @ <>= procedure :: calculate_weight => proton_remnant_calculate_weight <>= subroutine proton_remnant_calculate_weight (this, GeV_scale) class(proton_remnant_t), intent(inout) :: this real(default), intent(in) :: GeV_scale real(default) :: all, gluon, sea, vu, vd, valence, twin, weight call this%pdf_norm%get_norm (GeV_scale, 1, 0, all) call this%pdf_norm%get_norm (GeV_scale, 1, PDF_GLUON, gluon) call this%pdf_norm%get_norm (GeV_scale, 1, PDF_SEA, sea) call this%pdf_norm%get_norm (GeV_scale, 1, PDF_VALENCE_DOWN, vd) call this%pdf_norm%get_norm (GeV_scale, 1, PDF_VALENCE_UP, vu) valence = vd * this%valence_content (LHA_FLAVOR_d) + & vu * this%valence_content (LHA_FLAVOR_u) / two twin = this%twin_norm / all ! print *, all, gluon + sea + valence + twin, gluon, sea, valence, twin ! pdf_rescale = (one - n_d_valence * mean_d1 - n_u_valence * mean_u2) / & ! (1.E-1_default * mean_d1 - two * mean_u2) !!! pythia select case (remnant_weight_model) case (0) !!! no reweighting this%pdf_int_weight = [one, one, one, one, one] case (2) !!! pythia-like, only sea weight = (one - valence - twin) / (sea + gluon) this%pdf_int_weight = [weight, weight, one, one, one] case (3) !!! only valence and twin weight = (one - sea - gluon) / (valence + twin) this%pdf_int_weight = [one, one, weight, weight, weight] case (4) !!! only sea and twin weight = (one - valence) / (sea + gluon + twin) this%pdf_int_weight = [one, weight, one, one, weight] case default !!! equal weight weight = one / (valence + sea + gluon + twin) this%pdf_int_weight = [weight, weight, weight, weight, weight] end select this%pdf_int_weight(PDF_VALENCE_DOWN) = & this%pdf_int_weight(PDF_VALENCE_DOWN) * this%valence_content(1) this%pdf_int_weight(PDF_VALENCE_UP) = & this%pdf_int_weight(PDF_VALENCE_UP) * this%valence_content(2) * & 5.E-1_default ! print('("New rescale factors are: ",2(I10),7(E14.7))'),& ! this%valence_content,& ! this%pdf_int_weight,& ! sea_norm,& ! valence_norm,& ! this%twin_norm end subroutine proton_remnant_calculate_weight @ %def proton_remnant_calculate_weight @ <>= procedure :: push_is_parton => proton_remnant_push_is_parton <>= subroutine proton_remnant_push_is_parton & (this, id, lha_flavor, momentum_fraction) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id, lha_flavor real(default), intent(in) :: momentum_fraction class(muli_parton_t), pointer :: tmp_parton allocate (tmp_parton) tmp_parton%id = id tmp_parton%lha_flavor = lha_flavor tmp_parton%momentum = momentum_fraction call this%is_partons%push (tmp_parton) end subroutine proton_remnant_push_is_parton @ %def proton_remnant_push_is_parton @ <>= procedure :: push_twin => proton_remnant_push_twin <>= subroutine proton_remnant_push_twin & (this, id, lha_flavor, momentum_fraction, gev_scale) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: id, lha_flavor !!! of IS parton real(default), intent(in) :: momentum_fraction !!! of IS parton real(default), intent(in) :: GeV_scale class(muli_parton_t), pointer :: new_is, new_twin real(default) :: norm ! print *, "proton_remnant_push_twin", momentum_fraction allocate (new_is) allocate (new_twin) !!! IS initialization new_is%id = id new_is%lha_flavor = lha_flavor new_is%momentum = momentum_fraction new_is%twin => new_twin !!! twin initialization new_twin%id = -id new_twin%lha_flavor = -lha_flavor new_twin%momentum = remnant_twin_momentum_4 (momentum_fraction) new_twin%twin => new_is !!! remnant update this%n_twins = this%n_twins + 1 this%twin_norm = this%twin_norm + new_twin%momentum call this%is_partons%push (new_is) call this%twin_partons%push (new_twin) call this%calculate_weight (GeV_scale) end subroutine proton_remnant_push_twin @ %def proton_remnant_push_twin @ <>= procedure :: calculate_twin_norm => proton_remnant_calculate_twin_norm <>= subroutine proton_remnant_calculate_twin_norm (this) class(proton_remnant_t), intent(inout) :: this class(muli_parton_t), pointer :: twin integer :: n if (associated (this%twin_partons%next)) then this%twin_norm = zero twin => this%twin_partons%next do while (associated (twin)) this%twin_norm = this%twin_norm + twin%momentum twin => twin%next end do else this%twin_norm = zero end if end subroutine proton_remnant_calculate_twin_norm @ %def proton_remnant_calculate_twin_norm @ <>= procedure :: replace_is_parton => proton_remnant_replace_is_parton <>= subroutine proton_remnant_replace_is_parton & (this, old_id, new_id, pdg_f, x_proton, gev_scale) class(proton_remnant_t), intent(inout) :: this integer, intent(in) :: old_id, new_id, pdg_f real(default), intent(in) :: x_proton, gev_scale class(muli_parton_t), pointer :: old_is_parton integer :: lha_flavor real(default) :: momentum_fraction momentum_fraction = x_proton / this%momentum_fraction !!! convert PDG flavor numbers to LHA flavor numbers if (pdg_f == PDG_FLAVOR_g) then lha_flavor = LHA_FLAVOR_g else lha_flavor = pdg_f end if !!! we remove the old initial state parton from initial state stack. call this%is_partons%pop (old_id, old_is_parton) !!! this check has no physical meaning, it's just a check for consistency. if (associated (old_is_parton)) then !!! do we emit a gluon? if (lha_flavor == old_is_parton%lha_flavor) then !!! has the old initial state parton been a sea quark? if (associated (old_is_parton%twin)) then !!! the connection of the old IS parton with its twin was !!! provisional. We remove it now call this%twin_partons%pop (old_is_parton%twin) call this%fs_partons%push (old_is_parton%twin) this%n_twins = this%n_twins - 1 !!! and generate a new initial state parton - twin pair. call this%push_twin & (new_id, lha_flavor, momentum_fraction, gev_scale) else !!! there is no twin, so we just insert the new initial state parton. call this%push_is_parton (new_id, lha_flavor, momentum_fraction) end if else ! we emit a quark. is this a g->qqbar splitting? if (lha_flavor==LHA_FLAVOR_g) then !!! we insert the new initial state gloun. call this%push_is_parton (new_id, lha_flavor, momentum_fraction) !!! has the old initial state quark got a twin? if (associated (old_is_parton%twin)) then !!! we assume that this twin is the second splitting particle. !!! so the twin becomes a final state particle now and !!! must be removed from the is stack. call this%remove_twin (-old_id, GeV_scale) else !!! the old initial state quark has been a valence quark. !!! what should we do now? is this splitting sensible at all? !!! we don't know but allow these splittings. The most trivial !!! treatment is to restore the former valence quark. this%valence_content (old_is_parton%lha_flavor) = & this%valence_content (old_is_parton%lha_flavor) + 1 end if else !!! this is a q->qg splitting. the new initial state quark emits !!! the preceding initial state gluon. yeah, backward evolution is !!! confusing! the new initial state quark is not part of the !!! proton remnant any longer. how do we remove a quark from !!! the remnant? we add a conjugated twin parton and assume, !!! that this twin is created in a not yet resolved g->qqbar splitting. call this%push_twin (new_id, lha_flavor, momentum_fraction, gev_scale) end if end if !!! everything is done. what shall we do with the old initial state !!! parton? we don't need it any more but we store it anyway. call this%fs_partons%push (old_is_parton) !!! the new initial state parton has taken away momentum, so we update !!! the remnant momentum fraction. this%momentum_fraction = this%momentum_fraction * (1 - & momentum_fraction) / (1 - old_is_parton%momentum) else !!! this is a bug. print *, "proton_remnant_replace_is_parton: parton #", old_id, & " not found on ISR stack." if (associated (this%is_partons%next)) then print *, "actual content of isr stack:" call this%is_partons%next%print_peers () else print *, "ISR stack is not associated." end if stop end if end subroutine proton_remnant_replace_is_parton @ %def proton_remnant_replace_is_parton @ <>= procedure :: write_to_marker => proton_remnant_write_to_marker <>= subroutine proton_remnant_write_to_marker (this, marker, status) class(proton_remnant_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("proton_remnant_t") call marker%mark ("valence_content", this%valence_content) call marker%mark ("momentum_fraction", this%momentum_fraction) call marker%mark ("pdf_int_weight", this%pdf_int_weight) call marker%mark_end ("proton_remnant_t") end subroutine proton_remnant_write_to_marker @ %def proton_remnant_write_to_marker @ <>= procedure :: read_from_marker => proton_remnant_read_from_marker <>= subroutine proton_remnant_read_from_marker (this, marker, status) class(proton_remnant_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status character(:), allocatable :: name call marker%pick_begin ("proton_remnant_t", status=status) call marker%pick ("valence_content", this%valence_content, status) call marker%pick ("momentum_fraction", this%momentum_fraction, status) call marker%pick ("pdf_int_weight", this%pdf_int_weight, status) call marker%pick_end ("proton_remnant_t", status=status) end subroutine proton_remnant_read_from_marker @ %def proton_remnant_read_from_marker @ <>= procedure :: print_to_unit => proton_remnant_print_to_unit <>= subroutine proton_remnant_print_to_unit (this, unit, parents, components, peers) class(proton_remnant_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, '("Components of proton_remnant_t:")') write (unit, '("Valence Content: ",I1,":",I1)')this& &%valence_content write (unit, "(1x,A,I1)") "N Twins: ", this%n_twins write (unit, "(1x,A,5(F7.3))") "INT weights [g,s,d,u,t] ", & this%pdf_int_weight write (unit, "(1x,A,F7.3)") "Total Momentum Fraction: ", & this%momentum_fraction write (unit, "(1x,A,F7.3)") "Twin Norm: ", this%twin_norm end subroutine proton_remnant_print_to_unit @ %def proton_remnant_print_to_unit @ <>= procedure, nopass :: get_type => proton_remnant_get_type <>= pure subroutine proton_remnant_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="proton_remnant_t") end subroutine proton_remnant_get_type @ %def proton_remnant_get_type @ <>= procedure :: gnuplot_momentum_kind_pdf_array => & proton_remnant_gnuplot_momentum_kind_pdf_array <>= subroutine proton_remnant_gnuplot_momentum_kind_pdf_array & (this, momentum_unit, parton_unit, GeV_scale) class(proton_remnant_t), intent(in) :: this integer, intent(in) :: momentum_unit, parton_unit real(default), intent(in) :: GeV_scale real(default), dimension(2) :: valence_pdf real(double), dimension(-6:6) :: sea_pdf real(default), dimension(this%n_twins) :: twin_pdf integer :: x real(default) :: momentum_fraction do x = 1, 100 momentum_fraction = x * 1E-2_default call this%momentum_kind_pdf_array (GeV_scale, momentum_fraction, & valence_pdf, sea_pdf) call this%momentum_twin_pdf_array (momentum_fraction, twin_pdf) write (momentum_unit, fmt=*) momentum_fraction, & sum(valence_pdf) + sum(sea_pdf) + sum(twin_pdf), & valence_pdf, sea_pdf, twin_pdf call this%parton_kind_pdf_array (GeV_scale, momentum_fraction, & valence_pdf, sea_pdf) call this%parton_twin_pdf_array (momentum_fraction, twin_pdf) write(parton_unit,fmt=* )momentum_fraction, & sum(valence_pdf) + sum(sea_pdf) + sum(twin_pdf), & valence_pdf, sea_pdf, twin_pdf end do end subroutine proton_remnant_gnuplot_momentum_kind_pdf_array @ %def proton_remnant_gnuplot_momentum_kind_pdf_array @ <>= public :: pp_remnant_t <>= type, extends (ser_class_t) :: pp_remnant_t logical :: initialized = .false. real(default), private :: gev_initial_cme = gev_cme_tot real(default), private :: X = one type(proton_remnant_t), dimension(2) :: proton class(pdfnorm_t), pointer :: pdf_norm contains <> end type pp_remnant_t @ %def pp_remnant_t @ <>= procedure :: write_to_marker => pp_remnant_write_to_marker <>= subroutine pp_remnant_write_to_marker (this, marker, status) class(pp_remnant_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("pp_remnant_t") call marker%mark ("gev_initial_cme", this%gev_initial_cme) call marker%mark ("X", this%X) call this%proton(1)%write_to_marker (marker, status) call this%proton(2)%write_to_marker (marker, status) call marker%mark_end ("pp_remnant_t") end subroutine pp_remnant_write_to_marker @ %def pp_remnant_write_to_marker @ <>= procedure :: read_from_marker => pp_remnant_read_from_marker <>= subroutine pp_remnant_read_from_marker (this, marker, status) class(pp_remnant_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status character(:), allocatable :: name call marker%pick_begin ("pp_remnant_t", status=status) call marker%pick ("gev_initial_cme", this%gev_initial_cme, status) call marker%pick ("X", this%X, status) call this%proton(1)%read_from_marker (marker, status) call this%proton(2)%read_from_marker (marker, status) call marker%pick_end ("pp_remnant_t", status=status) end subroutine pp_remnant_read_from_marker @ %def pp_remnant_read_from_marker @ <>= procedure :: print_to_unit => pp_remnant_print_to_unit <>= subroutine pp_remnant_print_to_unit (this, unit, parents, components, peers) class(pp_remnant_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers write (unit, "(1x,A)") "Components of pp_remnant_t:" write (unit, "(1x,A,F10.3)") "Initial center of mass energy: ", & this%gev_initial_cme write (unit, "(1x,A,F10.3)") "Actual center of mass energy: ", & this%get_gev_actual_cme () write (unit, "(1x,A,F10.3)") "Total Momentum Fraction is: ", this%X if (components>0) then write (unit, "(3x,A)") "Proton 1:" call this%proton(1)%print_to_unit (unit, parents, components-1, peers) write (unit, "(3x,A)") "Proton 2:" call this%proton(2)%print_to_unit (unit, parents, components-1, peers) end if ! write (unit, "(1x,A,F7.2)") "Total Momentum Fraction: ", & ! this%momentum_fraction end subroutine pp_remnant_print_to_unit @ %def pp_remnant_print_to_unit @ <>= procedure, nopass :: get_type => pp_remnant_get_type <>= pure subroutine pp_remnant_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="pp_remnant_t") end subroutine pp_remnant_get_type @ %def pp_remnant_get_type @ <>= procedure :: initialize => pp_remnant_initialize <>= subroutine pp_remnant_initialize (this, muli_dir, & lhapdf_dir, lhapdf_file, lhapdf_member) class(pp_remnant_t), intent(out) :: this character(*), intent(in) :: muli_dir, lhapdf_dir, lhapdf_file integer, intent(in) :: lhapdf_member logical :: exist allocate (this%pdf_norm) ! call InitPDFset (lhapdf_dir // lhapdf_file) ! call InitPDF (lhapdf_member) print *, "looking for previously generated pdf integrals..." inquire (file=muli_dir // "/pdf_norm_" // lhapdf_file // & ".xml", exist=exist) if (exist) then print *, "found. Starting deserialization..." call this%pdf_norm%deserialize (name="pdf_norm_" // lhapdf_file, & file=muli_dir // "/pdf_norm_" // lhapdf_file // ".xml") print *, "done." else print *, "No integrals found. Starting generation..." call this%pdf_norm%scan () print *, "done." call this%pdf_norm%serialize (name="pdf_norm_" // lhapdf_file, & file=muli_dir // "/pdf_norm_" // lhapdf_file // ".xml") end if call this%proton(1)%initialize (this%pdf_norm) call this%proton(2)%initialize (this%pdf_norm) this%initialized = .true. ! call this%print_all () end subroutine pp_remnant_initialize @ %def pp_remnant_initialize @ <>= procedure :: finalize => pp_remnant_finalize <>= subroutine pp_remnant_finalize (this) class(pp_remnant_t), intent(inout) :: this call this%proton(1)%finalize () call this%proton(2)%finalize () deallocate (this%pdf_norm) end subroutine pp_remnant_finalize @ %def pp_remnant_finalize @ <>= procedure :: apply_initial_interaction => & pp_remnant_apply_initial_interaction <>= subroutine pp_remnant_apply_initial_interaction (this, gev_cme, x1, & x2, pdg_f1, pdg_f2, n1, n2, gev_scale, rnd1, rnd2) class(pp_remnant_t), intent(inout) :: this real(default), intent(in)::gev_cme,x1,x2,gev_scale,rnd1,rnd2 integer, intent(in) :: pdg_f1, pdg_f2, n1, n2 if (this%initialized) then call this%proton(1)%apply_initial_splitting & (n1, pdg_f1, x1, gev_scale, rnd1) call this%proton(2)%apply_initial_splitting & (n2, pdg_f2, x2, gev_scale, rnd2) this%X = (one - x1) * (one - x2) this%gev_initial_cme = gev_cme ! call this%print_all () else call msg_error ("pp_remnant_apply_initial_interaction: Not yet " // & "initialized, call pp_remnant_initialize first!") end if end subroutine pp_remnant_apply_initial_interaction @ %def pp_remnant_apply_initial_interaction @ <>= procedure :: reset => pp_remnant_reset <>= subroutine pp_remnant_reset (this) class(pp_remnant_t), intent(inout) :: this call this%proton(1)%reset () call this%proton(2)%reset () this%X = one end subroutine pp_remnant_reset @ %def pp_remnant_reset @ <>= procedure :: replace_parton => pp_remnant_replace_parton <>= subroutine pp_remnant_replace_parton (this, proton_id, old_id, & new_id, pdg_f, x_proton, gev_scale) class(pp_remnant_t), intent(inout) :: this integer, intent(in) :: proton_id, old_id, new_id, pdg_f real(default), intent(in) :: x_proton, gev_scale call this%proton(proton_id)%replace_is_parton & (old_id, new_id, pdg_f, x_proton, gev_scale) end subroutine pp_remnant_replace_parton @ %def pp_remnant_replace_parton @ <>= procedure :: momentum_pdf => pp_remnant_momentum_pdf <>= subroutine pp_remnant_momentum_pdf & (this, x_proton, gev2_scale, n, pdg_f, pdf) class(pp_remnant_t), intent(in) :: this real(default), intent(in) :: x_proton, gev2_scale integer, intent(in) :: n, pdg_f real(default), intent(out) :: pdf if (n==1 .or. n==2) then if (x_proton <= this%proton(n)%momentum_fraction) then if (pdg_f == PDG_FLAVOR_g) then call this%proton(n)%momentum_flavor_pdf (sqrt(GeV2_scale), & x_proton / this%proton(n)%momentum_fraction, & LHA_FLAVOR_g, pdf) else call this%proton(n)%momentum_flavor_pdf (sqrt(GeV2_scale), & x_proton / this%proton(n)%momentum_fraction, & pdg_f, pdf) end if pdf = pdf * this%proton(n)%momentum_fraction else pdf = zero end if else call msg_error ("pp_remnant_momentum_pdf: n must be either 1 or 2, " & // "but it is " // char (str (n)) // ".") stop end if end subroutine pp_remnant_momentum_pdf @ %def pp_remnant_momentum_pdf @ <>= procedure :: parton_pdf => pp_remnant_parton_pdf <>= subroutine pp_remnant_parton_pdf (this, x_proton, gev2_scale, n, pdg_f, pdf) class(pp_remnant_t), intent(in) :: this real(default), intent(in) :: x_proton, gev2_scale integer, intent(in) :: n, pdg_f real(default), intent(out) :: pdf if (n==1 .or. n==2) then if (x_proton <= this%proton(n)%momentum_fraction) then if (pdg_f == PDG_FLAVOR_g) then call this%proton(n)%parton_flavor_pdf (sqrt(GeV2_scale), & x_proton/this%proton(n)%momentum_fraction, LHA_FLAVOR_g, & pdf) else call this%proton(n)%parton_flavor_pdf (sqrt(GeV2_scale), & x_proton/this%proton(n)%momentum_fraction,pdg_f, pdf) end if pdf = pdf * this%proton(n)%momentum_fraction else pdf = zero end if else call msg_error ("pp_remnant_parton_pdf: n must be either 1 or 2, " & // "but it is " // char (str (n)) // ".") stop end if end subroutine pp_remnant_parton_pdf @ %def pp_remnant_parton_pdf @ <>= procedure :: apply_interaction => pp_remnant_apply_interaction <>= subroutine pp_remnant_apply_interaction (this, qcd_2_2) class(pp_remnant_t), intent(inout) :: this class(qcd_2_2_class), intent(in) :: qcd_2_2 integer, dimension(4) :: lha_f integer, dimension(2) :: int_k real(default) :: gev_pt real(default), dimension(2) :: mom_f integer :: n mom_f = qcd_2_2%get_remnant_momentum_fractions () lha_f = qcd_2_2%get_lha_flavors () int_k = qcd_2_2%get_pdf_int_kinds () gev_pt = qcd_2_2%get_gev_scale () ! print *,"pp_remnant_apply_interaction", mom_f, & ! qcd_2_2%get_parton_id(1), qcd_2_2%get_parton_id(2), lha_f do n = 1, 2 select case (int_k(n)) case (PDF_VALENCE_DOWN) call this%proton(n)%remove_valence_down_quark & (qcd_2_2%get_parton_id(n), gev_pt, mom_f(n)) case (PDF_VALENCE_UP) call this%proton(n)%remove_valence_up_quark & (qcd_2_2%get_parton_id(n), gev_pt, mom_f(n)) case (PDF_SEA) call this%proton(n)%remove_sea_quark & (qcd_2_2%get_parton_id(n), gev_pt, mom_f(n), lha_f(n)) case (PDF_GLUON) call this%proton(n)%remove_gluon & (qcd_2_2%get_parton_id(n), gev_pt, mom_f(n)) end select end do this%X = this%proton(1)%momentum_fraction * & this%proton(2)%momentum_fraction end subroutine pp_remnant_apply_interaction @ %def pp_remnant_apply_interaction @ <>= procedure :: get_pdf_int_weights => pp_remnant_get_pdf_int_weights <>= pure function pp_remnant_get_pdf_int_weights & (this, pdf_int_kinds) result (weight) class(pp_remnant_t), intent(in) :: this real(default) :: weight integer, dimension(2), intent(in) :: pdf_int_kinds ! pdf_int_kind weight = this%proton(1)%pdf_int_weight (pdf_int_kinds(1)) * & this%proton(2)%pdf_int_weight (pdf_int_kinds(2)) !*((this%x)**2) end function pp_remnant_get_pdf_int_weights @ %def pp_remnant_get_pdf_int_weights @ <>= procedure :: get_pdf_int_weight => pp_remnant_get_pdf_int_weight <>= elemental function pp_remnant_get_pdf_int_weight & (this, kind1, kind2) result (weight) class(pp_remnant_t), intent(in) :: this real(double) :: weight integer, intent(in) :: kind1, kind2 ! pdf_int_kind weight = this%proton(1)%pdf_int_weight(kind1) * & this%proton(2)%pdf_int_weight(kind2) !*((this%x)**2) end function pp_remnant_get_pdf_int_weight @ %def pp_remnant_get_pdf_int_weight @ <>= procedure :: set_pdf_weight => pp_remnant_set_pdf_weight <>= subroutine pp_remnant_set_pdf_weight (this, weights) class(pp_remnant_t), intent(inout) :: this real(default), dimension(10), intent(in) :: weights this%proton(1)%pdf_int_weight = weights(1:5) this%proton(2)%pdf_int_weight = weights(6:10) end subroutine pp_remnant_set_pdf_weight @ %def pp_remnant_set_pdf_weight @ <>= procedure :: get_gev_initial_cme => pp_remnant_get_gev_initial_cme <>= elemental function pp_remnant_get_gev_initial_cme (this) result (cme) class(pp_remnant_t), intent(in) :: this real(double) :: cme cme =this%gev_initial_cme end function pp_remnant_get_gev_initial_cme @ %def pp_remnant_get_gev_initial_cme @ <>= procedure :: get_gev_actual_cme => pp_remnant_get_gev_actual_cme <>= elemental function pp_remnant_get_gev_actual_cme (this) result (cme) class(pp_remnant_t), intent(in) :: this real(double) :: cme cme = this%gev_initial_cme * this%X end function pp_remnant_get_gev_actual_cme @ %def pp_remnant_get_gev_actual_cme @ <>= procedure :: get_cme_fraction => pp_remnant_get_cme_fraction <>= elemental function pp_remnant_get_cme_fraction (this) result (cme) class(pp_remnant_t), intent(in) :: this real(double) :: cme cme = this%X end function pp_remnant_get_cme_fraction @ %def pp_remnant_get_cme_fraction @ <>= procedure :: get_proton_remnant_momentum_fractions => & pp_remnant_get_proton_remnant_momentum_fractions <>= pure function pp_remnant_get_proton_remnant_momentum_fractions & (this) result (fractions) class(pp_remnant_t), intent(in) :: this real(double), dimension(2) :: fractions fractions = [this%proton(1)%get_momentum_fraction(), & this%proton(2)%get_momentum_fraction()] end function pp_remnant_get_proton_remnant_momentum_fractions @ %def pp_remnant_get_proton_remnant_momentum_fractions @ <>= procedure :: get_proton_remnants => pp_remnant_get_proton_remnants <>= subroutine pp_remnant_get_proton_remnants (this, proton1, proton2) class(pp_remnant_t), target, intent(in) :: this class(proton_remnant_t), intent(out), pointer :: proton1, proton2 proton1 => this%proton(1) proton2 => this%proton(2) end subroutine pp_remnant_get_proton_remnants @ %def pp_remnant_get_proton_remnants @ <>= procedure :: get_remnant_parton_flavor_pdf_arrays => & pp_remnant_get_remnant_parton_flavor_pdf_arrays <>= subroutine pp_remnant_get_remnant_parton_flavor_pdf_arrays & (this, GeV_scale, momentum1, momentum2, pdf1, pdf2) class(pp_remnant_t), intent(in) :: this real(default), intent(in) :: GeV_scale, momentum1, momentum2 real(double), dimension(-6:6), intent(out) :: pdf1, pdf2 call this%proton(1)%parton_flavor_pdf_array (GeV_scale, momentum1, pdf1) call this%proton(2)%parton_flavor_pdf_array (GeV_scale, momentum2, pdf2) end subroutine pp_remnant_get_remnant_parton_flavor_pdf_arrays @ %def pp_remnant_get_remnant_parton_flavor_pdf_arrays @ <>= interface subroutine getxmin (mem, xmin) integer, intent(in) :: mem double precision, intent(out) :: xmin end subroutine getxmin end interface @ %def getxmin @ <>= interface subroutine getxmax (mem, xmax) integer, intent(in) :: mem double precision, intent(out) :: xmax end subroutine getxmax end interface @ %def getxmax @ <>= interface subroutine getq2min (mem, q2min) integer, intent(in) :: mem double precision, intent(out) :: q2min end subroutine getq2min end interface @ %def getq2min @ <>= interface subroutine getq2max (mem, q2max) integer, intent(in) :: mem double precision, intent(out) :: q2max end subroutine getq2max end interface @ %def getq2max @ <>= pure function remnant_dglap_splitting_gqq (z) result(p) real(default) :: p real(default), intent(in) :: z p = (z**2 + (1-z)**2) / two end function remnant_dglap_splitting_gqq @ %def remnant_dglap_splitting_gqq @ <>= pure function remnant_gluon_pdf_approx (x, p) result (g) real(default) :: g integer, intent(in) :: p real(default), intent(in) :: x g = ((1-x)**p) / x end function remnant_gluon_pdf_approx @ %def remnant_gluon_pdf_approx @ <>= pure function remnant_norm_0 (xs) result (c0) real(default) :: c0 real(default), intent(in) :: xs c0 = 6*xs / (2 - xs * (3 - 3*xs + 2*xs**2)) end function remnant_norm_0 @ %def remnant_norm_0 @ <>= pure function remnant_norm_1 (xs) result (c1) real(default) :: c1 real(default), intent(in)::xs c1 = 3*xs / (2 - xs**2 * (3-xs) + 3*xs*log(xs)) end function remnant_norm_1 @ %def remnant_norm_1 @ <>= pure function remnant_norm_4 (xs) result (c4) real(default) :: c4 real(default), intent(in) :: xs real(default) :: y if ((one-xs) > 1E-3_default) then c4 = 3*xs / (1 + 11*xs + 6*xs*log(xs) + 12*xs**3*log(xs) + & 18*xs**2*log(xs) + 9*xs**2 - 19*xs**3 - 2*xs**4) else y=one / (one-xs) c4= 1130._default / 11907._default & - 10._default * y**5 & - 40._default * y**4 / three & -160._default * y**3 / 63._default & + 50._default * y**2 / 189._default & -565._default * y / 3969._default & -186170._default * (one-xs) / 2750517._default end if end function remnant_norm_4 @ %def remnant_norm_4 @ <>= pure function remnant_norm (xs, p) result (c) real(default) :: c real(default), intent(in) :: xs integer, intent(in) :: p select case (p) case (0) c = remnant_norm_0 (xs) case (1) c = remnant_norm_1 (xs) case default c = remnant_norm_4 (xs) end select end function remnant_norm @ %def remnant_norm @ <>= pure function remnant_twin_pdf_p (x, xs, p) result (qc) real(default) :: qc real(default), intent(in) :: x, xs integer, intent(in) :: p qc = remnant_norm (xs, p) * remnant_gluon_pdf_approx (xs + x, p) & * remnant_dglap_splitting_gqq (xs / (xs+x)) / (xs+x) end function remnant_twin_pdf_p @ %def remnant_twin_pdf_p @ <>= elemental function remnant_twin_momentum_4 (xs) result (p) real(default) :: p real(default), intent(in) :: xs if (xs < 0.99_default) then p = (-9 * (-1+xs) * xs * (1+xs) * (5+xs*(24+xs)) + & 12*xs*(1+2*xs)*(1+2*xs*(5+2*xs))*Log(xs))/& (8*(1+2*xs)*((-1+xs)*(1+xs*(10+xs))-6*xs*(1+xs)*Log(xs))) else p = (1-xs) / 6 - (5*(-1+xs)**2) / 63 + (5*(-1+xs)**3) / 216 end if end function remnant_twin_momentum_4 @ %def remnant_twin_momentum_4 @ <>= subroutine gnuplot_integrated_pdf (this, momentum_unit, parton_unit) class(proton_remnant_t), intent(in) :: this integer, intent(in) :: momentum_unit, parton_unit ! real(double), intent(in) :: gev_scale integer, parameter :: x_grid = 1000000 integer, parameter :: q_grid = 100 integer :: n, m, mem real(default) :: x, q, dx, dq, overall_sum, xmin, xmax, & q2min, q2max, qmin, qmax real(double) :: q2min_dbl, q2max_dbl, xmin_dbl, xmax_dbl real(double), dimension(-6:6) :: sea_pdf, sea_momentum_pdf_sum, & sea_parton_pdf_sum real(default), dimension(2) :: valence_pdf, valence_momentum_pdf_sum,& valence_parton_pdf_sum real(default), allocatable, dimension(:) :: twin_momentum_pdf_sum class(muli_parton_t), pointer :: tmp_twin mem = 1 call GetXmin (mem, xmin_dbl) call GetXmax (mem, xmax_dbl) call GetQ2max (mem, q2max_dbl) call GetQ2min (mem, q2min_dbl) xmin = xmin_dbl xmax = xmax_dbl q2min = q2min_dbl q2max = q2max_dbl qmin = sqrt(q2min) qmax = sqrt(q2max) print *, "qmin=", qmin, "GeV" print *, "qmax=", qmax, "GeV" dx = (xmax-xmin) / x_grid dq = (qmax-qmin) / q_grid q = qmin + dq / 2D0 tmp_twin => this%twin_partons%next n = 0 if (this%n_twins > 0) then allocate (twin_momentum_pdf_sum (this%n_twins)) do while (associated (tmp_twin)) n = n + 1 twin_momentum_pdf_sum(n) = tmp_twin%momentum tmp_twin => tmp_twin%next end do end if do m = 1, q_grid valence_momentum_pdf_sum = [0D0,0D0] valence_parton_pdf_sum = [0D0,0D0] sea_momentum_pdf_sum = & [0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0] sea_parton_pdf_sum = & [0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0] x = xmin + dx / 2D0 do n = 1, x_grid call this%parton_kind_pdf_array (Q, x, valence_pdf, sea_pdf) valence_parton_pdf_sum = valence_parton_pdf_sum + valence_pdf sea_parton_pdf_sum = sea_parton_pdf_sum + sea_pdf call this%momentum_kind_pdf_array (Q, x, valence_pdf, sea_pdf) valence_momentum_pdf_sum = valence_momentum_pdf_sum + valence_pdf sea_momentum_pdf_sum = sea_momentum_pdf_sum + sea_pdf x = x + dx end do valence_parton_pdf_sum = valence_parton_pdf_sum * dx sea_parton_pdf_sum = sea_parton_pdf_sum * dx valence_momentum_pdf_sum = valence_momentum_pdf_sum * dx sea_momentum_pdf_sum = sea_momentum_pdf_sum * dx if (this%n_twins > 0) then write (momentum_unit, fmt=*) q, & sum(valence_momentum_pdf_sum) + & sum(sea_momentum_pdf_sum) + sum(twin_momentum_pdf_sum), & valence_momentum_pdf_sum, & sea_momentum_pdf_sum, & twin_momentum_pdf_sum else write (momentum_unit, fmt=*) q, & sum(valence_momentum_pdf_sum) + sum(sea_momentum_pdf_sum), & valence_momentum_pdf_sum, & sea_momentum_pdf_sum end if write (parton_unit,fmt=*) q, & sum(valence_parton_pdf_sum) + sum(sea_parton_pdf_sum), & valence_parton_pdf_sum, & sea_parton_pdf_sum q = q + dq end do end subroutine gnuplot_integrated_pdf @ %def gnuplot_integrated_pdf @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The Multiple Interactions main module} This file contains the module [[muli]] which is the multiple parton interactions interface module to \whizard. [[muli]] is supposed to run together with initial state radiation. Both share a momentum evolution variable and compete for beam momentum, so the generation of this scale variable must be fully transparent to \whizard. That is why the corresponding procedures are here, while all other work like phase space integration, flavor generation and treatment of the beam remnant is put into [[muli_dsigma]], [[muli_mcint]] and [[muli_remnant]], respectively. [[qcd_2_2_t]] is a container class for properties of QCD $2\to 2$ interactions. It holds a very condensed internal representation and offers a convenient set of TBP to query all aspects without the burden of the generator internals. [[muli_t]] then is an extension of [[qcd_2_2_t]] that adds generator internals like random number generator, integrated cross-sections, the actual Monte Carlo generator for flavor generation and beam remnants in [[tao_rnd]], [[dsigma]], samples and beam, respectively. <<[[muli.f90]]>>= <> module muli use, intrinsic :: iso_fortran_env <> use constants use tao_random_numbers !NODEP! use muli_base use muli_momentum use muli_trapezium use muli_interactions use muli_dsigma use muli_mcint use muli_remnant <> <> <> <> contains <> end module muli @ %def muli <>= logical, parameter :: muli_default_modify_pdfs = .true. integer, parameter :: muli_default_lhapdf_member = 0 character(*), parameter :: muli_default_lhapdf_file = "cteq6ll.LHpdf" @ %def muli_default_modify_pdfs muli_default_lhapdf_member @ %def muli_default_lhapdf_file @ <>= type, extends(qcd_2_2_class) :: qcd_2_2_t private integer :: process_id = -1 integer :: integrand_id = -1 integer, dimension(2) :: parton_ids = [0,0] integer, dimension(4) :: flow = [0,0,0,0] real(default), dimension(3) :: momentum_fractions = [-one, -one, -one] real(default), dimension(3) :: hyperbolic_fractions = [-one ,- one,- one] contains <> end type qcd_2_2_t @ %def qcd_2_2_t @ <>= procedure :: write_to_marker => qcd_2_2_write_to_marker <>= subroutine qcd_2_2_write_to_marker (this, marker, status) class(qcd_2_2_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("qcd_2_2_t") call this%mom_write_to_marker (marker, status) call marker%mark ("process_id", this%process_id) call marker%mark ("integrand_id", this%integrand_id) call marker%mark ("momentum_fractions", this%momentum_fractions) call marker%mark ("hyperbolic_fractions", this%hyperbolic_fractions) call marker%mark_end("qcd_2_2_t") end subroutine qcd_2_2_write_to_marker @ %def qcd_2_2_write_to_marker @ <>= procedure :: read_from_marker => qcd_2_2_read_from_marker <>= subroutine qcd_2_2_read_from_marker (this, marker, status) class(qcd_2_2_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("qcd_2_2_t", status=status) call this%mom_read_from_marker (marker, status) call marker%pick ("process_id", this%process_id, status) call marker%pick ("integrand_id", this%integrand_id, status) call marker%pick ("momentum_fractions", this%momentum_fractions, status) call marker%pick & ("hyperbolic_fractions", this%hyperbolic_fractions, status) call marker%pick_end ("qcd_2_2_t", status=status) end subroutine qcd_2_2_read_from_marker @ %def qcd_2_2_read_from_marker @ <>= procedure :: print_to_unit => qcd_2_2_print_to_unit <>= subroutine qcd_2_2_print_to_unit (this, unit, parents, components, peers) class(qcd_2_2_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers integer, dimension(2,4) :: flow integer :: index if (parents > i_zero) & call this%mom_print_to_unit (unit, parents-1, components, peers) write (unit, "(1x,A)") "Components of qcd_2_2_t:" write (unit, "(3x,A,I3)") "Process id is: ", this%get_process_id () write (unit, "(3x,A,I3)") "Integrand id is: ", this%get_integrand_id () if (this%get_integrand_id () > 0) then write (unit, "(3x,A,4(I3))") "LHA Flavors are: ", & this%get_lha_flavors () write (unit, "(3x,A,4(I3))") "PDG Flavors are: ", & this%get_pdg_flavors () write (unit, "(3x,A,2(I3))") "Parton kinds are: ", & this%get_parton_kinds () write (unit, "(3x,A,2(I3))") "PDF int kinds are: ", & this%get_pdf_int_kinds () write (unit, "(3x,A,2(I3))") "Diagram kind is: ", & this%get_diagram_kind () end if call this%get_color_correlations (1, index, flow) write (unit, "(3x,A,4(I0))") "Color Permutations: ", this%flow write (unit, "(3x,A)") "Color Connections:" write (unit, & '(" (",I0,",",I0,")+(",I0,",",I0,")->(",I0,",",I0,& &")+(",I0,",",I0,")")') flow write (unit, "(3x,A,E14.7)") "Evolution scale is: ", & this%get_unit2_scale () write (unit, "(3x,A,E14.7)") "Momentum boost is: ", & this%get_momentum_boost () write (unit, "(3x,A,2(E14.7))") "Remant momentum fractions are: ", & this%get_remnant_momentum_fractions () write (unit, "(3x,A,2(E14.7))") "Total momentum fractions are: ", & this%get_total_momentum_fractions () end subroutine qcd_2_2_print_to_unit @ %def qcd_2_2_print_to_unit @ <>= procedure, nopass :: get_type => qcd_2_2_get_type <>= pure subroutine qcd_2_2_get_type (type) character(:), allocatable, intent(out) :: type allocate (type, source="qcd_2_2_t") end subroutine qcd_2_2_get_type @ %def qcd_2_2_get_type @ <>= procedure :: get_process_id => qcd_2_2_get_process_id <>= elemental function qcd_2_2_get_process_id (this) result (id) class(qcd_2_2_t), intent(in) :: this integer :: id id = this%process_id end function qcd_2_2_get_process_id @ %def qcd_2_2_get_process_id @ <>= procedure :: get_integrand_id => qcd_2_2_get_integrand_id <>= elemental function qcd_2_2_get_integrand_id (this) result (id) class(qcd_2_2_t), intent(in) :: this integer :: id id = this%integrand_id end function qcd_2_2_get_integrand_id @ %def qcd_2_2_get_integrand_id @ <>= procedure :: get_diagram_kind => qcd_2_2_get_diagram_kind <>= elemental function qcd_2_2_get_diagram_kind (this) result (kind) class(qcd_2_2_t), intent(in) :: this integer :: kind kind = valid_processes (6, this%process_id) end function qcd_2_2_get_diagram_kind @ %def qcd_2_2_get_diagram_kind @ This is one more hack. Before merging into the interleaved algorithm, [[muli]] has only cared for summed cross sections, but not in specific color flows. So two different diagrams with equal cross sections were summed up to diagram kind 1. Now [[muli]] also generates color flows, so we must devide diagram kind 1 into diagram color kind 0 and diagram color kind 1. <>= procedure :: get_diagram_color_kind => qcd_2_2_get_diagram_color_kind <>= pure function qcd_2_2_get_diagram_color_kind (this) result (kind) class(qcd_2_2_t), intent(in) :: this integer :: kind kind = valid_processes (6, this%process_id) if (kind == 1) then if (product (valid_processes (1:2,this%process_id)) > 0) then kind = 0 end if end if end function qcd_2_2_get_diagram_color_kind @ %def qcd_2_2_get_diagram_color_kind @ <>= procedure :: get_io_kind => qcd_2_2_get_io_kind <>= elemental function qcd_2_2_get_io_kind (this) result (kind) class(qcd_2_2_t), intent(in) :: this integer :: kind kind = valid_processes (5, this%process_id) end function qcd_2_2_get_io_kind @ %def qcd_2_2_get_io_kind @ <>= procedure :: get_lha_flavors => qcd_2_2_get_lha_flavors <>= pure function qcd_2_2_get_lha_flavors (this) result (lha) class(qcd_2_2_t), intent(in) :: this integer, dimension(4) :: lha lha = valid_processes (1:4, this%process_id) end function qcd_2_2_get_lha_flavors @ %def qcd_2_2_get_lha_flavors @ <>= procedure :: get_pdg_flavors => qcd_2_2_get_pdg_flavors <>= pure function qcd_2_2_get_pdg_flavors (this) result (pdg) class(qcd_2_2_t), intent(in) :: this integer, dimension(4) :: pdg pdg = this%get_lha_flavors () where (pdg == 0) pdg = 21 end function qcd_2_2_get_pdg_flavors @ %def qcd_2_2_get_pdg_flavors @ <>= procedure :: get_parton_id => qcd_2_2_get_parton_id <>= pure function qcd_2_2_get_parton_id (this, n) result (id) class(qcd_2_2_t), intent(in) :: this integer, intent(in) :: n integer :: id id = this%parton_ids (n) end function qcd_2_2_get_parton_id @ %def qcd_2_2_get_parton_id @ <>= procedure :: get_parton_kinds => qcd_2_2_get_parton_kinds <>= pure function qcd_2_2_get_parton_kinds (this) result (kinds) class(qcd_2_2_t), intent(in) :: this integer, dimension(2) :: kinds kinds = this%get_pdf_int_kinds () kinds(1) = parton_kind_of_int_kind (kinds(1)) kinds(2) = parton_kind_of_int_kind (kinds(2)) end function qcd_2_2_get_parton_kinds @ %def qcd_2_2_get_parton_kinds @ <>= procedure :: get_pdf_int_kinds => qcd_2_2_get_pdf_int_kinds <>= pure function qcd_2_2_get_pdf_int_kinds (this) result (kinds) class(qcd_2_2_t), intent(in) :: this integer, dimension(2) :: kinds kinds = double_pdf_kinds (1:2, this%integrand_id) end function qcd_2_2_get_pdf_int_kinds @ %def qcd_2_2_get_pdf_int_kinds @ <>= procedure :: get_momentum_boost => qcd_2_2_get_momentum_boost <>= elemental function qcd_2_2_get_momentum_boost (this) result (boost) class(qcd_2_2_t), intent(in) :: this real(default) :: boost boost = - one ! print('("qcd_2_2_get_momentum_boost: not yet implemented.")') ! boost = this%momentum_boost end function qcd_2_2_get_momentum_boost @ %def qcd_2_2_get_momentum_boost @ <>= procedure :: get_hyperbolic_fractions => qcd_2_2_get_hyperbolic_fractions <>= pure function qcd_2_2_get_hyperbolic_fractions (this) result (fractions) class(qcd_2_2_t), intent(in) :: this real(double), dimension(3) :: fractions fractions = this%hyperbolic_fractions end function qcd_2_2_get_hyperbolic_fractions @ %def qcd_2_2_get_hyperbolic_fractions @ <>= procedure :: get_remnant_momentum_fractions => & qcd_2_2_get_remnant_momentum_fractions <>= pure function qcd_2_2_get_remnant_momentum_fractions & (this) result (fractions) class(qcd_2_2_t), intent(in) :: this real(default), dimension(2) :: fractions fractions = this%momentum_fractions(1:2) end function qcd_2_2_get_remnant_momentum_fractions @ %def qcd_2_2_get_remnant_momentum_fractions @ <>= procedure :: get_total_momentum_fractions => & qcd_2_2_get_total_momentum_fractions <>= pure function qcd_2_2_get_total_momentum_fractions & (this) result (fractions) class(qcd_2_2_t), intent(in) :: this real(default), dimension(2) :: fractions fractions = [-one, -one] ! fractions = this%hyperbolic_fractions(1:2) * & ! this%beam%get_proton_remnant_momentum_fractions() end function qcd_2_2_get_total_momentum_fractions @ %def qcd_2_2_get_total_momentum_fractions @ <>= procedure :: get_color_flow => qcd_2_2_get_color_flow <>= pure function qcd_2_2_get_color_flow (this) result (flow) class(qcd_2_2_t), intent(in) :: this integer, dimension(4) :: flow flow = this%flow end function qcd_2_2_get_color_flow @ %def qcd_2_2_get_color_flow @ <>= procedure :: get_color_correlations => qcd_2_2_get_color_correlations <>= subroutine qcd_2_2_get_color_correlations & (this, start_index, final_index, flow) class(qcd_2_2_t), intent(in) :: this integer, intent(in) :: start_index integer, intent(out) :: final_index integer, dimension(2,4), intent(out) :: flow integer :: pos, f_end, f_beginning final_index = start_index !!! We set all flows to i_zero. i_zero means no connection. flow = reshape([0,0,0,0,0,0,0,0],[2,4]) !!! look at all four possible ends of color lines do f_end = 1, 4 !!! The beginning of of this potential line is stored in flow. !!! i_zero means no line. f_beginning = this%flow(f_end) !!! Is there a line beginning at f_beginning and ending at f_end? if (f_beginning > 0) then !!! yes it is. we get a new number for this new line final_index = final_index + 1 !!! Is this line beginning in the initial state? if (f_beginning < 3) then !!! Yes it is. lets connect the color entry of f_begin. flow(1,f_beginning) = final_index else !!! No, it's the final state. !!! lets connect the anticolor entry of f_begin. flow(2,f_beginning) = final_index end if !!! Is this line ending in the final state? if (f_end > 2) then !!! Yes it is. lets connect the color entry of f_end. flow(1,f_end) = final_index else !!! No, it's the initial state. !!! Lets connect the anticolor entry of f_end. flow(2,f_end) = final_index end if end if end do end subroutine qcd_2_2_get_color_correlations @ %def qcd_2_2_get_color_correlations @ <>= generic :: initialize => qcd_2_2_initialize procedure :: qcd_2_2_initialize <>= subroutine qcd_2_2_initialize (this, gev2_s, process_id, & integrand_id, parton_ids, flow, hyp, cart) class(qcd_2_2_t), intent(out) :: this real(default), intent(in) :: gev2_s integer, intent(in) :: process_id, integrand_id integer, dimension(2), intent(in) :: parton_ids integer, dimension(4), intent(in) :: flow real(default), dimension(3), intent(in)::hyp real(default), dimension(3), intent(in), optional :: cart call this%initialize (gev2_s) this%process_id = process_id this%integrand_id = integrand_id this%parton_ids = parton_ids this%flow = flow this%hyperbolic_fractions = hyp if (present (cart)) then this%momentum_fractions = cart else this%momentum_fractions = h_to_c_param (hyp) end if end subroutine qcd_2_2_initialize @ %def qcd_2_2_initialize @ \subsection{The main Multiple Interactions type} <>= public :: muli_t <>= type, extends(qcd_2_2_t) :: muli_t real(default) :: GeV2_scale_cutoff logical :: modify_pdfs = muli_default_modify_pdfs !!! Pt chain status logical :: finished = .false. logical :: exceeded = .false. !!! Timers real(default) :: init_time = zero real(default) :: pt_time = zero real(default) :: partons_time = zero real(default) :: confirm_time = zero !!! Generator internals logical :: initialized = .false. logical :: initial_interaction_given = .false. real(default) :: mean = one real(default), dimension(0:16) :: start_integrals = & [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] type(tao_random_state) :: tao_rnd type(muli_trapezium_tree_t) :: dsigma type(sample_inclusive_t) :: samples type(pp_remnant_t) :: beam !!! These pointers shall not be allocated, deallocated, !!! serialized or deserialized explicitly. class(muli_trapezium_node_class_t), pointer :: node => null() contains <> end type muli_t @ %def muli_t @ <>= procedure :: write_to_marker => muli_write_to_marker <>= subroutine muli_write_to_marker (this, marker, status) class(muli_t), intent(in) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%mark_begin ("muli_t") call qcd_2_2_write_to_marker (this, marker, status) call marker%mark ("modify_pdfs", this%modify_pdfs) call marker%mark ("initialized", this%initialized) call marker%mark & ("initial_interaction_given", this%initial_interaction_given) call marker%mark ("finished", this%finished) call marker%mark ("init_time", this%init_time) call marker%mark ("pt_time", this%pt_time) call marker%mark ("partons_time", this%partons_time) call marker%mark ("confirm_time", this%confirm_time) ! call marker%mark_instance (this%start_values, "start_values") call marker%mark_instance (this%dsigma, "dsigma") call marker%mark_instance (this%samples, "samples") call marker%mark_instance (this%beam, "beam") call marker%mark_end ("muli_t") end subroutine muli_write_to_marker @ %def muli_write_to_marker @ <>= procedure :: read_from_marker => muli_read_from_marker <>= subroutine muli_read_from_marker (this, marker, status) class(muli_t), intent(out) :: this class(marker_t), intent(inout) :: marker integer(dik), intent(out) :: status call marker%pick_begin ("muli_t", status=status) call qcd_2_2_read_from_marker (this, marker, status) call marker%pick ("modify_pdfs", this%modify_pdfs, status) call marker%pick ("initialized", this%initialized, status) call marker%pick & ("initial_interaction_given", this%initial_interaction_given, status) call marker%pick ("finished", this%finished, status) call marker%pick ("init_time", this%init_time, status) call marker%pick ("pt_time", this%pt_time, status) call marker%pick ("partons_time", this%partons_time, status) call marker%pick ("confirm_time", this%confirm_time, status) ! call marker%pick_instance & ! ("start_values", this%start_values, status=status) call marker%pick_instance ("dsigma", this%dsigma, status=status) call marker%pick_instance ("samples", this%samples, status=status) call marker%pick_instance ("beam", this%beam, status=status) call marker%pick_end ("muli_t", status) end subroutine muli_read_from_marker @ %def muli_read_from_marker @ <>= procedure :: print_to_unit => muli_print_to_unit <>= subroutine muli_print_to_unit (this, unit, parents, components, peers) class(muli_t), intent(in) :: this integer, intent(in) :: unit integer(dik), intent(in) :: parents, components, peers if (parents>0) & call qcd_2_2_print_to_unit (this, unit, parents-1, components, peers) write (unit, "(1x,A)") "Components of muli_t :" write (unit, "(3x,A)") "Model Parameters:" write (unit, "(3x,A,E20.10)") "GeV2_scale_cutoff : ", & this%GeV2_scale_cutoff write (unit, "(3x,A,L1)") "Modify PDF : ", this%modify_pdfs write (unit, "(3x,A)") "PT Chain Status:" write (unit, "(3x,A,L1)") "Initialized : ", this%initialized write (unit, "(3x,A,L1)") "initial_interaction_given: ", & this%initial_interaction_given write (unit, "(3x,A,L1)") "Finished : ", this%finished write (unit, "(3x,A,L1)") "Exceeded : ", this%exceeded write (unit, "(3x,A)") "Generator Internals:" write (unit, "(3x,A,E20.10)") "Mean Value : ", this%mean if (components > i_zero) then write (unit, "(3x,A,16(E20.10))") "Start Integrals : ", & this%start_integrals(1:16) ! write (unit, "(3x,A)") "start_values Component:" ! call this%start_values%print_to_unit & ! (unit, parents, components-1, peers) write (unit, "(3x,A)") "dsigma Component:" call this%dsigma%print_to_unit (unit, parents, components-1, peers) write (unit, "(3x,A)") "samples Component:" call this%samples%print_to_unit (unit, parents, components-1, peers) write (unit, "(3x,A)") "beam Component:" call this%beam%print_to_unit (unit, parents, components-1, peers) else write (unit, "(3x,A)") "Skipping Derived-Type Components." end if ! call print_comp_pointer (this%start_node, unit, i_zero, & ! min(components-1,i_one), i_zero, "start_node") ! call serialize_print_comp_pointer (this%node, unit, i_zero, & ! min(components-1,i_one), i_zero, "node") end subroutine muli_print_to_unit @ %def muli_print_to_unit @ <>= procedure, nopass :: get_type => muli_get_type <>= pure subroutine muli_get_type(type) character(:), allocatable, intent(out) :: type allocate (type, source="muli_t") end subroutine muli_get_type @ %def muli_get_type @ <>= generic :: initialize => muli_initialize procedure :: muli_initialize <>= subroutine muli_initialize (this, GeV2_scale_cutoff, gev2_s, & muli_dir, random_seed) class(muli_t), intent(out) :: this real(kind=default), intent(in) :: gev2_s, GeV2_scale_cutoff character(*), intent(in) :: muli_dir integer, intent(in), optional :: random_seed real(double) :: time logical :: exist type(muli_dsigma_t) :: dsigma_aq character(3) :: lhapdf_member_c call cpu_time(time) this%init_time = this%init_time-time print *, "muli_initialize: The MULI modules are still not fully " & // "populated, so MULI might generate some dummy values instead " & // "of real Monte Carlo generated interactions." print *, "Given Parameters:" print *, "GeV2_scale_cutoff=", GeV2_scale_cutoff print *, "muli_dir=", muli_dir print *, "lhapdf_dir=", "" print *, "lhapdf_file=", muli_default_lhapdf_file print *, "lhapdf_member=", muli_default_lhapdf_member print *, "" call this%transverse_mom_t%initialize (gev2_s) call this%beam%initialize (muli_dir, lhapdf_dir="", & lhapdf_file=muli_default_lhapdf_file, & lhapdf_member=muli_default_lhapdf_member) this%GeV2_scale_cutoff = GeV2_scale_cutoff if (present(random_seed)) then call tao_random_create (this%tao_rnd, random_seed) else call tao_random_create (this%tao_rnd, 1) end if print *, "looking for previously generated root function..." call integer_with_leading_zeros (muli_default_lhapdf_member, 3, & lhapdf_member_c) inquire (file=muli_dir//"/dsigma_"//muli_default_lhapdf_file//".xml", & exist=exist) if (exist) then print *, "found. Starting deserialization..." call this%dsigma%deserialize & (name="dsigma_"//muli_default_lhapdf_file//"_"//lhapdf_member_c, & file=muli_dir//"/dsigma_"//muli_default_lhapdf_file//".xml") ! call this%dsigma%print_all () print *, "done. Starting generation of plots..." call this%dsigma%gnuplot (muli_dir) print *, "done." else print *, & "No root function found. Starting generation of root function..." call dsigma_aq%generate (GeV2_scale_cutoff, gev2_s, this%dsigma) print *, "done. Starting serialization of root function..." call this%dsigma%serialize & (name="dsigma_"//muli_default_lhapdf_file//"_"//lhapdf_member_c, & file=muli_dir//"/dsigma_"//muli_default_lhapdf_file//".xml") print *, "done. Starting serialization of generator..." call dsigma_aq%serialize & (name="dsigma_aq_"//muli_default_lhapdf_file//"_" // & lhapdf_member_c, file=muli_dir//"/dsigma_aq_" // & muli_default_lhapdf_file//".xml") print *,"done. Starting generation of plots..." call this%dsigma%gnuplot (muli_dir) print *, "done." end if print *, "" print *, "looking for previously generated samples..." inquire (file=muli_dir//"/samples.xml", exist=exist) if (exist) then print *, "found. Starting deserialization..." call this%samples%deserialize ("samples",muli_dir//"/samples.xml") else print *,"No samples found. Starting with default initialization." call this%samples%initialize (4, int_sizes_all, int_all, 1E-2_default) end if call this%restart () this%initialized = .true. call cpu_time (time) this%init_time = this%init_time + time end subroutine muli_initialize @ %def muli_initialize @ <>= procedure :: apply_initial_interaction => muli_apply_initial_interaction <>= subroutine muli_apply_initial_interaction (this, GeV2_s, & x1, x2, pdg_f1, pdg_f2, n1, n2) class(muli_t), intent(inout) :: this real(default), intent(in) :: Gev2_s, x1, x2 integer, intent(in):: pdg_f1, pdg_f2, n1, n2 real(default) :: rnd1, rnd2, time if (this%initialized) then call cpu_time (time) this%init_time = this%init_time - time print *, "muli_apply_initial_interaction:" print *, "gev2_s=", gev2_s print *, "x1=", x1 print *, "x2=", x2 print *, "pdg_f1=", pdg_f1 print *, "pdg_f2=", pdg_f2 print *, "n1=", n1 print *, "n2=", n2 call tao_random_number (this%tao_rnd, rnd1) call tao_random_number (this%tao_rnd, rnd2) call cpu_time (time) this%init_time = this%init_time + time call this%beam%apply_initial_interaction & (sqrt (gev2_s), x1, x2, pdg_f1, pdg_f2, n1, n2,& !!! This is a hack: We should give the pt scale of the initial !!! interaction. Unfortunately, we only know the invariant !!! mass shat. shat/2 is the upper bound of pt, so we !!! use it for now. sqrt(gev2_s) * x1 *x2 / 2D0, & rnd1, rnd2) this%initial_interaction_given = .true. else print *, & "muli_apply_initial_interaction: call muli_initialize first. STOP" stop end if end subroutine muli_apply_initial_interaction @ %def muli_apply_initial_interaction @ <>= procedure :: finalize => muli_finalize <>= subroutine muli_finalize (this) class(muli_t), intent(inout) :: this print *, "muli_finalize" nullify (this%node) call this%dsigma%finalize () call this%samples%finalize () call this%beam%finalize () end subroutine muli_finalize @ %def muli_finalize @ <>= procedure :: stop_trainer => muli_stop_trainer <>= subroutine muli_stop_trainer (this) class(muli_t), intent(inout) :: this print *, "muli_stop_trainer: DUMMY!" end subroutine muli_stop_trainer @ %def muli_stop_trainer @ <>= procedure :: reset_timer => muli_reset_timer <>= subroutine muli_reset_timer (this) class(muli_t), intent(inout) :: this this%init_time = 0D0 this%pt_time = 0D0 this%partons_time = 0D0 this%confirm_time = 0D0 end subroutine muli_reset_timer @ %def muli_reset_timer @ <>= procedure :: restart => muli_restart <>= subroutine muli_restart (this) class(muli_t), intent(inout) :: this call this%dsigma%get_rightmost (this%node) call this%beam%reset () ! print *, associated(this%node) ! nullify (this%node) this%finished = .false. this%process_id = -1 this%integrand_id = -1 this%momentum_fractions = [-1D0,-1D0,1D0] this%hyperbolic_fractions = [-1D0,-1D0,1D0] ! this%start_values%process_id = -1 ! this%start_values%integrand_id = -1 ! this%start_values%momentum_fractions = [-1D0,-1D0,1D0] ! this%start_values%hyperbolic_fractions = [-1D0,-1D0,1D0] this%start_integrals = & [0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0,0D0] end subroutine muli_restart @ %def muli_restart @ <>= procedure :: is_initialized => muli_is_initialized <>= elemental function muli_is_initialized (this) result (res) logical :: res class(muli_t), intent(in) :: this res = this%initialized end function muli_is_initialized @ %def muli_is_initialized @ <>= procedure :: is_initial_interaction_given => & muli_is_initial_interaction_given <>= elemental function muli_is_initial_interaction_given (this) result (res) logical :: res class(muli_t), intent(in) :: this res = this%initial_interaction_given end function muli_is_initial_interaction_given @ %def muli_is_initial_interaction_given @ <>= procedure :: is_finished => muli_is_finished <>= elemental function muli_is_finished (this) result (res) logical :: res class(muli_t), intent(in) :: this res = this%finished end function muli_is_finished @ %def muli_is_finished @ <>= procedure :: enable_remnant_pdf => muli_enable_remnant_pdf <>= subroutine muli_enable_remnant_pdf (this) class(muli_t), intent(inout) :: this this%modify_pdfs = .true. end subroutine muli_enable_remnant_pdf @ %def muli_enable_remnant_pdf @ <>= procedure :: disable_remnant_pdf => muli_disable_remnant_pdf <>= subroutine muli_disable_remnant_pdf (this) class(muli_t), intent(inout) :: this this%modify_pdfs = .false. end subroutine muli_disable_remnant_pdf @ %def muli_disable_remnant_pdf @ <>= procedure :: generate_gev2_pt2 => muli_generate_gev2_pt2 <>= subroutine muli_generate_gev2_pt2 (this, gev2_start_scale, gev2_new_scale) class(muli_t), intent(inout) :: this real(kind=default), intent(in) :: gev2_start_scale real(kind=default), intent(out) :: gev2_new_scale real(double) :: time call cpu_time (time) this%pt_time = this%pt_time - time call this%set_gev2_scale (gev2_start_scale) this%start_integrals = this%node%approx_integral (this%get_unit_scale ()) call this%generate_next_scale () gev2_new_scale = this%get_gev2_scale () call cpu_time (time) this%pt_time = this%pt_time + time end subroutine muli_generate_gev2_pt2 @ %def muli_generate_gev2_pt2 @ <>= procedure :: generate_partons => muli_generate_partons <>= subroutine muli_generate_partons (this, n1, n2, x_proton_1, x_proton_2, & pdg_f1, pdg_f2, pdg_f3, pdg_f4) class(muli_t), intent(inout) :: this integer, intent(in) :: n1, n2 real(kind=default), intent(out) :: x_proton_1, x_proton_2 integer, intent(out) :: pdg_f1, pdg_f2, pdg_f3, pdg_f4 integer, dimension(4) :: pdg_f real(double) :: time ! print *, "muli_generate_partons: n1=", n1, " n2=", n2 this%parton_ids(1) = n1 this%parton_ids(2) = n2 call cpu_time (time) this%partons_time = this%partons_time - time this%mean = this%node%approx_value_n (this%get_unit_scale(), & this%integrand_id) call this%samples%mcgenerate_hit (this%get_unit2_scale(), & this%mean, this%integrand_id, this%tao_rnd, this%process_id, & this%momentum_fractions) ! print *,"muli_generate_partons", this%momentum_fractions call this%generate_flow () if (this%modify_pdfs) then call cpu_time (time) this%partons_time = this%partons_time + time this%confirm_time = this%confirm_time - time call this%beam%apply_interaction (this) call cpu_time (time) this%confirm_time = this%confirm_time + time this%partons_time = this%partons_time - time end if x_proton_1 = this%momentum_fractions(1) x_proton_2 = this%momentum_fractions(2) pdg_f = this%get_pdg_flavors () pdg_f1 = pdg_f(1) pdg_f2 = pdg_f(2) pdg_f3 = pdg_f(3) pdg_f4 = pdg_f(4) call cpu_time (time) this%partons_time = this%partons_time - time call qcd_2_2_print_to_unit (this, output_unit, 100_dik, 100_dik, 100_dik) end subroutine muli_generate_partons @ %def muli_generate_partons @ <>= procedure :: generate_flow => muli_generate_flow <>= subroutine muli_generate_flow(this) class(muli_t), intent(inout)::this integer::rnd integer::m,n logical, dimension(3)::t integer, dimension(4)::tmp_flow, tmp_array ! we initialize with zeros. a i_zero means no line ends here. this%flow=[0,0,0,0] ! we randomly pick a color flow call tao_random_number(this%tao_rnd,rnd) ! the third position of muli_flow_stats is the sum of all flow wheights of stratum diagram_kind. ! so we generate a random number 0 <= m < sum(weights) m=modulo(rnd,muli_flow_stats(3,this%get_diagram_color_kind())) ! lets visit all color flows of stratum diagram_kind. the first and second position of muli_flow_stats ! tells us the index of the first and the last valid color flow. do n=muli_flow_stats(1,this%get_diagram_color_kind()),muli_flow_stats(2,this%get_diagram_color_kind()) ! now we remove the weight of flow n from our random number. m=m-muli_flows(0,n) ! this is how we pick a flow. if (m<0) then ! the actual flow this%flow=muli_flows(1:4,n) exit end if end do ! the diagram kind contains a primitive diagram and all diagramms which can be deriven by ! (1) global charge conjugation ! (2) permutation of the initial state particles ! (3) permutation of the final state particles ! lets see, what transformations we have got in our actual interaction. tmp_array = this%get_lha_flavors () t = muli_get_state_transformations (this%get_diagram_color_kind (), & tmp_array) ! this%get_lha_flavors ()) ! now we have to apply these transformations to our flow. ! (1) means: swap beginning and end of a line. flow is a permutation that maps ! ends to their beginnings, so we apply flow to itself: !!$ print *,"(0)",this%flow if (t(1)) then tmp_flow=this%flow this%flow=[0,0,0,0] do n=1,4 if (tmp_flow(n)>0)this%flow(tmp_flow(n))=n end do !!$ print *,"(1)",this%flow end if if (t(2)) then ! we swap the particles 1 and 2 tmp_flow(1)=this%flow(2) tmp_flow(2)=this%flow(1) tmp_flow(3:4)=this%flow(3:4) !!$ print *,"(2)",tmp_flow ! we swap the beginnings assigned to particle 1 and 2 where(tmp_flow==1) this%flow=2 elsewhere(tmp_flow==2) this%flow=1 elsewhere this%flow=tmp_flow end where !!$ print *,"(2)",this%flow end if if (t(3)) then ! we swap the particles 3 and 4 tmp_flow(1:2)=this%flow(1:2) tmp_flow(3)=this%flow(4) tmp_flow(4)=this%flow(3) !!$ print *,"(3)",tmp_flow ! we swap the beginnings assigned to particle 3 and 4 where(tmp_flow==3) this%flow=4 elsewhere(tmp_flow==4) this%flow=3 elsewhere this%flow=tmp_flow end where !!$ print *,"(3)",this%flow end if end subroutine muli_generate_flow @ %def muli_generate_flow @ <>= procedure :: replace_parton => muli_replace_parton <>= subroutine muli_replace_parton & (this, proton_id, old_id, new_id, pdg_f, x_proton, gev_scale) class(muli_t), intent(inout) :: this integer, intent(in) :: proton_id, old_id, new_id, pdg_f real(kind=default), intent(in) :: x_proton, gev_scale ! print *, "muli_replace_parton(", proton_id, old_id, new_id, & ! pdg_f, x_proton, gev_scale, ")" if (proton_id==1 .or. proton_id==2) then call this%beam%replace_parton & (proton_id, old_id, new_id, pdg_f, x_proton, gev_scale) else print *, "muli_replace_parton: proton_id must be 1 or 2, but ", & proton_id, " was given." stop end if end subroutine muli_replace_parton @ %def muli_replace_parton @ <>= procedure :: get_parton_pdf => muli_get_parton_pdf @ <>= function muli_get_parton_pdf & (this, x_proton, gev2_scale, n, pdg_f) result (pdf) real(default) :: pdf class(muli_t), intent(in) :: this real(default), intent(in) :: x_proton, gev2_scale integer, intent(in) :: n, pdg_f call this%beam%parton_pdf (x_proton, gev2_scale, n, pdg_f, pdf) end function muli_get_parton_pdf @ %def muli_get_parton_pdf @ <>= procedure :: get_momentum_pdf => muli_get_momentum_pdf @ <>= function muli_get_momentum_pdf & (this, x_proton, gev2_scale, n, pdg_f) result (pdf) real(default) :: pdf class(muli_t), intent(in) :: this real(default), intent(in) :: x_proton, gev2_scale integer, intent(in) :: n, pdg_f call this%beam%momentum_pdf (x_proton, gev2_scale, n, pdg_f, pdf) end function muli_get_momentum_pdf @ %def muli_get_momentum_pdf @ <>= procedure :: print_timer => muli_print_timer <>= subroutine muli_print_timer(this) class(muli_t), intent(in) :: this print ("(1x,A,E20.10)"), "Init time: ", this%init_time print ("(1x,A,E20.10)"), "PT gen time: ", this%pt_time print ("(1x,A,E20.10)"), "Partons time: ", this%partons_time print ("(1x,A,E20.10)"), "Confirm time: ", this%confirm_time print ("(1x,A,E20.10)"), "Overall time: ", & this%init_time + this%pt_time + this%partons_time + this%confirm_time end subroutine muli_print_timer @ %def muli_print_timer @ <>= procedure :: generate_samples => muli_generate_samples <>= subroutine muli_generate_samples & (this, n_total, n_print, integrand_kind, muli_dir, analyse) class(muli_t), intent(inout) :: this integer(dik), intent(in) :: n_total, n_print integer, intent(in) :: integrand_kind character(*), intent(in) :: muli_dir logical, intent(in) :: analyse integer(dik) :: n_inner class(muli_trapezium_node_class_t), pointer :: start_node => null() class(muli_trapezium_node_class_t), pointer, save :: s_node => null() class(muli_trapezium_node_class_t), pointer, save :: node => null() character(2) :: prefix integer, save :: t_slice, t_region, t_proc, t_subproc, t_max_n = 0 integer(dik) :: n_t, n_p, n_m integer :: n, m, u, unit = 0 integer(dik) :: n_tries = 0 integer(dik) :: n_hits = 0 integer(dik) :: n_over = 0 integer(dik) :: n_miss = 0 real(default), save, dimension(3) :: cart_hit integer, save, dimension(4) :: t_i_rnd ! integer, save, dimension(5) :: r_n_proc real(default), dimension(16) :: d_rnd real(default), save :: t_area, t_dddsigma, t_rnd, t_weight, t_arg real(default) :: mean = 0D0 real(default) :: time = 0D0 real(default) :: timepa = 0D0 real(default) :: timept = 0D0 real(default) :: timet = 0D0 real(default) :: pts, s_pts = 1D0 real(default) :: pts2 = 1D0 real(default) :: rnd logical :: running character(3) :: num integer :: success = -1 integer :: chain_length = 0 integer :: int_kind integer :: process_id real(double), dimension(0:16) :: integral call this%print_parents () n_tries = one n_inner = n_total / n_print n_t = i_zero PRINT: do while (n_t < n_total) call cpu_time (time) timet = - time n_p = i_zero INNER: do while (n_p < n_print) chain_length = 0 ! print *,"new chain" call this%restart () this%integrand_id = integrand_kind call cpu_time (time) timept = timept - time call this%generate_next_scale (integrand_kind) call cpu_time (time) timept = timept + time CHAIN: do while (.not. this%is_finished ()) chain_length = chain_length + 1 n_p = n_p + 1 call this%confirm () call cpu_time (time) timepa = timepa - time ! print *, this%get_unit2_scale () call this%samples%mcgenerate_hit (this%get_unit2_scale(), & this%mean, this%integrand_id, this%tao_rnd, this%process_id, & this%momentum_fractions) call cpu_time (time) timepa = timepa + time timept = timept - time call this%generate_next_scale (integrand_kind) call cpu_time (time) timept = timept + time end do CHAIN ! print *, "chain length = ", chain_length end do INNER n_t = n_t + n_p call this%samples%sum_up () call cpu_time (time) timet = timet + time print *, n_t, "/", n_total print *, "time: ", timet print *, "pt time: ", timept print *, "pa time: ", timepa print *, this%samples%n_tries_sum, this%samples%n_hits_sum, & this%samples%n_over_sum if (this%samples%n_hits_sum > 0) then print *, (this%samples%n_hits_sum * 10000) / & this%samples%n_tries_sum, (this%samples%n_over_sum * 10000) / & this%samples%n_hits_sum else print *, "no hits" end if ! print ('(7(I11," "),5(E14.7," "))'), n_p, n_print, n_tries, & ! n_hits,n_over, int((n_hits*1D3)/n_tries), & ! int((n_over*1D6)/n_tries), n_hits/real(n_over), time1, time2, & ! time3, this%samples%int_kinds(integrand_kind)%overall_boost end do print call integer_with_leading_zeros (integrand_kind, 2, prefix) if (analyse) then call this%samples%int_kinds(integrand_kind)%analyse & (muli_dir, prefix//"_") call this%samples%int_kinds(integrand_kind)%serialize & ("sample_int_kind_"//prefix, & muli_dir//"/sample_int_kind/"//prefix//".xml") end if call this%samples%int_kinds(integrand_kind)%serialize & ("sample_int_kind_"//prefix, & muli_dir//"/sample_int_kind/"//prefix//".xml") end subroutine muli_generate_samples @ %def muli_generate_samples @ <>= procedure :: fake_interaction => muli_fake_interaction <>= subroutine muli_fake_interaction (this, GeV2_scale, x1, x2, & process_id, integrand_id, n1, n2, flow) class(muli_t), intent(inout) :: this real(default), intent(in) :: Gev2_scale, x1, x2 integer, intent(in) :: process_id, integrand_id, n1, n2 integer, dimension(4), intent(in), optional :: flow call this%set_gev2_scale (Gev2_scale) this%process_id = process_id this%integrand_id = integrand_id this%parton_ids = [n1, n2] if (present (flow)) then this%flow = flow else this%flow = [0,0,0,0] end if this%momentum_fractions = [x1, x2, this%get_unit2_scale()] call this%beam%apply_interaction (this) call this%beam%print_all () end subroutine muli_fake_interaction @ %def muli_fake_interaction @ <>= procedure :: generate_next_scale => muli_generate_next_scale <>= subroutine muli_generate_next_scale (this, integrand_kind) class(muli_t), intent(inout) :: this integer, intent(in), optional :: integrand_kind real(default) :: pts, tmp_pts, rnd integer :: tmp_int_kind class(muli_trapezium_node_class_t), pointer :: tmp_node pts = - one if (present (integrand_kind)) then call tao_random_number (this%tao_rnd, rnd) call generate_single_pts (integrand_kind, & this%start_integrals(integrand_kind), & this%beam%get_pdf_int_weights & (double_pdf_kinds (1:2,integrand_kind)), rnd, this%dsigma, & pts, this%node) else do tmp_int_kind = 1, 16 call tao_random_number (this%tao_rnd, rnd) call generate_single_pts (tmp_int_kind, & this%start_integrals(tmp_int_kind), & this%beam%get_pdf_int_weights & (double_pdf_kinds(1:2,tmp_int_kind)), rnd, & this%dsigma, tmp_pts, tmp_node) if (tmp_pts > pts) then pts = tmp_pts this%integrand_id = tmp_int_kind this%node => tmp_node end if end do end if if (pts > 0) then call this%set_unit_scale (pts) else this%finished = .true. end if ! print *, this%finished, this%integrand_id contains subroutine generate_single_pts & (int_kind, start_int, weight, rnd, int_tree, pts, node) integer, intent(in) :: int_kind real(default), intent(in) :: start_int, weight, rnd type(muli_trapezium_tree_t), intent(in) :: int_tree real(default), intent(out) :: pts class(muli_trapezium_node_class_t),pointer, intent(out) :: node real(default) :: arg ! print *, int_kind, start_int, weight, rnd if (weight > 0D0) then arg = start_int - log(rnd) / weight call int_tree%find_decreasing (arg, int_kind, node) if (node%get_l_integral(int_kind) > arg) then pts = node%approx_position_by_integral (int_kind, arg) else pts = -1D0 end if else pts = -1D0 end if end subroutine generate_single_pts end subroutine muli_generate_next_scale @ %def muli_generate_next_scale @ <>= procedure :: confirm => muli_confirm <>= subroutine muli_confirm (this) class(muli_t), intent(inout) :: this this%mean = this%node%approx_value_n(this%get_unit_scale (), & this%integrand_id) this%start_integrals = this%node%approx_integral (this%get_unit_scale ()) end subroutine muli_confirm @ %def muli_confirm @ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% <<[[muli_cross_sections.f90]]>>= ! This is a dummy for muli_cross_sections_module module muli_cross_sections_module end module muli_cross_sections_module @ <<[[muli_sampling.f90]]>>= ! This is a dummy for muli_sampling_module module muli_sampling_module end module muli_sampling_module @ @