def save_operator_files(task): """ Create archive of relative operator files. Manual follow-up: The operator files are bundled into tgz files and saved to the current run's results directory. They should then be moved (manually) to the directory specified in SPNCCI_LSU3SHELL_DIR, for subsequent use. """ # select files to save archive_file_list = glob.glob('*.dat') archive_file_list += glob.glob('*.PN') archive_file_list += glob.glob('*.PPNN') # generate archive descriptor = relative_operator_descriptor(task) archive_filename = "relative-operators-{}.tgz".format(descriptor) mcscript.call( [ "tar", "-zcvf", archive_filename ] + archive_file_list ) # move archive to results directory (if in multi-task run) if (mcscript.task.results_dir is not None): mcscript.call( [ "mv", "--verbose", archive_filename, "--target-directory={}".format(mcscript.task.results_dir) ] )
def save_mfdn_wavefunctions(task, postfix=""): """Collect and save MFDn wave functions. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ descriptor = task["metadata"]["descriptor"] work_dir = "work{:s}".format(postfix) filename_prefix = "{:s}-mfdn15wf-{:s}{:s}".format( mcscript.parameters.run.name, descriptor, postfix) archive_file_list = glob.glob(work_dir + "/mfdn_smwf*") archive_file_list += glob.glob(work_dir + "/mfdn_MBgroups*") archive_file_list += glob.glob(work_dir + "/mfdn_partitioning.*") archive_filename = "{:s}.tar".format(filename_prefix) mcscript.call([ "tar", "cvf", archive_filename, "--transform=s,{:s}/,,".format( work_dir), "--transform=s,^,{:s}/{:s}{:s}/,".format( mcscript.parameters.run.name, descriptor, postfix), "--show-transformed" ] + archive_file_list) # move wave function archives out (if in multi-task run) if (mcscript.task.results_dir is not None): wavefunction_dir = os.path.join(mcscript.task.results_dir, "wf") mcscript.utils.mkdir(wavefunction_dir, exist_ok=True) mcscript.call([ "mv", "--verbose", archive_filename, "--target-directory={}".format(wavefunction_dir) ])
def save_spncci_results(task): """ Rename and save spncci results files. """ ## # log file ## raw_log_filename = "spncci.out" ## new_log_filename = os.path.join( ## mcscript.task.results_dir, ## "{name}-{descriptor}.out".format(name=mcscript.parameters.run.name,**task) ## ) ## mcscript.call( ## [ ## "cp", ## "--verbose", ## raw_log_filename, ## new_log_filename ## ] ## ) # results file raw_log_filename = "spncci.res" new_log_filename = os.path.join( mcscript.task.results_dir, "{name}-{descriptor}.res".format(name=mcscript.parameters.run.name,**task) ) mcscript.call( [ "cp", "--verbose", raw_log_filename, new_log_filename ] )
def extract_natural_orbitals(task, postfix=""): """Extract OBDME files for subsequent natural orbital iterations. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # save OBDME files for next natural orbital iteration if not task.get("natural_orbitals"): raise mcscript.exception.ScriptError("natural orbitals not enabled") work_dir = "work{:s}".format(postfix) obdme_info_filename = "mfdn.rppobdme.info" try: (J, g, n) = task["natorb_base_state"] obdme_filename = glob.glob( "{:s}/mfdn.statrobdme.seq*.2J{:02d}.n{:02d}.2T*".format( work_dir, 2 * J, n)) except TypeError: obdme_filename = glob.glob("{:s}/mfdn.statrobdme.seq{:03d}*".format( work_dir, task["natorb_base_state"])) print("Saving OBDME files for natural orbital generation...") mcscript.call([ "cp", "--verbose", os.path.join(work_dir, obdme_info_filename), environ.natorb_info_filename(postfix) ]) mcscript.call([ "cp", "--verbose", obdme_filename[0], environ.natorb_obdme_filename(postfix) ])
def set_up_natural_orbitals(task, source_postfix, target_postfix): """Set up natural orbitals for MFDn run. Arguments: task (dict): as described in module docstring source_postfix (string): identifier for source of natural orbital information target_postfix (string): identifier to add to generated files Limitation: Currently uses initial orbital weights and truncation as natural orbital weights and truncation. """ # validate natural orbitals enabled if not task.get("natural_orbitals"): raise mcscript.exception.ScriptError( "natural orbitals are not enabled") mcscript.call([ environ.shell_filename("natorb-gen"), environ.orbitals_filename(source_postfix), environ.natorb_info_filename(source_postfix), environ.natorb_obdme_filename(source_postfix), environ.natorb_xform_filename(target_postfix), environ.orbitals_filename(target_postfix) ], mode=mcscript.CallMode.kSerial)
def do_generate_lsu3shell_rmes(task): """ Control code for generating RMEs in the SU(3)-NCSM basis, for relative unit tensors and symplectic raising/lowering/N operators. """ # retrieve relevant operator files retrieve_operator_files(task) # generate model space file needed by lsu3shell codes generate_model_space_file(task) # generate basis listing for basis in which rmes are calculated generate_basis_table(task) # generate operators rmes calculate_rmes(task) # save results save_su3rme_files(task) # clean up working directory mcscript.call(["du","-hs","."]) # log working directory disk usage delete_filenames=glob.glob('*') ##delete_filenames=glob.glob('*.rme') ##delete_filenames+=glob.glob('*.PN') ##delete_filenames+=glob.glob('*.PPNN') mcscript.call(["rm"] + delete_filenames)
def set_up_orbitals_Nmax(task, postfix=""): """Set up Nmax-truncated target orbitals for MFDn run. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # validate truncation mode if task["sp_truncation_mode"] is not modes.SingleParticleTruncationMode.kNmax: raise ValueError( "expecting truncation_mode to be {} but found {truncation_mode}". format(modes.SingleParticleTruncationMode.kNmax, **task)) # generate orbitals -- target basis truncation_parameters = task["truncation_parameters"] if truncation_parameters.get("Nmax_orb") is not None: Nmax_orb = truncation_parameters["Nmax_orb"] elif task["mb_truncation_mode"] == modes.ManyBodyTruncationMode.kNmax: Nmax_orb = truncation_parameters["Nmax"] + utils.Nv_for_nuclide( task["nuclide"]) elif task["mb_truncation_mode"] == modes.ManyBodyTruncationMode.kFCI: Nmax_orb = truncation_parameters["Nmax"] mcscript.call([ environ.shell_filename("orbital-gen"), "--Nmax", "{Nmax_orb:d}".format(Nmax_orb=Nmax_orb), "{:s}".format( environ.orbitals_filename(postfix)) ], mode=mcscript.CallMode.kSerial)
def cleanup_mfdn_workdir(task, postfix=""): """Remove temporary MFDn work files. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # cleanup of wave function files scratch_file_list = glob.glob("work{:s}/*".format(postfix)) mcscript.call(["rm", "-vf"] + scratch_file_list)
def moshinsky_transform_operator(): command_line=[ moshinsky_executable, "< moshinsky.in" ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial )
def generate_model_space_file(task): """Create LSU3shell model space file for SU3RME. Invokes generate_lsu3shell_model_space. """ command_line = [ generate_lsu3shell_model_space_executable, "{nuclide[0]:d}".format(**task), "{nuclide[1]:d}".format(**task), "{Nsigma_max:d}".format(**task), "{Nstep:d}".format(**task) ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial )
def set_up_radial_natorb(task, source_postfix, target_postfix): """Generate radial integrals and overlaps by transformation for MFDn run in natural orbital basis. Operation mode must be generic. Arguments: task (dict): as described in module docstring source_postfix (str): postfix for old basis target_postfix (str): postfix for new basis """ # validate natural orbitals enabled if not task.get("natural_orbitals"): raise mcscript.exception.ScriptError( "natural orbitals are not enabled") # compose radial transform mcscript.call([ environ.shell_filename("radial-compose"), environ.radial_xform_filename(source_postfix), environ.natorb_xform_filename(target_postfix), environ.radial_xform_filename(target_postfix) ], mode=mcscript.CallMode.kSerial) # compose interaction transform mcscript.call([ environ.shell_filename("radial-compose"), environ.radial_olap_int_filename(source_postfix), environ.natorb_xform_filename(target_postfix), environ.radial_olap_int_filename(target_postfix) ], mode=mcscript.CallMode.kSerial) # compose Coulomb transform if (task["use_coulomb"]): mcscript.call([ environ.shell_filename("radial-compose"), environ.radial_olap_coul_filename(source_postfix), environ.natorb_xform_filename(target_postfix), environ.radial_olap_coul_filename(target_postfix) ], mode=mcscript.CallMode.kSerial) # transform radial integrals for operator_type in k_radialgen_operators: mcscript.call([ environ.shell_filename("radial-xform"), environ.orbitals_filename(target_postfix), environ.natorb_xform_filename(target_postfix), environ.obme_filename(source_postfix, operator_type), environ.obme_filename(target_postfix, operator_type) ], mode=mcscript.CallMode.kSerial) # set up radial matrix elements for natural orbitals set_up_observable_radial_natorb(task, source_postfix, target_postfix)
def generate_basis_table(task): """Create SU(3)-NCSM basis table. Invokes ncsmSU3xSU2IrrepsTabular. Depends on model space file created by generate_lsu3shell_relative_operators. """ print("{nuclide}".format(**task)) model_space_filename = "model_space.dat".format(**task) basis_listing_filename = "lsu3shell_basis.dat" command_line=[su3basis_executable,model_space_filename,basis_listing_filename] mcscript.call( command_line, mode=mcscript.CallMode.kSerial )
def retrieve_operator_files(task): """ Retrieve archive of relative operator files. """ # identify archive file descriptor = relative_operator_descriptor(task) archive_filename = mcscript.utils.search_in_subdirectories( operator_directory_list, operator_subdirectory_list, "relative-operators-{}.tgz".format(descriptor), error_message="relative operator archive file not found" ) # extract archive contents mcscript.call( [ "tar", "xf", archive_filename ] )
def say_goodbye(task): """Do a goodbye world task given current task parameters. We are using this as an example of a second (well, first) "phase" of a calculation, which should only be attempted if the first (well, zeroth) "phase" has been flagged as having successfully completed. Expected dictionary keys: "world_name" : name of world to greet """ # write greeting message to file mcscript.utils.write_input( "goodbye.txt", input_lines=[ "We have already said hello, {world_name},".format(**task), "and now it is time to say goodbye." ] ) # save results file to common results directory print("Saving renamed output file...") results_filename = "{}-goodbye-{:s}.txt".format(mcscript.parameters.run.name,task["metadata"]["descriptor"]) mcscript.call( [ "cp", "--verbose", "goodbye.txt", results_filename ] ) mcscript.call( [ "cp", "--verbose", results_filename, "--target-directory={}".format(mcscript.task.results_dir) ] )
def generate_relative_operators(task): """Create recoupler input files for relative unit tensors and symplectic raising/lowering/N operators. Invokes generate_lsu3shell_relative_operators. """ command_line = [ generate_lsu3shell_relative_operators_executable, "{Nsigma_max:d}".format(**task), "{Nstep:d}".format(**task), "{N1v:d}".format(**task), "-1",# All J0 "-1"# All T0 ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial )
def set_up_interaction_orbitals(task, postfix=""): """Set up interaction orbitals for MFDn run. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # generate orbitals -- interaction bases mcscript.call([ environ.shell_filename("orbital-gen"), "--Nmax", "{truncation_int[1]:d}".format(**task), "{:s}".format( environ.orbitals_int_filename(postfix)) ], mode=mcscript.CallMode.kSerial) if task["use_coulomb"]: mcscript.call([ environ.shell_filename("orbital-gen"), "--Nmax", "{truncation_coul[1]:d}".format(**task), "{:s}".format( environ.orbitals_coul_filename(postfix)) ], mode=mcscript.CallMode.kSerial)
def call_spncci(task): """ Carry out spncci run. """ ## A = int(task["nuclide"][0]+task["nuclide"][1]) # why cast to int??? ## twice_Nsigma_0 = int(2*task["Nsigma_0"]) if ("spncci_variant" not in task): task["spncci_variant"] = "spncci" spncci_executable = os.path.join(spncci_executable_dir,task["spncci_variant"]) command_line = [ spncci_executable ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial ) # cleanup mcscript.call(["rm","-r","lsu3shell_rme","relative_observables"])
def say_hello(task): """ Do a hello world task given current task parameters. Expected dictionary keys: "world_name" : name of world to greet """ # write greeting message to file mcscript.utils.write_input( "hello.txt", input_lines=[ "Dear {world_name},".format(**task), " Hello!", "Your script", mcscript.parameters.run.name ] ) # save results file to common results directory print("Saving renamed output file...") results_filename = "{}-hello-{:s}.txt".format(mcscript.parameters.run.name,task["metadata"]["descriptor"]) mcscript.call( [ "cp", "--verbose", "hello.txt", results_filename ] ) mcscript.call( [ "cp", "--verbose", results_filename, "--target-directory={}".format(mcscript.task.results_dir) ] )
def recouple_operators(task,relative_operator_basename_list): """ Invoke lsu3shell recoupler code on relative unit tensors and symplectic raising/lowering/N operators. Invokes RecoupleSU3Operator. Arguments: relative_operator_basename_list (list) : list of operator names """ # iterate over unit tensors for basename in relative_operator_basename_list: # call recoupler command_line = [ recoupler_executable, "{}.recoupler".format(basename), basename ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial )
def set_up_orbitals_triangular(task, postfix=""): """Set up triangular-truncated (an+bl) target orbitals for MFDn run. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # validate truncation mode if task["sp_truncation_mode"] is not modes.SingleParticleTruncationMode.kTriangular: raise ValueError( "expecting truncation_mode to be {} but found {truncation_mode}". format(modes.SingleParticleTruncationMode.kTriangular, **task)) # generate orbitals -- target basis truncation_parameters = task["truncation_parameters"] mcscript.call([ environ.shell_filename("orbital-gen"), "--triangular", "{sp_weight_max:f}".format(**truncation_parameters), "{n_coeff:f}".format(**truncation_parameters), "{l_coeff:f}".format(**truncation_parameters), "{:s}".format( environ.orbitals_filename(postfix)) ], mode=mcscript.CallMode.kSerial)
def set_up_observable_radial_natorb(task, source_postfix, target_postfix): """Generate radial integrals and overlaps by transformation for MFDn run in natural orbital basis. Operation mode must be generic. Arguments: task (dict): as described in module docstring source_postfix (str): postfix for old basis target_postfix (str): postfix for new basis """ # validate natural orbitals enabled if not task.get("natural_orbitals"): raise mcscript.exception.ScriptError( "natural orbitals are not enabled") for (operator_type, order) in task.get("ob_observables", []): if operator_type == 'E': radial_power = order elif operator_type == 'M': radial_power = order - 1 else: raise mcscript.exception.ScriptError( "only E or M transitions currently supported") # short-circuit on solid harmonic of order zero if radial_power == 0: continue operator_id = "rY{:d}".format(order) mcscript.call([ environ.shell_filename("radial-xform"), environ.orbitals_filename(target_postfix), environ.natorb_xform_filename(target_postfix), environ.obme_filename(source_postfix, operator_id), environ.obme_filename(target_postfix, operator_id) ], mode=mcscript.CallMode.kSerial)
def set_up_orbitals_manual(task, postfix=""): """Copy in manually-provided orbitals. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ if task["sp_truncation_mode"] is not modes.SingleParticleTruncationMode.kManual: raise ValueError( "expecting truncation_mode to be {} but found {truncation_mode}". format(modes.SingleParticleTruncationMode.kManual, **task)) truncation_parameters = task["truncation_parameters"] sp_filename = truncation_parameters.get("sp_filename") if sp_filename is None: raise mcscript.exception.ScriptError( "sp_orbitals file must be provided") else: sp_filename = mcscript.utils.expand_path(sp_filename) if not os.path.exists(sp_filename): raise FileNotFoundError(sp_filename) mcscript.call( ["cp", "--verbose", sp_filename, environ.orbitals_filename(postfix)])
def calculate_rmes(task): """ Invoke lsu3shell SU3RME code to calculate rmes of relative unit tensors and symplectic raising/lowering/N operators in SU(3)-NCSM basis. Invokes SU3RME_MPI. """ model_space_filename = "model_space.dat".format(**task) if ("su3rme_mode" not in task): task["su3rme_mode"] = "text" # call SU3RME command_line = [ su3rme_executable, model_space_filename, model_space_filename, "relative_operators.dat", task["su3rme_mode"] ] mcscript.call( command_line, mode=mcscript.CallMode.kHybrid )
def save_su3rme_files(task): """Create archive of SU(3) RMEs of relative operators. Some auxiliary files (e.g., the list of operators) are saved as well. Manual follow-up: The rme files are bundled into tgz files and saved to the current run's results directory. They should then be moved (manually) to the directory specified in SPNCCI_LSU3SHELL_DIR, for subsequent use. """ su3rme_descriptor = task["su3rme_descriptor_template"].format(**task) # select files to save archive_file_list = [ "model_space.dat", "relative_operators.dat", "lsu3shell_basis.dat", "relative_unit_tensor_labels.dat" ] archive_file_list += glob.glob('*.rme') # generate archive archive_filename = "su3rme-{}.tgz".format(su3rme_descriptor) mcscript.call( [ "tar", "-zcvf", archive_filename ] + archive_file_list ) # save independent copy of basis listing outside tarball for easy inspection basis_filename = "lsu3shell_basis_{}.dat".format(su3rme_descriptor) mcscript.call( [ "cp", "lsu3shell_basis.dat", basis_filename ] ) # move archive to results directory (if in multi-task run) if (mcscript.task.results_dir is not None): mcscript.call( [ "mv", "--verbose", basis_filename,archive_filename, "--target-directory={}".format(mcscript.task.results_dir) ] )
def generate_em(task, postfix=""): """Generate electromagnetic matrix elements. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # accumulate em-gen input lines lines = [] # set up orbitals lines += [ "set-indexing {:s}".format(environ.orbitals_filename(postfix)), "set-basis-scale-factor {:e}".format( utils.oscillator_length(task["hw"])), ] for am_type in ["l", "s"]: lines.append("define-am-source {type:s} {filename:s}".format( type=am_type, filename=environ.obme_filename(postfix, am_type))) for (operator_type, order) in task.get("ob_observables", []): if operator_type == 'E': radial_power = order elif operator_type == 'M': radial_power = order - 1 else: raise mcscript.exception.ScriptError( "only E or M transitions currently supported") # load non-trivial solid harmonic RMEs if radial_power > 0: operator_id = "rY{:d}".format(radial_power) lines.append( "define-radial-source {type:s} {order:d} {filename:s}".format( type='r', order=radial_power, filename=environ.obme_filename(postfix, operator_id))) for species in ["p", "n"]: if operator_type == "E": lines.append( "define-target E {order:d} {species:s} {output_filename:s}" .format(order=order, species=species, output_filename=environ.observable_me_filename( postfix, operator_type, order, species))) elif operator_type == "M": lines.append( "define-target Dl {order:d} {species:s} {output_filename:s}" .format(order=order, species=species, output_filename=environ.observable_me_filename( postfix, "Dl", order, species))) lines.append( "define-target Ds {order:d} {species:s} {output_filename:s}" .format(order=order, species=species, output_filename=environ.observable_me_filename( postfix, "Ds", order, species))) # ensure trailing line lines.append("") # write input file mcscript.utils.write_input(environ.emgen_filename(postfix), input_lines=lines, verbose=False) # invoke em-gen mcscript.call([environ.shell_filename("em-gen")], input_lines=lines, mode=mcscript.CallMode.kSerial)
def save_mfdn_task_data(task, postfix=""): """Collect and save working information. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # convenience definitions descriptor = task["metadata"]["descriptor"] work_dir = "work{:s}".format(postfix) filename_prefix = "{:s}-mfdn15-{:s}{:s}".format( mcscript.parameters.run.name, descriptor, postfix) # save full archive of input, log, and output files print("Saving full output files...") # logging archive_file_list = [ environ.h2mixer_filename(postfix), "tbo_names{:s}.dat".format(postfix) ] # orbital information archive_file_list += [ environ.orbitals_int_filename(postfix), environ.orbitals_filename(postfix), ] # transformation information archive_file_list += [ environ.radial_xform_filename(postfix), # environ.radial_me_filename(postfix, operator_type, power), environ.radial_olap_int_filename(postfix), ] # Coulomb information: if task["use_coulomb"]: archive_file_list += [ environ.orbitals_coul_filename(postfix), environ.radial_olap_coul_filename(postfix), ] # natural orbital information if task.get("natural_orbitals"): archive_file_list += [ environ.natorb_info_filename(postfix), environ.natorb_obdme_filename(postfix), ] # glob for natural orbital xform archive_file_list += glob.glob(environ.natorb_xform_filename(postfix)) # MFDn output archive_file_list += [ work_dir + "/mfdn.input", work_dir + "/mfdn.out", work_dir + "/mfdn.res", ] if os.path.isfile(work_dir + "/mfdn_partitioning.generated"): archive_file_list += [work_dir + "/mfdn_partitioning.generated"] if os.path.isfile(work_dir + "/mfdn_sp_orbitals.info"): archive_file_list += [work_dir + "/mfdn_sp_orbitals.info"] # partitioning file if os.path.isfile(work_dir + "/mfdn_partitioning.info"): archive_file_list += [work_dir + "/mfdn_partitioning.info"] # MFDN obdme if (task["save_obdme"]): archive_file_list += glob.glob(work_dir + "/mfdn*obdme*") # observable output if os.path.isfile(environ.emgen_filename(postfix)): archive_file_list += [environ.emgen_filename(postfix)] if os.path.isfile(environ.obscalc_ob_filename(postfix)): archive_file_list += [environ.obscalc_ob_filename(postfix)] if os.path.isfile(environ.obscalc_ob_res_filename(postfix)): archive_file_list += [environ.obscalc_ob_res_filename(postfix)] # generate archive (outside work directory) task_data_archive_filename = "{:s}.tgz".format(filename_prefix) mcscript.call([ "tar", "zcvf", task_data_archive_filename, "--transform=s,{:s}/,,". format(work_dir), "--transform=s,^,{:s}/{:s}{:s}/,".format( mcscript.parameters.run.name, descriptor, postfix), "--show-transformed" ] + archive_file_list) # copy results out (if in multi-task run) if (mcscript.task.results_dir is not None): # copy out task data archives task_data_dir = os.path.join(mcscript.task.results_dir, "task-data") mcscript.utils.mkdir(task_data_dir, exist_ok=True) mcscript.call([ "cp", "--verbose", task_data_archive_filename, "--target-directory={}".format(task_data_dir) ])
def extract_mfdn_task_data(task, task_data_dir=None, run_name=None, descriptor=None, postfix=""): """Extract task directory from task data archive. Arguments: task (dict): as described in module docstring task_data_dir (str, optional): location where results archives can be found; defaults to current run results directory run_name (str, optional): run name for archive; defaults to current run name descriptor (str, optional): descriptor for archive; defaults to current descriptor postfix (str, optional): postfix for archive; defaults to empty string """ # get defaults if task_data_dir is None: task_data_dir = os.path.join(mcscript.task.results_dir, "task-data") if run_name is None: run_name = mcscript.parameters.run.name if descriptor is None: descriptor = task["metadata"]["descriptor"] # expand results directory path task_data_dir = mcscript.utils.expand_path(task_data_dir) # construct archive path filename_prefix = "{:s}-mfdn15-{:s}{:s}".format(run_name, descriptor, postfix) task_data_archive_filename = "{:s}.tgz".format(filename_prefix) archive_path = os.path.join(task_data_dir, task_data_archive_filename) # extract archive mcscript.call([ "tar", "zxvf", archive_path, ]) # archive subdirectory inside expanded path extracted_dir = os.path.join(run_name, descriptor + postfix) # move MFDn files back into work directory work_dir = "work{:s}".format(postfix) mcscript.utils.mkdir(work_dir, exist_ok=True) file_list = [ extracted_dir + "/mfdn.input", extracted_dir + "/mfdn.out", extracted_dir + "/mfdn.res", ] if os.path.isfile(extracted_dir + "/mfdn_partitioning.generated"): file_list += [extracted_dir + "/mfdn_partitioning.generated"] if os.path.isfile(extracted_dir + "/mfdn_sp_orbitals.info"): file_list += [extracted_dir + "/mfdn_sp_orbitals.info"] # partitioning file if os.path.isfile(extracted_dir + "/mfdn_partitioning.info"): file_list += [extracted_dir + "/mfdn_partitioning.info"] # MFDN obdme if (glob.glob(extracted_dir + "/mfdn.*obdme*")): file_list += glob.glob(extracted_dir + "/mfdn.*obdme*") mcscript.call([ "mv", "-t", work_dir + "/", ] + file_list) # move remaining files into task directory file_list = glob.glob(extracted_dir + "/*") mcscript.call([ "mv", "-t", "./", ] + file_list) # remove temporary directories mcscript.call(["rm", "-vfd", extracted_dir, run_name])
def generate_observable_rmes(task): """Generate relative U3ST RMEs of observable operators. This may either be by upcoupling relative RMEs or by analytic expressions. Invokes generate_relative_operator_rmes. Output directory: relative_observables Output filename format: {}_hw{:.1f}_Nmax{:02d}_u3st.dat """ mcscript.utils.mkdir("relative_observables") os.chdir("relative_observables") # set parameters A = int(task["nuclide"][0]+task["nuclide"][1]) Nmax=task["Nmax"] J0=0 T0=-1 g0=0 J_max_jisp=4 J_max_coulomb=21 # generate Hamiltonian RMEs (by upcoupling) for hw in mcscript.utils.value_range(*task["hw_range"]): # generate load file interaction_filename = mcscript.utils.search_in_subdirectories( interaction_directory_list, interaction_subdirectory_list, task["interaction_filename_template"].format(hw=hw), error_message="relative interaction file not found" ) hamiltonian_input_lines = [ "{}".format(hw), "Tintr 1.", "INT 1. {} {} {} {} {}".format(J_max_jisp,J0,T0,g0,interaction_filename,**task) ] if task["use_coulomb"]==True: coulomb_filename = mcscript.utils.search_in_subdirectories( interaction_directory_list, interaction_subdirectory_list, task["coulomb_filename"], error_message="relative interaction file not found (for Coulomb interaction)" ) hamiltonian_input_lines+=["COUL 1. {} {} {} {} {}".format(J_max_coulomb,J0,T0,g0,coulomb_filename,**task)] hamiltonian_load_filename = "hamiltonian.load" mcscript.utils.write_input(hamiltonian_load_filename,hamiltonian_input_lines,verbose=True) # Call code to upcouple and generate input file for hamiltonian # # TODO: fix to take (N,Z) instead of (A,N1v), and remove N1v from task dictionary command_line = [ generate_relative_operator_rmes_executable, "{}".format(A) , "{Nmax:d}".format(**task), "{N1v:d}".format(**task), "hamiltonian" ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial ) # generate RMEs for other observables (analytically) for hw in mcscript.utils.value_range(*task["hw_range"]): # generate observable load files for observable in task["observables"] : observable_name=observable[0] # Generate load files for other observables input_lines = [ "{}".format(hw), "{} 1.".format(observable_name) ] load_file_name = "{}.load".format(observable_name) mcscript.utils.write_input(load_file_name,input_lines,verbose=True) # Generate observable u3st rmes print("made load file") command_line = [ generate_relative_operator_rmes_executable, "{:d}".format(A) , "{Nmax:d}".format(**task), "{N1v:d}".format(**task), "{}".format(observable_name) ] mcscript.call( command_line, mode=mcscript.CallMode.kSerial ) os.chdir("..")
def extract_wavefunctions(task, wavefunctions_dir=None, run_name=None, descriptor=None, postfix="", target_dir=None): """Extract wave functions to task directory from output archive. Arguments: task (dict): as described in module docstring wavefunctions_dir (str, optional): location where results archives can be found; defaults to current run results directory run_name (str, optional): run name for archive; defaults to current run name descriptor (str, optional): descriptor for archive; defaults to current descriptor postfix (str, optional): postfix for archive; defaults to empty string target_dir (str, optional): path for target directory for wavefunction files; defaults to current task directory and, if unqualified, will be taken relative to such as current working directory """ # get defaults if wavefunctions_dir is None: wavefunctions_dir = os.path.join(mcscript.task.results_dir, "wf") if run_name is None: run_name = mcscript.parameters.run.name if descriptor is None: descriptor = task["metadata"]["descriptor"] if target_dir is None: target_dir = "work{:s}".format(postfix) mcscript.utils.mkdir(target_dir, exist_ok=True) # expand results directory path wavefunctions_dir = mcscript.utils.expand_path(wavefunctions_dir) # construct archive path filename_prefix = "{:s}-mfdn15wf-{:s}{:s}".format(run_name, descriptor, postfix) wavefunctions_archive_filename = "{:s}.tar".format(filename_prefix) archive_path = os.path.join(wavefunctions_dir, wavefunctions_archive_filename) if not os.path.exists(archive_path): # fall back to old filename convention filename_prefix = "{:s}-mfdn15-{:s}{:s}".format( run_name, descriptor, postfix) wavefunctions_archive_filename = "{:s}-wf.tar".format(filename_prefix) archive_path = os.path.join(wavefunctions_dir, wavefunctions_archive_filename) # extract archive mcscript.call([ "tar", "xvf", archive_path, ]) # archive subdirectory inside expanded path extracted_dir = os.path.join(run_name, descriptor + postfix) # move files into task directory file_list = glob.glob(os.path.join(extracted_dir, "*")) mcscript.call([ "mv", "-t", target_dir, ] + file_list) # remove temporary directories mcscript.call(["rm", "-vfd", extracted_dir, run_name])
def retrieve_su3rme_files(task): """ Retrieve archive of relative operator SU(3) RME files. (1) Directory is symlinked as a subdirectory named lsu3shell_rme, or... (2) Files are retrieved into a subdirectory named lsu3shell_rme. """ # identify su3rme data directory su3rme_descriptor = task["su3rme_descriptor_template"].format(**task) directory_name = mcscript.utils.search_in_subdirectories( su3rme_directory_list, su3rme_subdirectory_list, "su3rme-{}".format(su3rme_descriptor), error_message="Data directory for SU(3) RMEs not found", fail_on_not_found=False ) archive_filename = mcscript.utils.search_in_subdirectories( su3rme_directory_list, su3rme_subdirectory_list, "su3rme-{}.tgz".format(su3rme_descriptor), error_message="Archive file for SU(3) RMEs not found", fail_on_not_found=False ) if (directory_name is not None): # remove any existing symlink or data directory # # Notes: On a symlink to a directory: rmdir fails; rm or "rm -r" # removes symlink. But "rm -r" will also work if tar file had # been directly expanded before and needs to be replaced by a # symlink. if (os.path.exists("lsu3shell_rme")): mcscript.call(["rm","-r","lsu3shell_rme"]) # link to data su3rme directory mcscript.call( [ "ln", "-s", directory_name, "lsu3shell_rme" ] ) elif (archive_filename is not None): # set up data directory if (not os.path.exists("lsu3shell_rme")): mcscript.utils.mkdir("lsu3shell_rme") # extract archive contents mcscript.call( [ "tar", "-xvf", archive_filename, "--directory=lsu3shell_rme" ] ) else: raise(mcscript.exception.ScriptError("Cannot find SU(3) RME data"))
def set_up_radial_analytic(task, postfix=""): """Generate radial integrals and overlaps by integration for MFDn run in analytic basis. Operation mode may in general be direct oscillator, dilated oscillator, or generic (TODO). Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ # validate basis mode if (task["basis_mode"] not in {modes.BasisMode.kDirect, modes.BasisMode.kDilated }): # no modes.BasisMode.kGeneric yet raise ValueError("invalid basis mode {basis_mode}".format(**task)) # basis radial code -- expected by radial_utils codes basis_radial_code = "oscillator" # TODO GENERALIZE: if not oscillator basis # define commands ket_basis_command = "set-ket-basis {basis_type:s} {orbital_filename:s}" operator_target_command = ( "define-operator-target {mode:s} {operator_type:s} {output_filename:s}" ) xform_target_command = ( "define-xform-target {scale_factor:e} {bra_basis_type:s} {bra_orbital_file:s} {output_filename:s}" ) # collect input lines lines = [] lines.append( ket_basis_command.format( basis_type=basis_radial_code, orbital_filename=environ.orbitals_filename(postfix))) # generate kinematic RMEs for operator_type in k_kinematic_operators.keys(): lines.append( operator_target_command.format( mode="kinematic", operator_type=operator_type, output_filename=environ.obme_filename(postfix, operator_type))) # generate am RMEs for operator_type in k_am_operators.keys(): lines.append( operator_target_command.format( mode="am", operator_type=operator_type, output_filename=environ.obme_filename(postfix, operator_type))) # generate isospin RMEs for operator_type in k_isospin_operators.keys(): lines.append( operator_target_command.format( mode="isospin", operator_type=operator_type, output_filename=environ.obme_filename(postfix, operator_type))) # set up radial matrix elements for observables lines += set_up_observable_radial_analytic(task, postfix) # generate radial overlaps -- generate trivial identities if applicable # # dummy radial xform lines.append( xform_target_command.format( scale_factor=1.0, bra_basis_type=basis_radial_code, bra_orbital_file=environ.orbitals_filename(postfix), output_filename=environ.radial_xform_filename(postfix))) # interaction xform b_ratio = math.sqrt(task["hw_int"] / task["hw"]) lines.append( xform_target_command.format( scale_factor=b_ratio, bra_basis_type="oscillator", bra_orbital_file=environ.orbitals_int_filename(postfix), output_filename=environ.radial_olap_int_filename(postfix))) if (task["use_coulomb"]): if task.get("hw_coul_rescaled") is None: b_ratio = 1 else: b_ratio = math.sqrt(task["hw_coul_rescaled"] / task["hw"]) lines.append( xform_target_command.format( scale_factor=b_ratio, bra_basis_type="oscillator", bra_orbital_file=environ.orbitals_coul_filename(postfix), output_filename=environ.radial_olap_coul_filename(postfix))) # call radial-gen mcscript.call([environ.shell_filename("radial-gen")], mode=mcscript.CallMode.kSerial, input_lines=lines)
def evaluate_ob_observables(task, postfix=""): """Evaluate one-body observables with obscalc-ob. Arguments: task (dict): as described in module docstring postfix (string, optional): identifier to add to generated files """ work_dir = "work{:s}".format(postfix) # accumulate obscalc-ob input lines lines = [] # initial comment lines.append("# task: {}".format(task)) lines.append("") # indexing setup lines += [ "set-indexing {:s}".format(environ.orbitals_filename(postfix)), "set-output-file {:s}".format( environ.obscalc_ob_res_filename(postfix)), ] # set up operators for (operator_type, order) in task.get("ob_observables", []): lines.append("define-radial-source {:s}".format( environ.radial_me_filename(postfix, operator_type, order))) for species in ["p", "n"]: if operator_type == "M": # convenience definition for M observable lines.append("define-operator Dl({:s}) {:s}".format( species, environ.observable_me_filename(postfix, "Dl", order, species))) lines.append("define-operator Ds({:s}) {:s}".format( species, environ.observable_me_filename(postfix, "Ds", order, species))) else: lines.append("define-operator {:s}({:s}) {:s}".format( operator_type, species, environ.observable_me_filename(postfix, operator_type, order, species))) # get filenames for static densities and extract quantum numbers filenames = glob.glob(os.path.join(work_dir, "mfdn.statrobdme.*")) regex = re.compile( # directory prefix r"{}".format(os.path.join(work_dir, "")) + # prolog r"mfdn\.statrobdme" # sequence number r"\.seq(?P<seq>\d{3})" # 2J r"\.2J(?P<twoJ>\d{2})" # parity (v14 only) r"(\.p(?P<g>\d))?" # n r"\.n(?P<n>\d{2})" # 2T r"\.2T(?P<twoT>\d{2})") conversions = { "seq": int, "twoJ": int, "g": lambda x: int(x) if x is not None else 0, "n": int, "twoT": int } statrobdme_files = [] for filename in filenames: match = regex.match(filename) if match is None: print(regex) raise ValueError("bad statrobdme filename: {}".format(filename)) info = match.groupdict() # convert fields for key in info: conversion = conversions[key] info[key] = conversion(info[key]) statrobdme_files.append( mcscript.utils.dict_union(info, {"filename": filename})) # sort states by sequence number statrobdme_files.sort(key=lambda item: item["seq"]) for statrobdme_file in statrobdme_files: lines.append( "define-static-densities {twoJ:d} {g:d} {n:d} {filename:s} {info_filename:s}" .format(info_filename=os.path.join(work_dir, "mfdn.rppobdme.info"), **statrobdme_file)) # define-transition-densities 2Jf gf nf 2Ji gi fi robdme_info_filename robdme_filename # get filenames for static densities and extract quantum numbers filenames = glob.glob(os.path.join(work_dir, "mfdn.robdme.*")) regex = re.compile(r"{}".format(os.path.join(work_dir, "")) + # prolog r"mfdn\.robdme" # final sequence number r"\.seq(?P<seqf>\d{3})" # final 2J r"\.2J(?P<twoJf>\d{2})" # final parity (v14 only) r"(\.p(?P<gf>\d))?" # final n r"\.n(?P<nf>\d{2})" # final 2T r"\.2T(?P<twoTf>\d{2})" # initial sequence number r"\.seq(?P<seqi>\d{3})" # initial 2J r"\.2J(?P<twoJi>\d{2})" # initial parity (v14 only) r"(\.p(?P<gi>\d))?" # initial n r"\.n(?P<ni>\d{2})" # inital 2T r"\.2T(?P<twoTi>\d{2})") conversions = { "seqf": int, "twoJf": int, "gf": lambda x: int(x) if x is not None else 0, "nf": int, "twoTf": int, "seqi": int, "twoJi": int, "gi": lambda x: int(x) if x is not None else 0, "ni": int, "twoTi": int } robdme_files = [] for filename in filenames: match = regex.match(filename) if match is None: raise ValueError("bad statrobdme filename format") info = match.groupdict() # convert fields for key in info: conversion = conversions[key] info[key] = conversion(info[key]) if "gf" not in info: info["gf"] = 0 if "gi" not in info: info["gi"] = 0 robdme_files.append( mcscript.utils.dict_union(info, {"filename": filename})) # sort by sequence number of final state, then sequence number of initial state robdme_files.sort(key=lambda item: (item["seqf"], item["seqi"])) for robdme_file in robdme_files: lines.append( "define-transition-densities {twoJf:d} {gf:d} {nf:d} {twoJi:d} {gi:d} {ni:d} {filename:s} {info_filename:s}" .format(info_filename=os.path.join(work_dir, "mfdn.rppobdme.info"), **robdme_file)) # ensure trailing line lines.append("") # write input file mcscript.utils.write_input(environ.obscalc_ob_filename(postfix), input_lines=lines, verbose=False) # invoke em-gen mcscript.call([environ.shell_filename("obscalc-ob")], input_lines=lines, mode=mcscript.CallMode.kSerial) # copy results out (if in multi-task run) if (mcscript.task.results_dir is not None): descriptor = task["metadata"]["descriptor"] print("Saving basic output files...") work_dir = "work{:s}".format(postfix) filename_prefix = "{:s}-obscalc-{:s}{:s}".format( mcscript.parameters.run.name, descriptor, postfix) res_filename = "{:s}.res".format(filename_prefix) obscalc_dir = os.path.join(mcscript.task.results_dir, "obscalc") mcscript.utils.mkdir(obscalc_dir, exist_ok=True) mcscript.call([ "cp", "--verbose", environ.obscalc_ob_res_filename(postfix), os.path.join(obscalc_dir, res_filename) ])
import os import mcscript mcscript.init() print(64*"-") print("Python's environment (os.environ):") for (variable,value) in sorted(os.environ.items()): print("{}={}".format(variable,value)) print() print(64*"-") print("Local invocation of env:") mcscript.call(["env"],mode=mcscript.CallMode.kLocal) print() print(64*"-") print("Invocation of env as serial compute code:") mcscript.call(["env"],mode=mcscript.CallMode.kSerial) print() print(64*"-") print("Invocation of env as hybrid compute code:") mcscript.call(["env"],mode=mcscript.CallMode.kHybrid) print() ################################################################ # termination ################################################################
""" import mcscript mcscript.init() ################################################################## # main body ################################################################## mcscript.call( ["cat"], input_lines=[ "", "Dear World,", "", " Hello!", "", "Your faithful script,", # note use of run parameters from mcscript.parameters.run mcscript.parameters.run.name ] ) ################################################################ # termination ################################################################ mcscript.termination()
input_lines=[ "", "Dear World,", "", " Hello!", "", "Your faithful script,", # note use of run parameters from mcscript.parameters.run mcscript.parameters.run.name ] ) # example of running an executable # # Note that mcscript.call is a wrapper to the subprocess # package, but does a lot more... It generates logging output, it # checks the return code and generates an exception on failure # (i.e., a nonzero return), it can provide input lines to the code # via standard input (optional parameter input_lines), and various # other possibilities depending on the optional parameters. # # See the docstring for mcscript.utils.call for further information. mcscript.call(["/bin/cat","hello.txt"]) ################################################################ # termination ################################################################ mcscript.termination()