def start_server(self):

        working_queue = Queue()
        output_queue = Queue()
        # TODO Safe/guaranteed exit condition?
        while True:
            # Start by getting the next jobs
            working_queue = self.get_next_jobs(working_queue)

            if not working_queue.qsize():
                return td_api.collect_lowest_energies(self.td_state)

            # Now we know the grid point to run set up the optimiser class
            processors = []
            for i in range(4):
                p = Process(target=self.optimise_grid_point,
                            args=(working_queue, output_queue))
                processors.append(p)
                p.start()

            for p in processors:
                p.join()

            # print('waiting for all jobs to finish')

            self.update_state(output_queue)
Beispiel #2
0
    def run_torsiondrive_scan(self):
        """
        Run torsiondrive scan in the following steps:
        1. Create json input for torsiondrive
        2. Send the json input dictionary to td_api.next_jobs_from_state(), get the next set of jobs
        3. If there are no jobs needed, finish and return the lowest energy on each dihedral grid
        4. If there are new jobs, run them with geomeTRIC.run_json.
        5. Collect the results and put them into new json input dictionary
        6. Go back to step 2.
        """

        # step 1
        td_state = td_api.create_initial_state(
            dihedrals=self.dihedrals,
            grid_spacing=self.grid_spacing,
            elements=self.elements,
            init_coords=self.init_coords,
            dihedral_ranges=self.dihedral_ranges,
            energy_decrease_thresh=self.energy_decrease_thresh,
            energy_upper_limit=self.energy_upper_limit,
        )

        while True:
            # step 2
            next_jobs = td_api.next_jobs_from_state(td_state, verbose=True)

            # step 3
            if len(next_jobs) == 0:
                print("torsiondrive Scan Finished")
                return td_api.collect_lowest_energies(td_state)

            # step 4
            job_results = collections.defaultdict(list)
            for grid_id_str, job_geo_list in next_jobs.items():
                for job_geo in job_geo_list:
                    dihedral_values = td_api.grid_id_from_string(grid_id_str)

                    # Run geometric
                    geometric_input_dict = self.make_geomeTRIC_input(
                        dihedral_values, job_geo)
                    geometric_output_dict = geometric.run_json.geometric_run_json(
                        geometric_input_dict)

                    # Pull out relevevant data
                    final_result = geometric_output_dict['trajectory'][-1]
                    final_geo = final_result['molecule']['geometry']
                    final_energy = final_result['properties']['return_energy']

                    # Note: the results should be appended in the same order as in the inputs
                    # It's not a problem here when running serial for loop
                    job_results[grid_id_str].append(
                        (job_geo, final_geo, final_energy))

            # step 5
            td_api.update_state(td_state, job_results)
Beispiel #3
0
    def _collect_results(self, td_state: Dict[str, Any],
                         molecule: "Ligand") -> "Ligand":
        """
        After the torsiondrive has been completed collect the results and pack them into the ligand.
        """
        # torsiondrive will only give us the lowest energy for each grid point
        # we have to then work out what the final geometry is from this
        optimised_energies = td_api.collect_lowest_energies(td_state=td_state)
        final_grid = td_state["grid_status"]
        # make a torsiondrive data store assuming 1D only
        torsion_data = TorsionDriveData(
            grid_spacing=self.grid_spacing,
            dihedral=td_state["dihedrals"][0],
            torsion_drive_range=td_state["dihedral_ranges"][0],
        )
        # now grab each grid point in sorted order
        for (
                angle,
                energy,
        ) in sorted(optimised_energies.items()):
            # grab all optimisation done at this angle
            optimisations = final_grid[str(angle[0])]
            # loop over each result and check if the energy matches the lowest
            # results -> (initial geometry, final geometry, final energy)
            for result in optimisations:
                if result[-1] == energy:
                    grid_data = TorsionData(
                        angle=angle[0],
                        geometry=np.array(result[1]) * constants.BOHR_TO_ANGS,
                        energy=energy,
                    )
                    torsion_data.add_grid_point(grid_data=grid_data)
                    break
        # validate the data
        torsion_data.validate_angles()
        # dump to file (qdata.txt and scan.xyz)
        export_torsiondrive_data(molecule=molecule, tdrive_data=torsion_data)
        # dump the qubekit torsion data to file
        torsion_data.to_file("scan_data.json")
        # save to mol
        molecule.add_qm_scan(scan_data=torsion_data)
        # dump the torsiondrive state to file
        self._dump_state(td_state=td_state)
        # now remove all temp folders
        for f in os.listdir("."):
            if os.path.isdir(f):
                shutil.rmtree(f, ignore_errors=True)

        return molecule