1 // ENGINE.H : the "engine" base class for computation engine classes.
2 
3 // Copyright (C) 1998 Tommi Hassinen.
4 
5 // This package is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 
10 // This package is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 
15 // You should have received a copy of the GNU General Public License
16 // along with this package; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 /*################################################################################################*/
20 
21 #ifndef ENGINE_H
22 #define ENGINE_H
23 
24 #include "libghemicaldefine.h"
25 
26 class setup;
27 
28 struct ecomp_store;
29 
30 class engine;
31 
32 class engine_bp;	// boundary potential
33 class engine_pbc;	// periodic boundary conditions
34 
35 class number_density_evaluator;
36 class radial_density_function_evaluator;
37 
38 /*################################################################################################*/
39 
40 class atom;	// atom.h
41 class bond;	// bond.h
42 
43 class model;	// model.h
44 
45 #include <stdlib.h>
46 
47 #include <vector>
48 using namespace std;
49 
50 #include "typedef.h"
51 
52 /*################################################################################################*/
53 
54 /// The setup class is used to define the submodel boundaries in the model.
55 /** There can be only a single setup object for each model object.
56 The setup object will create the engine objects. */
57 
58 class setup
59 {
60 	private:
61 
62 	model * mdl;
63 
64 	protected:
65 
66 	engine * current_eng;
67 	i32s current_eng_index;
68 
69 	bool has_setup_tables;
70 
71 	// the global tables.
72 	// ^^^^^^^^^^^^^^^^^^
73 
74 	atom ** atmtab; i32s natm;
75 
76 	// the local tables.
77 	// ^^^^^^^^^^^^^^^^^
78 
79 	atom ** qm_atmtab; i32s qm_natm;
80 	bond ** qm_bndtab; i32s qm_nbnd;
81 
82 	atom ** mm_atmtab; i32s mm_natm;
83 	bond ** mm_bndtab; i32s mm_nbnd;
84 
85 	bond ** boundary_bndtab; i32s boundary_nbnd;
86 
87 	atom ** sf_atmtab; i32s sf_natm;
88 
89 	public:
90 
91 	setup(model *);
92 	virtual ~setup(void);
93 
GetModel(void)94 	model * GetModel(void) { return mdl; }
95 
HasSetupTables(void)96 	bool HasSetupTables(void) { return has_setup_tables; }
97 
98 	// access to global tables.
99 	// ^^^^^^^^^^^^^^^^^^^^^^^^
100 
GetAtoms(void)101 	atom ** GetAtoms(void) { return atmtab; }
GetAtomCount(void)102 	i32s GetAtomCount(void) { return natm; }
103 
104 	// access to local tables.
105 	// ^^^^^^^^^^^^^^^^^^^^^^^
106 
GetQMAtoms(void)107 	atom ** GetQMAtoms(void) { return qm_atmtab; }
GetQMAtomCount(void)108 	i32s GetQMAtomCount(void) { return qm_natm; }
GetQMBonds(void)109 	bond ** GetQMBonds(void) { return qm_bndtab; }
GetQMBondCount(void)110 	i32s GetQMBondCount(void) { return qm_nbnd; }
111 
GetMMAtoms(void)112 	atom ** GetMMAtoms(void) { return mm_atmtab; }
GetMMAtomCount(void)113 	i32s GetMMAtomCount(void) { return mm_natm; }
GetMMBonds(void)114 	bond ** GetMMBonds(void) { return mm_bndtab; }
GetMMBondCount(void)115 	i32s GetMMBondCount(void) { return mm_nbnd; }
116 
GetBoundaryBonds(void)117 	bond ** GetBoundaryBonds(void) { return boundary_bndtab; }
GetBoundaryBondCount(void)118 	i32s GetBoundaryBondCount(void) { return boundary_nbnd; }
119 
GetSFAtoms(void)120 	atom ** GetSFAtoms(void) { return sf_atmtab; }
GetSFAtomCount(void)121 	i32s GetSFAtomCount(void) { return sf_natm; }
122 
GetCurrentEngine(void)123 	engine * GetCurrentEngine(void) { return current_eng; }
124 
GetCurrEngIndex(void)125 	i32s GetCurrEngIndex(void) { return current_eng_index; }
SetCurrEngIndex(i32s index)126 	void SetCurrEngIndex(i32s index) { current_eng_index = index; }		// only file operations etc should use this...
127 
128 	virtual void UpdateAtomFlags(void) = 0;
129 
130 	void DiscardSetupInfo(void);
131 	void UpdateSetupInfo(void);
132 
133 	// functions for obtaining information about available eng objects.
134 	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
135 
136 	virtual i32u GetEngineCount(void) = 0;
137 	virtual i32u GetEngineIDNumber(i32u) = 0;		// this is not much used yet. for saving eng info in files?!?!?!
138 	virtual const char * GetEngineName(i32u) = 0;
139 	virtual const char * GetClassName_lg(void) = 0;		// also see model::AddAtom_lg() ; this is an another Win32 API conflict...
140 
141 	void CreateCurrentEngine(void);				///< Create the current_eng object for plotting...
142 	void DiscardCurrentEngine(void);
143 
144 	virtual engine * CreateEngineByIndex(i32u) = 0;		///< Create an engine object.
145 	engine * CreateEngineByIDNumber(i32u);
146 };
147 
148 /*################################################################################################*/
149 
150 typedef double ecomp_data[5];
151 
152 #define ECOMP_DATA_IND_B_bs	0	// bond stretching
153 #define ECOMP_DATA_IND_B_ab	1	// angle bending
154 #define ECOMP_DATA_IND_B_ti	2	// torsion + imp.tor. interactions
155 #define ECOMP_DATA_IND_NB_lj	3	// nonbonded interactions
156 #define ECOMP_DATA_IND_NB_es	4	// electrostatic interactions
157 
158 /// A virtual base class for computations.
159 
160 /** The engine classes are used to implement the computational details of various models
161 (like different quantum-mechanical models and molecular mechanics models).
162 
163 The engine class will store it's own atom coordinates.
164 
165 When we want to compute something, we create an instance of some suitable engine-class using
166 our setup-class. The engine-class will copy that information it needs, and calculates those results
167 it is supposed to calculate. If we calculate some useful results that change our original system,
168 we can copy those results back to our model-class.
169 
170 The setup class will create two kinds of atom and bond tables using contents of the model object;
171 one (global) contains all atoms/bonds, and the others (local ones) contain only those atoms/bonds
172 that belong to a submodel (say, QM or MM submodel).
173 
174 Since there is, for example, only one table for coordinates and derivatives at the engine base class,
175 the different derived engine classes must create a suitable lookup table that maps the local tables
176 back to the global one. */
177 
178 // here are some common error/warning messages:
179 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
180 
181 #define CONSTRAINTS_NOT_SUPPORTED "Sorry ; constraints are not yet supported by this engine class."
182 
183 class engine
184 {
185 	private:
186 
187 	setup * stp;
188 
189 	protected:
190 
191 	i32s natm;
192 
193 	f64 * crd;
194 
195 	f64 energy;
196 
197 // add atom::ecomp_grp_ind ; define/register the new groups in the model object (and save them in files).
198 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
199 // ecomp_grp		vector<const char *>	<- in model!!!
200 // ecomp_ngrp		int			<- in engine!!!
201 // ecomp_data		double *
202 // ecomp_map		int *			<- make the size (n*n).
203 //////////////////////////////////////////////////////////////////////////////
204 //	f64 E_solute;
205 //	f64 E_solvent;
206 //	f64 E_solusolv;
207 //////////////////////////////////////////////////////////////////////////////
208 
209 	f64 * d1;	// GetD1() ???
210 	f64 * d2;	// GetD2() ???
211 
212 	f64 virial[3];
213 
214 	bool update_neighbor_list;
215 
216 	int ECOMPcycles;
217 
218 	int ECOMPstore_size;
219 	ecomp_data * ECOMPstore;
220 
221 	friend void CopyCRD(model *, engine *, i32u);
222 	friend void CopyCRD(engine *, model *, i32u);
223 
224 	friend class model;
225 
226 	friend class geomopt;
227 
228 	friend class moldyn;
229 	friend class moldyn_langevin;
230 
231 	friend class sasaeval;
232 
233 	friend class random_search;
234 	friend class systematic_search;
235 	friend class monte_carlo_search;
236 	friend class transition_state_search;
237 	friend class stationary_state_search;
238 
239 	public:
240 
241 	engine(setup *, i32u);
242 	virtual ~engine(void);
243 
GetSetup(void)244 	setup * GetSetup(void) { return stp; }
GetAtomCount(void)245 	i32s GetAtomCount(void) { return natm; }
246 
247 	void Check(i32u);			///< This is for debugging; will compare the computed gradient to a numerical one.
248 	f64 GetGradientVectorLength(void);	///< This calculates the gradient vector length (using the d1 array).
249 
250 	void ScaleCRD(f64, f64, f64);
251 
252 /**	This will request an update for the NB-term list (neighbor list) at the next
253 	energy evaluation.
254 */
RequestNeighborListUpdate(void)255 	void RequestNeighborListUpdate(void) { update_neighbor_list = true; }
256 
257 	virtual void Compute(i32u, bool = false) = 0;	///< Will compute the energy, and the gradient if needed.
258 
259 	virtual void DoSHAKE(bool);	///< This is an optional method that contains some SHAKE-like corrections to atomic coordinates ; is called before calculating forces in MD.
260 
261 	// these are added to make it easier to set torsional constraints (like for plotting etc).
262 	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
263 
264 	virtual bool SetTorsionConstraint(atom *, atom *, atom *, atom *, f64, f64, bool) = 0;
265 	virtual bool RemoveTorsionConstraint(atom *, atom *, atom *, atom *) = 0;
266 
267 	// these are mainly for drawing energy level diagrams...
268 	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
269 
270 	virtual i32s GetOrbitalCount(void) = 0;
271 	virtual f64 GetOrbitalEnergy(i32s) = 0;
272 
273 	virtual i32s GetElectronCount(void) = 0;
274 
275 	// these are for plotting purposes...
276 	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
277 
278 	virtual void SetupPlotting(void) = 0;
279 
280 	virtual fGL GetVDWSurf(fGL *, fGL *) = 0;
281 
282 	virtual fGL GetESP(fGL *, fGL *) = 0;
283 
284 	virtual fGL GetElDens(fGL *, fGL *) = 0;
285 
286 	virtual fGL GetOrbital(fGL *, fGL *) = 0;
287 	virtual fGL GetOrbDens(fGL *, fGL *) = 0;
288 
289 	// these are to take data out for external apps etc...
290 	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
291 
292 	f64 GetEnergy(void);	///< Compute() must be called before this one!
293 
294 	f64 ReadCRD(int);
295 
296 	protected:
297 
298 	void ecomp_AddCycle(void);				// called in every energy evaluation!
299 	void ecomp_AddStore2(int, int, int, double);		// called in every energy evaluation!
300 	void ecomp_AddStoreX(vector<int> &, int, double);	// called in every energy evaluation!
301 
302 	public:
303 
304 	void ecomp_Reset(void);
305 	double ecomp_ReadStore(int, int, int);
306 };
307 
308 /*################################################################################################*/
309 
310 fGL value_VDWSurf(engine *, fGL *, fGL *);
311 fGL value_ESP(engine *, fGL *, fGL *);
312 fGL value_ElDens(engine *, fGL *, fGL *);
313 fGL value_Orbital(engine *, fGL *, fGL *);
314 fGL value_OrbDens(engine *, fGL *, fGL *);
315 
316 void CopyCRD(model *, engine *, i32u);
317 void CopyCRD(engine *, model *, i32u);
318 
319 /*################################################################################################*/
320 
321 /// A base engine class for systems that utilize a boundary potential.
322 
323 class engine_bp : virtual public engine
324 {
325 	protected:
326 
327 	bool use_bp;
328 	f64 bp_rad_solute; f64 bp_fc_solute;
329 	f64 bp_rad_solvent; f64 bp_fc_solvent;
330 
331 	number_density_evaluator * nd_eval;
332 	radial_density_function_evaluator * rdf_eval;
333 
334 	friend class model;
335 
336 	friend class number_density_evaluator;
337 	friend class radial_density_function_evaluator;
338 
339 	public:
340 
341 	engine_bp(setup *, i32u);
342 	virtual ~engine_bp(void);
343 };
344 
345 /*################################################################################################*/
346 
347 /// A base engine class for systems with periodic boundary conditions.
348 
349 class engine_pbc : virtual public engine
350 {
351 	protected:
352 
353 	f64 box_HALFdim[3];
354 
355 	i32s num_mol;
356 	i32s * mrange;
357 
358 // TODO : how to use RDF-evaluator also here???
359 
360 	friend class model;
361 	friend class moldyn;
362 
363 	public:
364 
365 	engine_pbc(setup *, i32u);
366 	virtual ~engine_pbc(void);
367 
368 /**	This will check that molecules have not escaped from the periodic box.
369 	If we doing geometry optimization or molecular dynamics for periodic models,
370 	we should remember to call this at suitable intervals...
371 */
372 	void CheckLocations(void);
373 };
374 
375 /*################################################################################################*/
376 
377 /// Calculates "number density" of solvent molecules -> engine::bp_center.
378 
379 class number_density_evaluator
380 {
381 	protected:
382 
383 	engine_bp * eng;
384 	bool linear;
385 
386 	i32s classes;
387 	f64 * upper_limits;
388 	f64 * class_volumes;
389 
390 	i32u cycles;
391 	i32u * counts;
392 
393 	public:
394 
395 	number_density_evaluator(engine_bp *, bool, i32s);
396 	~number_density_evaluator(void);
397 
398 	private:
399 
400 	void UpdateClassLimits(void);
401 	void ResetCounters(void);
402 
403 	public:
404 
405 	void PrintResults(ostream &);
406 
AddCycle(void)407 	inline void AddCycle(void)
408 	{
409 		cycles++;
410 	}
411 
AddValue(f64 p1)412 	inline void AddValue(f64 p1)
413 	{
414 		i32s index = 0;
415 		while (index < classes)
416 		{
417 			if (p1 >= upper_limits[index]) index++;
418 			else break;
419 		}
420 
421 		counts[index]++;
422 	}
423 };
424 
425 /*################################################################################################*/
426 
427 /// Calculates radial density function of solvent molecules (in practive O-O distances of H2O) -> engine::bp_center.
428 
429 class radial_density_function_evaluator
430 {
431 	protected:
432 
433 	engine_bp * eng;
434 
435 	i32s classes;
436 	f64 graph_begin;
437 	f64 graph_end;
438 	f64 count_begin;
439 	f64 count_end;
440 
441 	f64 * upper_limits;
442 	f64 * class_volumes;
443 
444 	i32u cycles;
445 	i32u * counts;
446 
447 	friend class eng1_mm_tripos52_nbt_bp;
448 	friend class eng1_mm_default_nbt_bp;
449 	friend class eng1_sf;
450 
451 	public:
452 
453 	radial_density_function_evaluator(engine_bp *, i32s, f64, f64, f64 = -1.0, f64 = -1.0);
454 	~radial_density_function_evaluator(void);
455 
456 	private:
457 
458 	void ResetCounters(void);
459 
460 	public:
461 
462 	void PrintResults(ostream &);
463 
AddCycle(void)464 	inline void AddCycle(void)
465 	{
466 		cycles++;
467 	}
468 
AddValue(f64 p1)469 	inline void AddValue(f64 p1)
470 	{
471 		if (p1 < graph_begin) return;
472 		if (p1 >= graph_end) return;
473 
474 		i32s index = 0;
475 		while (index < classes)
476 		{
477 			if (p1 >= upper_limits[index]) index++;
478 			else break;
479 		}
480 
481 		counts[index]++;
482 	}
483 };
484 
485 /*################################################################################################*/
486 
487 #endif	// ENGINE_H
488 
489 // eof
490