def compute_elec_struct(self,zbackprop): if not zbackprop: cbackprop = "" else: cbackprop = "backprop_" istate = self.get_istate() nstates = self.get_numstates() # initialize electronic_phases if not present if not hasattr(self,'electronic_phases'): self.electronic_phases = np.ones(nstates) if not hasattr(self,'backprop_electronic_phases'): self.backprop_electronic_phases = np.ones(nstates) exec("pos = self.get_" + cbackprop + "positions()") pos_list = pos.tolist() TC = TCProtobufClient(host='localhost', port=54321) base_options = self.get_tc_options() base_options["castarget"] = istate TC.update_options(**base_options) TC.connect() # Check if the server is available avail = TC.is_available() #print "TCPB Server available: {}".format(avail) # Write CI vectors and orbitals for initial guess and overlaps cwd = os.getcwd() # Gradient calculation # here we call TC once for energies and once for the gradient # will eventually be replaced by a more efficient interface options = {} results = TC.compute_job_sync("energy", pos_list, "bohr", **options) #print results e = np.zeros(nstates) e[0] = results['energy'] results = TC.compute_job_sync("gradient", pos_list, "bohr", **options) #print results f = np.zeros((nstates,self.numdims)) #print "results['gradient'] ", results['gradient'] #print "results['gradient'].flatten() ", results['gradient'].flatten() f[self.istate,:] = -1.0 * results['gradient'].flatten() exec("self.set_" + cbackprop + "energies(e)") exec("self.set_" + cbackprop + "forces(f)")
def compute(self, input_model: "AtomicInput", config: "TaskConfig" = None) -> "AtomicResult": """ Submit AtomicInput to TeraChem running in "server mode" """ self.found(raise_error=True) from tcpb.tcpb import TCProtobufClient with TCProtobufClient(host=os.getenv("TERACHEM_PBS_HOST"), port=int(os.getenv("TERACHEM_PBS_PORT"))) as client: return client.compute(input_model)
def compute_electronic_overlap(self, pos1, civec1, orbs1, pos2, civec2, orbs2): orbout1 = os.path.join(cwd, "c0.1") orbs1.tofile(orbout1) orbout2 = os.path.join(cwd, "c0.2") orbs2.tofile(orbout2) civecout1 = os.path.join(cwd, "civec.1") civec1.tofile(civecout1) civecout2 = os.path.join(cwd, "civec.2") civec2.tofile(civecout2) TC = TCProtobufClient(host='localhost', port=self.tc_port) options = self.get_tc_options() # TC.update_options(**base_options) TC.connect() # Check if the server is available avail = TC.is_available() options["geom2"] = (0.529177 * pos2).tolist() options["cvec1file"] = civecfilename options["cvec2file"] = civecout options["orb1afile"] = orbout2 options["orb2afile"] = orbout results2 = TC.compute_job_sync("ci_vec_overlap", pos1.tolist(), "bohr", **options) S = results2['ci_overlap'] return S
def found(raise_error: bool = False) -> bool: """Whether TeraChemPBS harness is ready for operation. Parameters ---------- raise_error: bool Passed on to control negative return between False and ModuleNotFoundError raised. Returns ------- bool If tcpb package is found and server available, returns True. If raise_error is False and tcpb package missing and/or server us unavailable, returns False. If raise_error is True and tcpb package missing and/or server us unavailable, the error message is raised. """ tcpb_pkg_available = which_import( "tcpb", return_bool=True, raise_error=raise_error, raise_msg="TeraChem protobuf client package (tcpb) not found. Please install tcpb>=0.7.0.", ) if not tcpb_pkg_available: return False from tcpb.exceptions import ServerError from tcpb.tcpb import TCProtobufClient try: with TCProtobufClient( host=os.getenv("TERACHEM_PBS_HOST"), port=int(os.getenv("TERACHEM_PBS_PORT")) ) as client: return client.is_available() except TypeError as e: # TERACHEM_PBS_HOST/PORT environment variables unset msg = "Environment variables 'TERACHEM_PBS_HOST' and 'TERACHEM_PBS_PORT' must be set!" logger.error(msg) if raise_error: raise ValueError(msg) from e except ServerError as e: msg = ( f"Unable to connect to TeraChem server at " f"{os.getenv('TERACHEM_PBS_HOST')}:{os.getenv('TERACHEM_PBS_PORT')}" ) logger.error(msg) if raise_error: raise OSError(msg) from e return False
def compute_elec_struct(self, zbackprop): """Subroutine that calls electronic structure calculation in Terachem through tcpb interface. This version is compatible with tcpb-0.5.0 When running multiple job on the same server we need to make sure we use different ports for Terachem server. Every trajectory or centroid has a port variable, which is passed along to children. Needs to be provided at input in start file as a traj_param""" if not zbackprop: cbackprop = "" else: cbackprop = "backprop_" istate = self.get_istate() nstates = self.get_numstates() # initialize electronic_phases if not present if not hasattr(self, 'electronic_phases'): self.electronic_phases = np.ones(nstates) if not hasattr(self, 'backprop_electronic_phases'): self.backprop_electronic_phases = np.ones(nstates) exec("pos = self.get_" + cbackprop + "positions()") pos_list = pos.tolist() TC = TCProtobufClient(host='localhost', port=self.tc_port) base_options = self.get_tc_options() options = base_options options["castarget"] = istate # TC.update_options(**base_options) TC.connect() # Check if the server is available avail = TC.is_available() # print "TCPB Server available: {}".format(avail) # Write CI vectors and orbitals for initial guess and overlaps cwd = os.getcwd() if hasattr(self, 'civecs'): civecout = os.path.join(cwd, "CIvecs.Singlet.old") orbout = os.path.join(cwd, "c0.old") orbout_t = os.path.join(cwd, "c0_t.old") eval("self.get_" + cbackprop + "civecs()").tofile(civecout) eval("self.get_" + cbackprop + "orbs()").tofile(orbout) n = int(math.floor(math.sqrt(self.get_norbs()))) ((np.resize(eval("self.get_" + cbackprop + "orbs()"), (n, n)).T).flatten()).tofile(orbout_t) # print "old civecs", eval("self.get_" + cbackprop + "civecs()") # print "old orbs", eval("self.get_" + cbackprop + "orbs()") zolaps = True if ("casscf" in self.tc_options): if (self.tc_options["casscf"] == "yes"): options["caswritevecs"] = "yes" options["casguess"] = orbout_t else: options["caswritevecs"] = "yes" options["guess"] = orbout else: options["caswritevecs"] = "yes" options["guess"] = orbout else: zolaps = False options["caswritevecs"] = "yes" # Gradient calculation # here we call TC once for energies and once for the gradient # will eventually be replaced by a more efficient interface results = TC.compute_job_sync("energy", pos_list, "bohr", **options) # print results e = np.zeros(nstates) e = results['energy'] # e[:] = results['energy'][:] results = TC.compute_job_sync("gradient", pos_list, "bohr", **options) # print results civecfilename = os.path.join(results['job_scr_dir'], "CIvecs.Singlet.dat") exec("self.set_" + cbackprop + "civecs(np.fromfile(civecfilename))") # print "new civecs", self.civecs # orbfilename = os.path.join(results['job_scr_dir'], "c0") orbfilename = results['orbfile'] exec("self.set_" + cbackprop + "orbs((np.fromfile(orbfilename)).flatten())") self.set_norbs(self.get_orbs().size) # BGL transpose hack is temporary n = int(math.floor(math.sqrt(self.get_norbs()))) clastchar = orbfilename.strip()[-1] # print "n", n # print "clastchar", clastchar if clastchar != '0': tmporbs = eval("self.get_" + cbackprop + "orbs()") exec("self.set_" + cbackprop + "orbs(((tmporbs.reshape((n,n))).T).flatten())") # end transpose hack # print "new orbs", eval("self.get_" + cbackprop + "orbs()") orbout2 = os.path.join(cwd, "c0.new") eval("self.get_" + cbackprop + "orbs()").tofile(orbout2) self.set_ncivecs(self.get_civecs().size) f = np.zeros((nstates, self.numdims)) # print "results['gradient'] ", results['gradient'] # print "results['gradient'].flatten() ", results['gradient'].flatten() f[self.istate, :] = -1.0 * results['gradient'].flatten() exec("self.set_" + cbackprop + "energies(e)") exec("self.set_" + cbackprop + "forces(f)") # if False: if zolaps: exec("pos2 = self.get_" + cbackprop + "prev_wf_positions_in_angstrom()") # print 'pos2.tolist()', pos2.tolist() # print 'civecfilename', civecfilename # print 'civecout', civecout # print 'orbfilename', orbfilename # print 'orbout2', orbout2 # print 'orbout', orbout options = base_options options["geom2"] = pos2.tolist() options["cvec1file"] = civecfilename options["cvec2file"] = civecout options["orb1afile"] = orbout2 options["orb2afile"] = orbout # print 'pos_list', pos_list results2 = TC.compute_job_sync("ci_vec_overlap", pos_list, "bohr", **options) # print "results2", results2 S = results2['ci_overlap'] # print "S before phasing ", S # phasing electronic overlaps for jstate in range(nstates): S[:, jstate] *= eval("self.get_" + cbackprop + "electronic_phases()[jstate]") S[jstate, :] *= eval("self.get_" + cbackprop + "electronic_phases()[jstate]") for jstate in range(nstates): if S[jstate, jstate] < 0.0: ep = eval("self.get_" + cbackprop + "electronic_phases()") ep[jstate] *= -1.0 exec("self.set_" + cbackprop + "electronic_phases(ep)") # I'm not sure if this line is right, but it seems to be working S[jstate, :] *= -1.0 # print "S", S exec("self.set_" + cbackprop + "S_elec_flat(S.flatten())") W = np.zeros((2, 2)) W[0, 0] = S[istate, istate] tdc = np.zeros(nstates) for jstate in range(nstates): if istate == jstate: tdc[jstate] = 0.0 else: W[1, 0] = S[jstate, istate] W[0, 1] = S[istate, jstate] W[1, 1] = S[jstate, jstate] tdc[jstate] = self.compute_tdc(W) # print "tdc", tdc[jstate] # tmp=self.compute_tdc(W) # tdc = np.zeros(self.numstates) # if self.istate == 1: # jstate = 0 # else: # jstate = 1 # tdc[jstate] = tmp # # print "tdc2 ", tdc exec("self.set_" + cbackprop + "timederivcoups(tdc)") else: exec("self.set_" + cbackprop + "timederivcoups(np.zeros(self.numstates))") exec("self.set_" + cbackprop + "prev_wf_positions(pos)")
def test_atomic_input_to_job_input_cisco_casci_similarity(ethylene): """ Test that the new atomic_input_to_job_input function produces the same protobuf messages that Stefan's old method created """ # Dicts of options used according to Stefan's old methodology old_methodoloy_options = { "method": "hf", "basis": "6-31g**", "atoms": ethylene["atoms"], } keywords = { # base options "charge": 0, "spinmult": 1, "closed_shell": True, "restricted": True, "precision": "double", "convthre": 1e-8, "threall": 1e-20, # cisno options "cisno": "yes", "cisnostates": 2, "cisnumstates": 2, "closed": 7, "active": 2, "cassinglets": 2, "dcimaxiter": 100, } # Construct Geometry in bohr geom_angstrom = qcel.Datum("geometry", "angstrom", np.array(ethylene["geometry"])) geom_bohr = _round(geom_angstrom.to_units("bohr")) # Construct Molecule object m_ethylene = Molecule.from_data({ "symbols": ethylene["atoms"], "geometry": geom_bohr, "molecular_multiplicity": keywords["spinmult"], "molecular_charge": keywords["charge"], }) # Construct AtomicInput atomic_input = AtomicInput( molecule=m_ethylene, driver="energy", model={ "method": "hf", "basis": "6-31g**" }, keywords=keywords, ) # Create protobof JobInput using Stefan's old approach client = TCProtobufClient("host", 11111) stefan_style = client._create_job_input_msg( "energy", geom_bohr, "bohr", **{ **old_methodoloy_options, **keywords }) # Create protobuf JobInput using AtomicInput object job_input = atomic_input_to_job_input(atomic_input) assert job_input == stefan_style