In the multisystem framework, it is important to detail how the various components are initialized.
The top level system is created in main/run.F90 by calling the multisystem_basic_t constructor
which itself calls multisystem_basic_init() and multisystem_init().
Definition of multisystem_basic_init()
recursivesubroutinemultisystem_init(this,namespace,factory)class(multisystem_t),intent(inout)::thistype(namespace_t),intent(in)::namespace!< namespace for the multisystem container
class(system_factory_abst_t),intent(in)::factory!< system factory to instantiate the systems in the container
integer::isys,system_type,iccharacter(len=128)::system_nametype(block_t)::blkPUSH_SUB(multisystem_init)this%namespace=namespaceif(parse_block(this%namespace,factory%block_name(),blk)==0)thendoisys=1,parse_block_n(blk)! Parse system name and type
callparse_block_string(blk,isys-1,0,system_name)if(len_trim(system_name)==0)thencallmessages_input_error(this%namespace,factory%block_name(),'All systems must have a name')endifdoic=1,len(parser_varname_excluded_characters)if(index(trim(system_name),parser_varname_excluded_characters(ic:ic))/=0)thencallmessages_input_error(this%namespace,factory%block_name(),&'Illegal character "'//parser_varname_excluded_characters(ic:ic)//'" in system name',row=isys-1,column=0)endifenddocallparse_block_integer(blk,isys-1,1,system_type)callmultisystem_create_system(this,system_name,system_type,isys,factory)enddocallparse_block_end(blk)elsemessage(1)="Input error while reading block "//trim(this%namespace%get())//"."//trim(factory%block_name())callmessages_fatal(1,namespace=this%namespace)endifPOP_SUB(multisystem_init)endsubroutinemultisystem_init
Finally, multisystem_create_system() loops over the subsystems and calls the system factory to create each of them.
Definition of multisystem_create_system()
recursivesubroutinemultisystem_create_system(this,system_name,system_type,isys,factory)class(multisystem_t),intent(inout)::thischaracter(len=128),intent(in)::system_name!< name of the system to be created
integer,intent(in)::system_type!< system type as defined in system_factory_oct_m
integer,intent(in)::isys!< system counter
class(system_factory_abst_t),intent(in)::factory!< system factory
type(system_iterator_t)::iterclass(system_t),pointer::sys,otherPUSH_SUB(multisystem_create_system)! Create folder to store system files.
! Needs to be done before creating the system as this in turn might create subfolders.
callio_mkdir(system_name,namespace=this%namespace)! Create system
sys=>factory%create(this%namespace,system_name,system_type)if(.not.associated(sys))thencallmessages_input_error(this%namespace,factory%block_name(),'Unknown system type.')endif! Check that the system is unique
calliter%start(this%list)dowhile(iter%has_next())other=>iter%get_next()if(sys%namespace==other%namespace)thencallmessages_input_error(this%namespace,factory%block_name(),'Duplicated system in multi-system',&row=isys-1,column=0)endifenddo! Add system to list of systems
callthis%list%add(sys)POP_SUB(multisystem_create_system)endsubroutinemultisystem_create_system
Initializing the propagators
The propagators for the system(s) are initialized in time_dependent_run_multisystem() by a call to systems%init_propagators().
As time_dependent_run_multisystem() is called with systems being of type multisystem_basic_t, this translates to a call to
multisystem_init_propagator().
Definition of multisystem_init_propagator()
This routine parses the input for the propagator type, and then creates a propagator of the given type using the respective constructor.
Then, multisystem_init_propagator() loops over the subsystems, and calls system%propagator_init() for each.
In general (i.e. if the function is not overloaded by a derived class), systems use the function system_propagator_init():
Definition of system_init_propagator()
system_propagator_init() parses the input file, looking for the variable TDSystemPropagator. Here it is important to remember
the order in which the parser treats namespaces.
the top-level multisystem will internally be called . and we have in total three namespaces:
.
./System_A
./System_B
The system%propagator_init() routines for System_A and System_B will first look whether TDSystemPropagator is defined in their respective namespace. If this is not the case, they will look for the variable in the parent namespace, which here is the global namespace ..
The code does allow to specify different propagators for the multisystem, and the subsystems. While this might work if the subsystems do not interact, it will most likely fail for interacting systems. Therefore, it is highly recommended not to specify the propagators for the subsystems separately, unless one knows exactly what one is doing.