Timer unit: 1e-06 s

Total time: 12.4592 s
File: /pfs/work/g2pbloch/jintrac/python/jintrac_imas_driver.py
Function: jetto_wrapper at line 304

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   304                                           @profile
   305                                           def jetto_wrapper(noprocessors, in_imas_control, in_ids_bundle_updated, in_ids_bundle_work, in_ids_bundle_prev):
   306                                               """Wrapper for Jetto Fortran actor."""
   307                                           
   308         1          9.7      9.7      0.0      if verbose: print("JINTRAC_IMAS_DRIVER: jetto wrapper called...", mpicfg.myrank)
   309                                           
   310         1          0.6      0.6      0.0      in_prof = in_ids_bundle_work['core_profiles']
   311         1          0.6      0.6      0.0      in_src = in_ids_bundle_work['core_sources']
   312         1          0.7      0.7      0.0      in_trans = in_ids_bundle_work['core_transport']
   313         1          0.4      0.4      0.0      in_equil = in_ids_bundle_work['equilibrium']
   314         1          0.6      0.6      0.0      in_nbi = in_ids_bundle_work['nbi']
   315         1          0.4      0.4      0.0      in_pel = in_ids_bundle_work['pellets']
   316         1          0.6      0.6      0.0      in_pulse = in_ids_bundle_work['pulse_schedule']
   317         1          0.4      0.4      0.0      in_contr = in_ids_bundle_work['controllers']
   318         1          0.3      0.3      0.0      in_summ = in_ids_bundle_work['summary']
   319         1          0.4      0.4      0.0      in_num = in_ids_bundle_updated['transport_solver_numerics']
   320         1          0.2      0.2      0.0      in_work = in_ids_bundle_updated['workflow']
   321                                           
   322         1          5.6      5.6      0.0      if verbose: print("JINTRAC_IMAS_DRIVER: Calling jetto_actor...", mpicfg.myrank)
   323         1          1.3      1.3      0.0      out_prof, out_src, out_trans, out_equil, out_summ, out_num, out_work \
   324         1    8958798.8 8958798.8     71.9                = jetto(in_prof, in_src, in_trans, in_equil, in_nbi,
   325         1          0.2      0.2      0.0                        in_pel, in_pulse, in_contr, in_summ, in_num, in_work)
   326         1         29.5     29.5      0.0      if verbose: print("JINTRAC_IMAS_DRIVER: ...jetto_actor done!", mpicfg.myrank)
   327                                           
   328         1          1.9      1.9      0.0      if mpicfg.init and mpicfg.size > 1:
   329                                                   out_prof = mpicfg.comm.bcast(out_prof, root=0)
   330                                                   out_src = mpicfg.comm.bcast(out_src, root=0)
   331                                                   out_trans = mpicfg.comm.bcast(out_trans, root=0)
   332                                                   out_equil = mpicfg.comm.bcast(out_equil, root=0)
   333                                                   out_summ = mpicfg.comm.bcast(out_summ, root=0)
   334                                                   out_num = mpicfg.comm.bcast(out_num, root=0)
   335                                                   out_work = mpicfg.comm.bcast(out_work, root=0)
   336                                           
   337         8         12.4      1.5      0.0      for ii in range(len(out_work.time_loop.component)):
   338         7          9.1      1.3      0.0          if out_work.time_loop.component[ii].name == 'jetto':
   339         1          0.3      0.3      0.0              jetto_index = ii
   340         1          7.7      7.7      0.0      time = out_work.time_loop.workflow_cycle[0].component[jetto_index].control_float[0]
   341                                           
   342                                               # time is not correctly transferred back from JETTO via out_work.time[0]
   343                                               # even though out_work.time[0] still has the correct value at the very end
   344                                               # of the JETTO actor routine jetto_actor.f90 ; the time for a time slice
   345                                               # does not seem to become passed back for any IDS structure; to circumvent
   346                                               # this bug, the time is written also to
   347                                               # time_loop.workflow_cycle[0].component[jetto_index].control_float[0] in
   348                                               # JETTO and re-set in out_work.time[0] with this quantity
   349                                           
   350         1          1.8      1.8      0.0      out_work.ids_properties.homogeneous_time = imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS
   351         1          2.3      2.3      0.0      out_work.time[0] = time
   352                                           
   353         1          3.3      3.3      0.0      timereached = out_work.time[0] + out_work.time_loop.workflow_cycle[0].component[jetto_index].time_interval
   354         1          1.6      1.6      0.0      if out_prof.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   355         1          0.9      0.9      0.0          out_prof.time[0] = timereached
   356         1          1.6      1.6      0.0      if out_src.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   357         1          0.8      0.8      0.0          out_src.time[0] = timereached
   358         1          1.5      1.5      0.0      if out_trans.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   359         1          0.7      0.7      0.0          out_trans.time[0] = timereached
   360         1          1.4      1.4      0.0      if out_equil.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   361         1          0.7      0.7      0.0          out_equil.time[0] = timereached
   362         1          1.0      1.0      0.0      if out_summ.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   363         1          0.6      0.6      0.0          out_summ.time[0] = timereached
   364         1          0.7      0.7      0.0      if out_num.ids_properties.homogeneous_time == imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS:
   365         1          0.6      0.6      0.0          out_num.time[0] = timereached
   366                                           
   367         1    3459717.4 3459717.4     27.8      out_ids_bundle = bundle_copy(in_ids_bundle_work)
   368         1        357.0    357.0      0.0      out_ids_bundle['core_profiles'] = out_prof
   369         1        742.6    742.6      0.0      out_ids_bundle['core_sources'] = out_src
   370         1          7.6      7.6      0.0      out_ids_bundle['core_transport'] = out_trans
   371         1      38898.2  38898.2      0.3      out_ids_bundle['equilibrium'] = out_equil
   372         1        533.7    533.7      0.0      out_ids_bundle['summary'] = out_summ
   373         1         18.8     18.8      0.0      out_ids_bundle['transport_solver_numerics'] = out_num
   374         1         25.6     25.6      0.0      out_ids_bundle['workflow'] = out_work
   375                                           
   376         1          0.4      0.4      0.0      return out_ids_bundle

Total time: 155.743 s
File: /pfs/work/g2pbloch/jintrac/python/jintrac_imas_driver.py
Function: jintrac_imas_driver at line 735

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   735                                           @profile
   736                                           def jintrac_imas_driver(params, mpi='no'):
   737                                           
   738                                               """
   739                                               JINTRAC-IMAS generic workflow driver.
   740                                               :param dict params: Data loaded and converted by PyYAML from the jintrac_imas_config.yaml file.
   741                                               """
   742                                           
   743                                               global mpi_root
   744                                               global verbose
   745                                           
   746         1          2.8      2.8      0.0      mpi_root = True
   747         1          0.4      0.4      0.0      verbose = True  #  'master' switch
   748                                           
   749         1          0.4      0.4      0.0      if debug: print("JINTRAC_IMAS_DRIVER: Python Driver started")
   750                                           
   751                                               # Workflow configuration parameters
   752                                           
   753         1          0.6      0.6      0.0      user_in = params["Input IDS user"]
   754         1          0.4      0.4      0.0      machine_in = params["Input IDS machine"]
   755         1          0.9      0.9      0.0      shot_in = params["Input IDS shot"]
   756         1          0.7      0.7      0.0      run_in = params["Input IDS run"]
   757         1          0.4      0.4      0.0      user_out = params["Output IDS user"]
   758         1          0.3      0.3      0.0      machine_out = params["Output IDS machine"]
   759         1          0.3      0.3      0.0      shot_out = params["Output IDS shot"]
   760         1          0.5      0.5      0.0      run_out = params["Output IDS run"]
   761         1         15.1     15.1      0.0      user_tmp = os.environ['HOME']+'/public/tempdb'
   762                                           
   763         1          0.6      0.6      0.0      tstart = params["Start time"]
   764         1          0.5      0.5      0.0      tend = params["End time"]
   765         1          0.8      0.8      0.0      noprocessors = params["Number of processors for parallelised actors"]
   766         1          0.5      0.5      0.0      lreplace = params["Replace existing IDS"]
   767         1          0.5      0.5      0.0      components = params["Active components"]
   768                                           
   769         1          0.4      0.4      0.0      if debug: print("JINTRAC_IMAS_DRIVER: Workflow configuration has been read")
   770                                           
   771                                               # To wrap into jintrac_mpi_init    
   772         1          0.5      0.5      0.0      if mpi == 'yes':
   773         1          0.2      0.2      0.0          if debug: print("JINTRAC_IMAS_DRIVER: MPI starting...")
   774         1     173541.6 173541.6      0.1          from mpi4py import MPI  # This import performs an implicit MPI_INIT
   775         1          1.0      1.0      0.0          if debug: print("JINTRAC_IMAS_DRIVER: MPI started okay")
   776         1          2.5      2.5      0.0          mpicfg.init = True
   777         1          2.8      2.8      0.0          mpicfg.comm = MPI.COMM_WORLD
   778         1          7.4      7.4      0.0          mpicfg.size = mpicfg.comm.Get_size()
   779         1          4.1      4.1      0.0          mpicfg.rank = mpicfg.comm.Get_rank()
   780         1          5.7      5.7      0.0          mpicfg.myrank = "(MPI process "+str(mpicfg.rank)+")"
   781         1          1.7      1.7      0.0          mpi_root = (mpicfg.rank == 0)
   782         1          1.0      1.0      0.0          verbose = verbose and mpi_root
   783         1          0.7      0.7      0.0          if mpicfg.size == 1:
   784         1         22.1     22.1      0.0              if verbose: print("JINTRAC_IMAS_DRIVER: Parallel MPI execution (1 process)")
   785                                                   else:
   786                                                       if verbose: print("JINTRAC_IMAS_DRIVER: Parallel MPI execution ({0} processes)".format(mpicfg.size))
   787                                               else:
   788                                                   if verbose: print("JINTRAC_IMAS_DRIVER: Serial execution (no MPI)")
   789                                                   noprocessors = 1
   790                                           
   791         1          1.0      1.0      0.0      if verbose:
   792         1          6.7      6.7      0.0          print("")
   793         1          2.7      2.7      0.0          print("JINTRAC_IMAS_DRIVER: Workflow configuration parameters")
   794         1         13.7     13.7      0.0          print("JINTRAC_IMAS_DRIVER:      tstart         =", tstart)
   795         1          5.8      5.8      0.0          print("JINTRAC_IMAS_DRIVER:      tend           =", tend)
   796         1          7.0      7.0      0.0          print("JINTRAC_IMAS_DRIVER:      shot,run(in)   =", shot_in, run_in)
   797         1          5.7      5.7      0.0          print("JINTRAC_IMAS_DRIVER:      machine(in)    =", machine_in)
   798         1          4.8      4.8      0.0          print("JINTRAC_IMAS_DRIVER:      user(in)       =", user_in)
   799         1          7.9      7.9      0.0          print("JINTRAC_IMAS_DRIVER:      shot,run(out)  =", shot_out, run_out)
   800         1          4.2      4.2      0.0          print("JINTRAC_IMAS_DRIVER:      machine(out)   =", machine_out)
   801         1          6.0      6.0      0.0          print("JINTRAC_IMAS_DRIVER:      user(out)      =", user_out)
   802         1          4.5      4.5      0.0          print("JINTRAC_IMAS_DRIVER:      no. processors =", noprocessors)
   803         1          7.6      7.6      0.0          print("JINTRAC_IMAS_DRIVER:      replace IDS    =", lreplace)
   804                                           
   805         1         11.2     11.2      0.0          print("\nJINTRAC_IMAS_DRIVER: Active Components:", components)
   806                                           
   807         1          0.4      0.4      0.0      comment_file = 'ids_comment'
   808                                           
   809         1         39.9     39.9      0.0      imas_control = WorkflowControl()
   810         1          4.1      4.1      0.0      num_components = imas_control.get_num_components()
   811                                           
   812                                               # Build list of components to be used
   813         1          0.7      0.7      0.0      component_list = []   # component_list is identical to components but with upper case enforcement
   814         3          1.4      0.5      0.0      for item in components:
   815         3          4.6      1.5      0.0          component_list.append(item.upper())
   816                                           
   817                                               # Reference Python actors as global functions
   818         1          1.0      1.0      0.0      list_of_jintrac_actors = ['edge2d', 'jetto', 'coconut']
   819         1          6.4      6.4      0.0      for name in [name for name in list_of_jintrac_actors if name.upper() in component_list]:
   820         1          0.7      0.7      0.0          if debug: print("JINTRAC_IMAS_DRIVER: Trying to import "+name+" actor...")
   821         1          0.7      0.7      0.0          try:
   822         1      66338.8  66338.8      0.0              ierr = import_actor(name)
   823         1          0.7      0.7      0.0              if ierr != 0:
   824                                                           error_exit("JINTRAC_IMAS_DRIVER: Failed to import JINTRAC Python actor "+name.upper())
   825                                                   except:
   826                                                       error_exit("JINTRAC_IMAS_DRIVER: Reference to JINTRAC Python actor "+name.upper()+" not found!")
   827         1          0.6      0.6      0.0          if debug: print("JINTRAC_IMAS_DRIVER: Successful import of "+name+" actor")
   828                                           
   829         1          0.9      0.9      0.0      if 'HCD' in component_list:
   830                                                   try:
   831                                                       globals()['hcd_jintrac_interface'] = getattr(import_module('hcd_jintrac_interface'), 'hcd_jintrac_interface')
   832                                                       globals()['hcd_jintrac_interface_init'] = getattr(import_module('hcd_jintrac_interface'), 'hcd_jintrac_interface_init')
   833                                                   except:
   834                                                       error_exit("JINTRAC_IMAS_DRIVER: Reference to HCD JINTRAC plugin interface routines not found!")
   835                                           
   836                                               # Make list of input and output IDS objects
   837                                               # from combined lists of required IDS structures for each workflow component
   838         1          0.2      0.2      0.0      ids_list = []
   839         3          0.9      0.3      0.0      for elem in component_list:
   840         3          6.3      2.1      0.0          ids_list.extend(imas_control.get_ids_list_required(elem))
   841         1          4.1      4.1      0.0      ids_list = list(set(ids_list))  # Remove duplicates
   842                                           
   843                                               # Determine IMAS backend -> wrap into a function
   844         1         12.8     12.8      0.0      backendtype = os.environ['JINTRAC_IMAS_BACKEND']
   845         1          0.6      0.6      0.0      if backendtype == None:
   846                                                   if mpi_root: print("JINTRAC_IMAS_DRIVER: No IMAS IDS backend ($JINTRAC_IMAS_BACKEND) selected, using MDSPLUS.")
   847                                                   backendtype = 'MDSPLUS'
   848         1          0.7      0.7      0.0      if backendtype == 'MDSPLUS':
   849                                                   # previous IDS data access scheme in use with MDSPLUS backend selection
   850                                                   # for backwards compatibility while IMAS versions < 3.35 are still in use on some clusters
   851         1          1.6      1.6      0.0          backend = imas.imasdef.MDSPLUS_BACKEND
   852                                               elif backendtype == 'HDF5':
   853                                                   backend = imas.imasdef.HDF5_BACKEND
   854                                               else:
   855                                                   error_exit("JINTRAC_IMAS_DRIVER: Selected IMAS IDS backend ($JINTRAC_IMAS_BACKEND="
   856                                                              +backendtype+") not supported!")
   857                                           
   858                                               # Open/create output local datafile -> Should be handled by the AL
   859         1          3.5      3.5      0.0      version = os.environ['IMAS_VERSION'][:1]
   860         1          0.8      0.8      0.0      if mpi_root:
   861         1         12.7     12.7      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Creating local database "+user_out+'/'+machine_out+'/'+version)
   862         1          0.5      0.5      0.0          if user_out[0] != '/':
   863                                                       user_out_root = os.environ['HOME']+'/public/imasdb'
   864                                                   else:
   865         1          0.2      0.2      0.0              user_out_root = user_out
   866         1         13.1     13.1      0.0          if not os.path.exists(user_out_root+'/'+machine_out+'/'+version):
   867                                                       os.makedirs(user_out_root+'/'+machine_out+'/'+version)
   868         1          0.3      0.3      0.0          if backendtype == 'MDSPLUS':
   869         1          0.4      0.4      0.0              if user_out[0] != '/':
   870                                                           os.popen("imasdb "+machine_out).read()
   871                                                       else:
   872         1      90376.8  90376.8      0.1                  os.popen("imasdb "+user_out_root+'/'+machine_out+'/'+version).read()
   873                                                   elif backendtype == 'HDF5':
   874                                                       hdf5_outdir = user_out_root+'/'+machine_out+'/'+version+'/'+str(shot_out)
   875                                                       if not os.path.exists(hdf5_outdir):
   876                                                           os.mkdir(hdf5_outdir)
   877                                           
   878         1          2.9      2.9      0.0      if mpicfg.init and mpicfg.size > 1: mpicfg.comm.barrier()
   879                                           
   880                                               # Setup output IDS -> move into IDSOUT_init wrapper
   881         1          0.9      0.9      0.0      idx_out = -9999
   882         1          1.6      1.6      0.0      if 'IDSOUT' in component_list:
   883         1         14.8     14.8      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Initialising output IDS...")
   884         1         37.6     37.6      0.0          DBentry.idsout = imas.DBEntry(backend, machine_out, shot_out, run_out, user_name=user_out)
   885                                           
   886         1          0.8      0.8      0.0          create_ids = lreplace
   887         1          0.9      0.9      0.0          if create_ids == False:
   888                                                       if verbose: print("JINTRAC_IMAS_DRIVER: ...Opening output IDS environment...", user_out, machine_out, version)
   889                                                       status, idx_out = DBentry.idsout.open()  # idx_out points to output IDS file index
   890                                                       if status != 0:
   891                                                           if verbose: print("JINTRAC_IMAS_DRIVER: IDS output file does not exist; creating new file instead...")
   892                                                           create_ids = True
   893                                           
   894         1          0.6      0.6      0.0          if create_ids:
   895         1          0.9      0.9      0.0              if mpi_root:
   896         1         19.0     19.0      0.0                  if verbose: print("JINTRAC_IMAS_DRIVER: ...Creating output IDS environment...", user_out, machine_out, version)
   897         1    1638364.1 1638364.1      1.1                  status, idx_out = DBentry.idsout.create()  # idx_out points to output IDS file index
   898         1          9.9      9.9      0.0                  if status != 0:
   899                                                               error_exit("IDS output file creation has failed... Aborting with status = "+str(status))
   900                                           
   901         1         21.6     21.6      0.0          if mpicfg.init and mpicfg.size > 1:
   902                                                       idx_out = mpicfg.comm.bcast(idx_out, root=0)
   903                                           
   904                                           
   905                                               # Open input datafile; shot_in=0 indicates no IDS inputs -> move into IDSIN_init wrapper
   906         1      27199.6  27199.6      0.0      ids_in = imas.ids(0, 0, 0, 0)
   907         1          0.5      0.5      0.0      idx_in = -9999
   908         1          1.8      1.8      0.0      if shot_in == 0 or not mpi_root:
   909                                                   if 'IDSOUT' in component_list:
   910                                                       idx_in = idx_out
   911                                                       if DBentry.API == 'NEW':
   912                                                           DBentry.idsin = DBentry.idsout
   913                                                   else:
   914                                                       # Set up dummy input IDS file (required for input slice initialisation)
   915                                                       if DBentry.API == 'NEW':
   916                                                           DBentry.idsin = imas.DBEntry(backend, '', 0, 0)
   917                                               else:
   918         1         37.8     37.8      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Opening input IDS...")
   919         1         13.5     13.5      0.0          print(backend, machine_in, shot_in, run_in, user_in)
   920         1          1.6      1.6      0.0          if DBentry.API == 'OLD':
   921                                                       ids_in = imas.ids(shot_in, run_in)
   922                                                       ids_in.open_env(user_in, machine_in, version)
   923                                                       idx_in = ids_in.core_profiles.getPulseCtx()  # idx_in points to input IDS file index
   924                                                   else:
   925         1         50.7     50.7      0.0              DBentry.idsin = imas.DBEntry(backend, machine_in, shot_in, run_in, user_name=user_in)
   926         1        869.7    869.7      0.0              status, idx_in = DBentry.idsin.open()  # idx_in points to input IDS file index
   927         1          1.1      1.1      0.0              if status != 0:
   928                                                           error_exit("Failure to open input IDS file... Aborting with status = "+str(status))
   929                                           
   930                                               # Initialise temporary IDS file
   931                                               # Required by all workflows calling physics actors - see JIRA issue IMAS-2921
   932         1     433495.2 433495.2      0.3      alenv = ALEnv(user_temp=user_tmp)
   933         1         12.8     12.8      0.0      tmp_db = alenv.ids_tmp
   934                                           
   935                                               # Set up IDS bundles, to make it easier to pass the IDSs between actors
   936                                               # ids_bundle_input:     IDS time slice from input database file, used i.a. for initialisation
   937                                               # ids_bundle_work:      input IDSs of the current timestep, only one timeslice
   938                                               # ids_bundle_prev:      collection of component-specific output IDSs from the previous component call
   939                                               #                       (initialised by subset of ids_bundle_work), only one timeslice
   940                                               # ids_bundle_updated:   output IDSs of the current timestep, only one timeslice
   941                                           
   942                                               # Initial IDS bundle (must contain all IDSs likely to be used)
   943                                               # Unused IDSs are removed from this list below
   944         1         10.1     10.1      0.0      ids_list_complete = imas_control.get_complete_ids_list()
   945         1          2.2      2.2      0.0      ids_bundle_input = {}
   946                                               
   947                                               # Read IDS input data -> move into a wrapper
   948         1          1.7      1.7      0.0      if mpi_root:
   949                                                   # Check which subset of IDS from the complete list are present in the data entry
   950        22         16.9      0.8      0.0          for ids_struct in ids_list_complete:
   951        22         37.6      1.7      0.0              if DBentry.API == 'OLD':
   952                                                           ids_bundle_input[ids_struct] = eval('ids_in.'+ids_struct)
   953                                                       else:
   954        22          6.7      0.3      0.0                  try:
   955                                                               # Next line currently causes problems if:
   956                                                               #  - no IDSIN is required (i.e. shot_in==0), AND
   957                                                               #  - IDSOUT datafile does not yet exist
   958        22   50742304.5 2306468.4     32.6                      ids_bundle_input[ids_struct] = eval('DBentry.idsin.get("'+ids_struct+'")')
   959                                                           except:
   960                                                               # Fall-back to using old-style API call to define structure
   961                                                               ids_bundle_input[ids_struct] = eval('ids_in.'+ids_struct)
   962                                               
   963         1   45878227.2 45878227.2     29.5          tmpdict = bundle_copy(ids_bundle_input)
   964        22          8.9      0.4      0.0          for elem in tmpdict:
   965        12          8.4      0.7      0.0              if elem not in ids_list:
   966        10         76.1      7.6      0.0                  del ids_bundle_input[elem]
   967                                                       else:
   968        12          6.3      0.5      0.0                  if shot_in != 0 and mpi_root:
   969        12          8.6      0.7      0.0                      if DBentry.API == 'OLD':
   970                                                                   ids_bundle_input[elem].ids_properties.homogeneous_time = ids_bundle_input[elem].getField('ids_properties/homogeneous_time')
   971                                                               else:
   972        12       9166.1    763.8      0.0                          ids_bundle_input[elem].ids_properties.homogeneous_time = DBentry.idsin.get_node(elem, 'ids_properties/homogeneous_time')
   973                                               
   974                                                   # Read in input IDS data, if present
   975         1          0.4      0.4      0.0          if shot_in != 0 and mpi_root:
   976         1         18.3     18.3      0.0              print("Reading input IDS...")
   977        12          8.4      0.7      0.0              for elem in ids_bundle_input:
   978         9         60.5      6.7      0.0                  if is_populated(ids_bundle_input[elem],1):
   979         3         68.3     22.8      0.0                      if verbose: print("Getting first slice from ", elem, "...")
   980         2          2.8      1.4      0.0                      if elem != 'equilibrium' and elem != 'summary' and elem != 'core_sources' and elem != 'workflow' and elem != 'pulse_schedule':
   981         1          0.5      0.5      0.0                          if DBentry.API == 'OLD':
   982                                                                       ids_bundle_input[elem].getSlice(tstart, interp_value)
   983                                                                   else:
   984         1     327381.7 327381.7      0.2                              ids_bundle_input[elem] = DBentry.idsin.get_slice(elem, tstart, interp_value)
   985         2          2.7      1.3      0.0                      elif elem == 'summary' or elem == 'workflow': # getSlice procedure does not work for summary IDS in test case #130011/public/iter/1 as array heating_current_drive.nbi[0].power.values does not seem to be populated
   986                                                                   ids_bundle_input[elem].ids_properties.homogeneous_time = imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS # set homogeneous time flag and add dummy time as empty IDS structures cannot be passed as argument to Python actors with IMAS version >= 3.28.0 even if they are not used by the actors
   987                                                                   ids_bundle_input[elem].time = np.array([-9999.0])
   988         2          1.6      0.8      0.0                      elif elem == 'pulse_schedule':
   989                                                                   if DBentry.API == 'OLD':
   990                                                                       ids_bundle_input[elem].get()
   991                                                                   else:
   992                                                                       ids_bundle_input[elem] = DBentry.idsin.get(elem)
   993                                                               else: # getSlice interpolation option does not seem to work for equilibrium IDS in test case #130011/public/iter/1 (segmentation fault for unknown reasons); core_sources contains time slice for t = 1.5 s three times, once at the beginning and two times at the end of the times array; core_sources contains two sources with the same identifier 'ec'; names and indices for core_sources source identifiers are not in agreement with name-index association given in the data dictionary
   994         2          4.2      2.1      0.0                          if DBentry.API == 'OLD':
   995                                                                       ids_bundle_input[elem].getSlice(tstart, interp_value)
   996                                                                   else:
   997         2    3193050.2 1596525.1      2.1                              ids_bundle_input[elem] = DBentry.idsin.get_slice(elem, tstart, interp_value)
   998                                                           else: # set homogeneous time flag and add dummy time as empty IDS structures cannot be passed as argument to Python actors with IMAS version >= 3.28.0 even if they are not used by the actors
   999         9          9.0      1.0      0.0                      ids_bundle_input[elem].ids_properties.homogeneous_time = imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS
  1000         9         39.0      4.3      0.0                      ids_bundle_input[elem].time = np.array([-9999.0])
  1001                                                   else:
  1002                                                       for elem in ids_bundle_input:
  1003                                                           ids_bundle_input[elem].ids_properties.homogeneous_time = imas.imasdef.IDS_TIME_MODE_HOMOGENEOUS
  1004                                                           ids_bundle_input[elem].time = np.array([-9999.0])
  1005                                           
  1006         1          1.9      1.9      0.0      if mpicfg.init and mpicfg.size > 1:
  1007                                                   if verbose: print('bcast ids_bundle_input...')
  1008                                                   ids_bundle_input = mpicfg.comm.bcast(ids_bundle_input, root=0)
  1009                                                   if verbose: print('...done')
  1010                                           
  1011                                               # Copy slice from ids_bundle_input to ids_bundle_work and ids_bundle_updated
  1012         1    3399663.8 3399663.8      2.2      ids_bundle_work = bundle_copy(ids_bundle_input)
  1013         1    4340984.3 4340984.3      2.8      ids_bundle_updated = bundle_copy(ids_bundle_input)
  1014                                           
  1015                                               # Set up initial workflow IDS, turn on required components and set initial time intervals
  1016                                               # Trigger first component only
  1017         1         12.7     12.7      0.0      ids_bundle_work['workflow'].time = np.array([tstart])
  1018         1         60.7     60.7      0.0      ids_bundle_work['workflow'].time_loop.component.resize(num_components)
  1019         1         23.3     23.3      0.0      ids_bundle_work['workflow'].time_loop.workflow_cycle.resize(1)
  1020         1         94.8     94.8      0.0      ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component.resize(num_components)
  1021         1         11.3     11.3      0.0      names = imas_control.get_array_order()
  1022         8          2.4      0.3      0.0      for icomponent in range(num_components):
  1023         8          8.1      1.0      0.0          ids_bundle_work['workflow'].time_loop.component[icomponent].name = names[icomponent]
  1024         8         10.4      1.3      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].index = icomponent + 1 #index in Fortran notation
  1025         8          8.7      1.1      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].execution_mode = 0
  1026         8         10.0      1.3      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].time_interval = 0.0
  1027         8         20.5      2.6      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].control_integer = np.array([0, 0, 0, 0])
  1028         8         16.3      2.0      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].control_float = np.array([0.0])
  1029         3          1.3      0.4      0.0      for icomponent in component_list:
  1030         3          4.2      1.4      0.0          icomponent_index = imas_control.get_component_index(icomponent)
  1031         3          4.2      1.4      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent_index].time_interval = tend-tstart
  1032         1          0.8      0.8      0.0      ids_bundle_work['workflow'].time_loop.time_end = tend
  1033         1          1.2      1.2      0.0      first_component_index = imas_control.get_component_index(component_list[0])
  1034         1          1.4      1.4      0.0      ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[first_component_index].execution_mode = 1
  1035                                               # Always set JETTO trigger, required for decomposed COCONUT runs:
  1036         1          0.7      0.7      0.0      if 'JETTO' in component_list:
  1037         1          0.9      0.9      0.0          jetto_component_index = imas_control.get_component_index('JETTO')
  1038         1          1.3      1.3      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[jetto_component_index].execution_mode = 1
  1039         1          0.6      0.6      0.0      if 'IDSIN' in component_list:
  1040         1          0.8      0.8      0.0          idsin_component_index = imas_control.get_component_index('IDSIN')
  1041         1          2.7      2.7      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[idsin_component_index].control_integer[2] = idx_in
  1042         1          0.3      0.3      0.0      if 'IDSOUT' in component_list:
  1043         1          0.8      0.8      0.0          idsout_component_index = imas_control.get_component_index('IDSOUT')
  1044         1          1.3      1.3      0.0          ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[idsout_component_index].control_integer[2] = idx_out
  1045         1          0.7      0.7      0.0          if create_ids == False:
  1046                                                       # Do not recreate IDS datafile if it exists already in case of restart from IMAS case;
  1047                                                       # instead, append to the existing IDS datafile, assuming that put() procedure has already been run
  1048                                                       # for each IDS structure in the preceding run. This assumption may need to be revised later on!
  1049                                                       for elem in ids_list:
  1050                                                           elemidx = imas_control.get_idsname_index(elem)
  1051                                                           ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[idsout_component_index].control_integer[3] += 2**(elemidx)
  1052                                           
  1053                                               # Zero HCD sources as they may be supposed to be provided from external actor that has not yet been called
  1054                                               # (this part can be removed pending adaptations in JINTRAC for non-consideration of external source input
  1055                                               # at (non-restart) initialisation step if HCD workflow is active and sources are not supposed to come from input IDS files):
  1056                                               #  TEMPORARILY(?) COMMENTED-OUT, BECAUSE IF THIS IS EXECUTED WITH AN EDGE2D-ONLY RUN WE GET A
  1057                                               #  KeyError('core_sources') EXCEPTION FOR REASONS NOT CLEAR TO ME (PJK) - IF ANYONE CAN EXPLAIN, PLEASE...
  1058                                               #for isource in range(len(ids_bundle_work['core_sources'].source)):
  1059                                               #    ids_bundle_work['core_sources'].source[isource].profiles_1d[0].electrons.energy[:] = 0.0
  1060                                               #    ids_bundle_work['core_sources'].source[isource].profiles_1d[0].total_ion_energy[:] = 0.0
  1061                                               #    ids_bundle_work['core_sources'].source[isource].profiles_1d[0].j_parallel[:] = 0.0
  1062                                               #    for iion in range(len(ids_bundle_work['core_sources'].source[isource].profiles_1d[0].ion)):
  1063                                               #        ids_bundle_work['core_sources'].source[isource].profiles_1d[0].ion[iion].particles[:] = 0.0
  1064                                               #    ids_bundle_work['core_sources'].source[isource].profiles_1d[0].momentum_tor[:] = 0.0
  1065                                           
  1066         1          0.4      0.4      0.0      ids_bundle_prev = {}
  1067         3          2.8      0.9      0.0      for item in component_list:
  1068         3    6779104.9 2259701.6      4.4          ids_bundle_prev[item] = bundle_copy(ids_bundle_work,imas_control.get_ids_sublist_updates(item))
  1069                                           
  1070         1          1.3      1.3      0.0      if 'IDSOUT' in component_list:
  1071         1         21.1     21.1      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Writing dataset_description")
  1072         1          7.8      7.8      0.0          ids_bundle_updated['dataset_description'] \
  1073         1        824.8    824.8      0.0              = dd.init(ids_bundle_work['dataset_description'], 0,
  1074         1          0.2      0.2      0.0                  comment_file)
  1075         1         22.1     22.1      0.0          ids_bundle_updated['dataset_description'].setPulseCtx(idx_out)
  1076         1          0.5      0.5      0.0          if mpi_root:
  1077         1       3751.0   3751.0      0.0              DBentry.idsout.put(ids_bundle_updated['dataset_description'])
  1078                                                   #code.interact(local=locals())
  1079                                           
  1080                                               # Time loop
  1081                                           
  1082         1          0.9      0.9      0.0      time = tstart
  1083         1          2.1      2.1      0.0      while time < tend:
  1084         1         22.0     22.0      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: time =", time, '\n')
  1085         8          5.4      0.7      0.0          for icomponent in range(num_components):
  1086         8          9.6      1.2      0.0              ids_bundle_work['workflow'].time[0] = time
  1087         8         21.7      2.7      0.0              ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].control_integer[0] = 0 #re-set action flag
  1088         8         25.4      3.2      0.0              ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent].control_float = np.array([0.0])
  1089         1       1764.3   1764.3      0.0          ids_bundle_updated['workflow'].copyValues(ids_bundle_work['workflow']) #workflow IDS from ids_bundle_updated foreseen to be used by all actors
  1090                                           
  1091                                                   # Advance each component
  1092         3          1.7      0.6      0.0          for item in component_list:
  1093         3         51.2     17.1      0.0              if verbose: print("JINTRAC_IMAS_DRIVER: check trigger for item ",item,"...")
  1094         3         21.9      7.3      0.0              item_index = imas_control.get_component_index(item)
  1095         3          9.3      3.1      0.0              if ids_bundle_updated['workflow'].time_loop.workflow_cycle[0].component[item_index].execution_mode == 1:
  1096         3         19.8      6.6      0.0                  if verbose: print("JINTRAC_IMAS_DRIVER: wrapper called for item ",item,"...")
  1097         3          0.8      0.3      0.0                  args = ("(noprocessors, imas_control, ids_bundle_updated, ids_bundle_work, ids_bundle_prev[item])")
  1098                                           
  1099                                                           # Call component via its wrapper
  1100         3   25454536.5 8484845.5     16.3                  ids_bundle_updated_tmp = eval(imas_control.get_wrapper(item) + args)
  1101                                           
  1102                                                           # Workflow-component specific consideration of IDS updates, update ids_bundle_prev:
  1103        14         44.9      3.2      0.0                  for ids_struct in imas_control.get_ids_sublist_updates(item):
  1104        14         11.3      0.8      0.0                      if ids_struct in ids_bundle_updated_tmp:
  1105        11        157.6     14.3      0.0                          if is_populated(ids_bundle_updated_tmp[ids_struct],2):
  1106        11    4817487.6 437953.4      3.1                              ids_bundle_updated[ids_struct].copyValues(ids_bundle_updated_tmp[ids_struct])
  1107        11    3587909.3 326173.6      2.3                              ids_bundle_prev[item][ids_struct].copyValues(ids_bundle_updated_tmp[ids_struct])
  1108         3          1.7      0.6      0.0                          elif ids_struct == 'transport_solver_numerics':
  1109                                                                       if is_populated(ids_bundle_updated_tmp[ids_struct],1):
  1110                                                                           ids_bundle_updated[ids_struct].copyValues(ids_bundle_updated_tmp[ids_struct])
  1111                                                                           ids_bundle_prev[item][ids_struct].copyValues(ids_bundle_updated_tmp[ids_struct])
  1112                                           
  1113                                                   # Copy newly updated IDS into input (work) IDS,
  1114                                                   # ready for next time step
  1115         1    4769085.3 4769085.3      3.1          ids_bundle_work = bundle_copy(ids_bundle_updated)
  1116                                           
  1117                                                   # Update and increment time
  1118         1          4.1      4.1      0.0          time = ids_bundle_work['workflow'].time[0]
  1119         1          1.1      1.1      0.0          dtmax = 0.0
  1120         3          1.8      0.6      0.0          for icomponent in component_list:
  1121         3          6.7      2.2      0.0              icomponent_index = imas_control.get_component_index(icomponent)
  1122         3         16.0      5.3      0.0              dtmax = max(dtmax, ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent_index].time_interval)
  1123         1          3.8      3.8      0.0          time += dtmax
  1124         1         37.1     37.1      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Calculated time interval = ", dtmax)
  1125         1          1.5      1.5      0.0          dtmaxnew = tend-time
  1126         3          1.0      0.3      0.0          for icomponent in component_list:
  1127         3          3.1      1.0      0.0              icomponent_index = imas_control.get_component_index(icomponent)
  1128         3          4.3      1.4      0.0              ids_bundle_work['workflow'].time_loop.workflow_cycle[0].component[icomponent_index].time_interval = dtmaxnew
  1129         1         19.5     19.5      0.0          if verbose: print("JINTRAC_IMAS_DRIVER: Next target interval = ", dtmaxnew)
  1130                                           
  1131                                               # end of time loop
  1132                                           
  1133         1          8.0      8.0      0.0      if verbose: print("JINTRAC_IMAS_DRIVER: Finish time =", time)
  1134                                           
  1135         1       2166.3   2166.3      0.0      alenv.close()
  1136                                           
  1137         1          5.2      5.2      0.0      ids_in.close()
  1138         1          3.4      3.4      0.0      if DBentry.API == 'NEW':
  1139         1       1367.3   1367.3      0.0          DBentry.idsin.close()
  1140                                           
  1141         1          2.5      2.5      0.0      if 'IDSOUT' in component_list:
  1142         1       2230.6   2230.6      0.0          DBentry.idsout.close()
  1143                                           
  1144         1          0.4      0.4      0.0      return 0