1 /* NWChemMolecule.c */
2 /**********************************************************************************************************
3 Copyright (c) 2002-2013 Abdul-Rahman Allouche. All rights reserved
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 documentation files (the Gabedit), to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
8 and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9 
10   The above copyright notice and this permission notice shall be included in all copies or substantial portions
11   of the Software.
12 
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
14 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
15 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
16 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17 DEALINGS IN THE SOFTWARE.
18 ************************************************************************************************************/
19 
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <math.h>
23 
24 #include "../../Config.h"
25 #include "../Common/Global.h"
26 #include "../NWChem/NWChemTypes.h"
27 #include "../NWChem/NWChemGlobal.h"
28 #include "../NWChem/NWChemKeywords.h"
29 #include "../Geometry/GeomGlobal.h"
30 #include "../Geometry/GeomConversion.h"
31 #include "../Geometry/GeomXYZ.h"
32 #include "../Geometry/Fragments.h"
33 #include "../Geometry/DrawGeom.h"
34 #include "../Utils/Utils.h"
35 #include "../Utils/UtilsInterface.h"
36 #include "../Utils/Constants.h"
37 #include "../Utils/GabeditTextEdit.h"
38 #include "../Geometry/InterfaceGeom.h"
39 #include "../Common/Windows.h"
40 #include "../Utils/Constants.h"
41 #include "../Utils/AtomsProp.h"
42 #include "../Symmetry/MoleculeSymmetry.h"
43 #include "../Symmetry/MoleculeSymmetryInterface.h"
44 
45 /************************************************************************************************************/
46 static gint totalCharge = 0;
47 static gint spinMultiplicity=1;
48 /************************************************************************************************************/
getNWChemMultiplicity()49 gint getNWChemMultiplicity()
50 {
51 	return spinMultiplicity;
52 }
53 /************************************************************************************************************/
initNWChemMoleculeButtons()54 void initNWChemMoleculeButtons()
55 {
56 }
57 /************************************************************************************************************/
initNWChemMolecule()58 void initNWChemMolecule()
59 {
60 	nwchemMolecule.listOfAtoms = NULL;
61 	nwchemMolecule.totalNumberOfElectrons = 0;
62 	nwchemMolecule.numberOfValenceElectrons = 0;
63 	nwchemMolecule.numberOfAtoms = 0;
64 }
65 /************************************************************************************************************/
freeNWChemMolecule()66 void freeNWChemMolecule()
67 {
68 	static gboolean first = TRUE;
69 
70 	if(first)
71 	{
72 		initNWChemMolecule();
73 		first = FALSE;
74 		return;
75 	}
76 
77 	if(nwchemMolecule.listOfAtoms) g_free(nwchemMolecule.listOfAtoms);
78 	initNWChemMolecule();
79 }
80 /************************************************************************************************************/
setNWChemMoleculeFromSXYZ(gint nAtoms,gchar ** symbols,gdouble * X,gdouble * Y,gdouble * Z)81 static gint setNWChemMoleculeFromSXYZ(gint nAtoms, gchar** symbols, gdouble* X, gdouble* Y, gdouble* Z)
82 {
83 	gint n;
84 	NWChemAtom* atomList = NULL;
85 
86 	nwchemMolecule.listOfAtoms = NULL;
87 	nwchemMolecule.numberOfAtoms = 0;
88 	if(nAtoms<1) return 1;
89 
90 	nwchemMolecule.listOfAtoms = (NWChemAtom*)g_malloc(sizeof(NWChemAtom)*(nAtoms));
91 	if(nwchemMolecule.listOfAtoms==NULL) return -1;
92 
93 	nwchemMolecule.numberOfAtoms = nAtoms;
94 
95 	atomList = nwchemMolecule.listOfAtoms;
96 	for(n=0; n<nwchemMolecule.numberOfAtoms; n++)
97 	{
98 		atomList->position[0]  = X[n];
99 		atomList->position[1]  = Y[n];
100 		atomList->position[2]  = Z[n];
101 		atomList->symbol  = g_strdup(symbols[n]);
102 		atomList++;
103 	}
104 
105 	return 0;
106 }
107 /************************************************************************************************************/
setXYZFromGeomXYZ(gint i,gdouble * x,gdouble * y,gdouble * z)108 static void setXYZFromGeomXYZ(gint i, gdouble* x, gdouble* y, gdouble *z)
109 {
110   	if(!test(GeomXYZ[i].X))
111     		*x = get_value_variableXYZ(GeomXYZ[i].X);
112   	else
113     		*x = atof(GeomXYZ[i].X);
114   	if(!test(GeomXYZ[i].Y))
115     		*y = get_value_variableXYZ(GeomXYZ[i].Y);
116   	else
117     		*y = atof(GeomXYZ[i].Y);
118   	if(!test(GeomXYZ[i].Z))
119     		*z = get_value_variableXYZ(GeomXYZ[i].Z);
120   	else
121     		*z = atof(GeomXYZ[i].Z);
122 
123          if(Units==0)
124          {
125               *x *= BOHR_TO_ANG;
126               *y *= BOHR_TO_ANG;
127               *z *= BOHR_TO_ANG;
128          }
129 }
130 /************************************************************************************************************/
setNWChemMoleculeFromGeomXYZ()131 static gboolean setNWChemMoleculeFromGeomXYZ()
132 {
133 	gint i;
134 	gchar** symbols = NULL;
135 	gdouble* X = NULL;
136 	gdouble* Y = NULL;
137 	gdouble* Z = NULL;
138 	gint numberOfAtoms = NcentersXYZ;
139 
140 	if(numberOfAtoms<1) return FALSE;
141 
142 	symbols = (gchar**)g_malloc(sizeof(gchar*)*(numberOfAtoms));
143 
144 	if(symbols == NULL) return FALSE;
145 
146 	X = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
147 	if(X == NULL) return FALSE;
148 	Y = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
149 	if(Y == NULL) return FALSE;
150 	Z = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
151 	if(Z == NULL) return FALSE;
152 
153 	nwchemMolecule.totalNumberOfElectrons = 0;
154 	for(i=0; i<numberOfAtoms; i++)
155 	{
156 		SAtomsProp prop = prop_atom_get(GeomXYZ[i].Symb);
157 
158 		symbols[i] = g_strdup(GeomXYZ[i].Symb);
159 		setXYZFromGeomXYZ(i, &X[i] , &Y[i] , &Z[i]);
160 		nwchemMolecule.totalNumberOfElectrons += prop.atomicNumber;
161 	}
162 	nwchemMolecule.numberOfValenceElectrons = nwchemMolecule.totalNumberOfElectrons;
163 	setNWChemMoleculeFromSXYZ(numberOfAtoms, symbols, X, Y, Z);
164 
165 	for (i=0;i<(gint)NcentersXYZ;i++) g_free( symbols[i]);
166 	g_free( symbols);
167 	g_free(X);
168 	g_free(Y);
169 	g_free(Z);
170 	return TRUE;
171 }
172 /************************************************************************************************************/
setNWChemMoleculeFromGeomZMatrix()173 static gboolean setNWChemMoleculeFromGeomZMatrix()
174 {
175 	iprogram=PROG_IS_NWCHEM;
176 	if(!zmat_to_xyz()) return FALSE;
177 	delete_dummy_atoms();
178 	/* conversion_zmat_to_xyz();*/
179 	return setNWChemMoleculeFromGeomXYZ();
180 }
181 /************************************************************************************************************/
setNWChemMolecule()182 gboolean setNWChemMolecule()
183 {
184 	freeNWChemMolecule();
185 	if(MethodeGeom==GEOM_IS_XYZ && setNWChemMoleculeFromGeomXYZ()) return TRUE;
186 	if(setNWChemMoleculeFromGeomZMatrix()) return TRUE;
187 	return FALSE;
188 }
189 /************************************************************************************************************/
setNWChemGeometryFromInputFile(gchar * fileName)190 void setNWChemGeometryFromInputFile(gchar* fileName)
191 {
192 	read_XYZ_from_nwchem_input_file(fileName);
193 	setNWChemMolecule();
194 }
195 /************************************************************************************************************/
testAbelianGroup()196 static gboolean testAbelianGroup()
197 {
198 	gint i;
199 	gchar** symbols = NULL;
200 	gdouble* X = NULL;
201 	gdouble* Y = NULL;
202 	gdouble* Z = NULL;
203 	gint numberOfAtoms = nwchemMolecule.numberOfAtoms;
204 	gchar pointGroupSymbol[BSIZE];
205 	gchar abelianPointGroupSymbol[BSIZE];
206 	gchar message[BSIZE];
207 	gint maximalOrder = 20;
208 	gint nGenerators;
209 	gint nMolcas = 0;
210 	gint nElements;
211 	gchar* generators[3];
212 	gchar* molcasGenerators[3];
213 	gchar* elements[8];
214 	gdouble principalAxisTolerance = getTolerancePrincipalAxis();
215 	gdouble positionTolerance = getTolerancePosition();
216 
217 	if(numberOfAtoms<1) return FALSE;
218 
219 	for(i=0;i<3;i++)
220 	{
221 		generators[i] = g_malloc(100*sizeof(gchar));
222 		molcasGenerators[i] = g_malloc(100*sizeof(gchar));
223 	}
224 	for(i=0;i<8;i++) elements[i] = g_malloc(100*sizeof(gchar));
225 
226 	symbols = (gchar**)g_malloc(sizeof(gchar*)*(numberOfAtoms));
227 	if(symbols == NULL) return FALSE;
228 
229 	X = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
230 	if(X == NULL) return FALSE;
231 	Y = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
232 	if(Y == NULL) return FALSE;
233 	Z = (gdouble*)g_malloc(sizeof(gdouble)*(numberOfAtoms));
234 	if(Z == NULL) return FALSE;
235 
236 	for(i=0; i<numberOfAtoms; i++)
237 	{
238 		symbols[i] = g_strdup(nwchemMolecule.listOfAtoms[i].symbol);
239 		X[i] = nwchemMolecule.listOfAtoms[i].position[0];
240 		Y[i] = nwchemMolecule.listOfAtoms[i].position[1];
241 		Z[i] = nwchemMolecule.listOfAtoms[i].position[2];
242 	}
243 	computeAbelianGroup(principalAxisTolerance, pointGroupSymbol, abelianPointGroupSymbol, maximalOrder, TRUE,
244 	       	&numberOfAtoms, symbols, X, Y, Z,
245 		&nGenerators, generators, &nMolcas, molcasGenerators, &nElements, elements, &positionTolerance, message);
246 
247 	for(i=0;i<3;i++)
248 	{
249 		g_free(generators[i]);
250 		g_free(molcasGenerators[i]);
251 	}
252 	for(i=0;i<8;i++) g_free(elements[i]);
253 
254 	for (i=0;i<(gint)numberOfAtoms;i++) g_free( symbols[i]);
255 	g_free( symbols);
256 	g_free(X);
257 	g_free(Y);
258 	g_free(Z);
259 	if(!strcmp( pointGroupSymbol,abelianPointGroupSymbol))return TRUE;
260 	return FALSE;
261 }
262 /*************************************************************************************************************/
263 /*
264 static gdouble getMinDistance()
265 {
266 	gdouble d=0;
267 	gint i;
268 	gint k;
269 	NWChemAtom* atomList = nwchemMolecule.listOfAtoms;
270 	for(i=0; i<nwchemMolecule.numberOfAtoms-1; i++)
271 	{
272 		gdouble dd = 0;
273 		for(k=0;k<3;k++)
274 		{
275 			gdouble xx = atomList->position[k]-atomList->position[k+1];
276 			dd += xx*xx;
277 		}
278 		if(i==0) d = dd;
279 		else if(d>dd) d= dd;
280 		atomList++;
281 	}
282 	d = sqrt(d);
283 
284 	return d;
285 }
286 */
287 /*************************************************************************************************************/
288 /*
289 static void setFirstAtomToXAxis(gint numberOfAtoms, gdouble* X, gdouble* Y, gdouble*Z)
290 {
291 	gdouble d;
292 	gdouble s;
293 	gdouble c;
294 	gint i;
295 	gdouble positionTolerance = -1;
296 
297 	if(numberOfAtoms<1) return;
298 	d = X[0]*X[0]+Y[0]*Y[0];
299 	if(d<1e-10) return;
300 	d = sqrt(d);
301 	if(positionTolerance<0) positionTolerance= getMinDistance()/50;
302 
303 	s = -Y[0]/d;
304 	c = +X[0]/d;
305 
306 	for (i=0;i<numberOfAtoms;i++)
307 	 {
308 		 gdouble x = X[i];
309 		 gdouble y = Y[i];
310 		X[i] = c*x - s*y;
311 		Y[i] = s*x + c*y;
312 		if(fabs(Y[i])<positionTolerance) Y[i]=0.0;
313 	 }
314 
315 }
316 */
317 /*************************************************************************************************************/
318 /*
319 static gint getRealNumberXYZVariables()
320 {
321 	gint k=0;
322 	gint i;
323         for(i=0;i<NcentersXYZ;i++)
324 	{
325 		if(test(GeomXYZ[i].X))k++;
326 		if(test(GeomXYZ[i].Y))k++;
327 		if(test(GeomXYZ[i].Z))k++;
328 	}
329 	return k;
330 }
331 */
332 /*************************************************************************************************************/
putNWChemMoleculeInTextEditor()333 static void putNWChemMoleculeInTextEditor()
334 {
335         gchar buffer[BSIZE];
336 	gint i;
337 	gint nV = 0;
338 	gdouble x,y,z;
339 
340 	if(nwchemMolecule.numberOfAtoms<1) return;
341 
342 	if(MethodeGeom==GEOM_IS_XYZ)
343 	{
344 		sprintf(buffer,"\ncharge %d\n",totalCharge);
345         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
346 		sprintf(buffer,"\ngeometry\n");
347         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
348       		for (i=0;i<nwchemMolecule.numberOfAtoms;i++)
349 		{
350 			gchar X[100];
351 			gchar Y[100];
352 			gchar Z[100];
353 			setXYZFromGeomXYZ(i, &x, &y, &z);
354 			sprintf(X,"%f",x);
355 			sprintf(Y,"%f",y);
356 			sprintf(Z,"%f",z);
357 			sprintf(buffer," %s  %s %s %s\n",nwchemMolecule.listOfAtoms[i].symbol, X,Y,Z);
358         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, buffer, -1);
359 		}
360 		if(strstr(getNWChemExcitedMethod(),"CIS")||strstr(getNWChemExcitedMethod(),"TDDFT") || strstr(getNWChemTypeMethod(),"HL-"))
361 		{
362 			if(!testAbelianGroup())
363         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, " symmetry C1\n", -1);
364 		}
365 		sprintf(buffer,"end\n");
366         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
367 		nV = 0;
368         	if(NVariablesXYZ>0)
369         	for(i=0;i<NVariablesXYZ;i++)
370         	{
371         		if(VariablesXYZ[i].Used) nV++;
372         	}
373 		if(nV>0 && nV!= 3*nwchemMolecule.numberOfAtoms)
374 		{
375 			sprintf(buffer,"\nconstraints\n");
376         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
377       			for (i=0;i<nwchemMolecule.numberOfAtoms;i++)
378 			{
379   				if(!(!test(GeomXYZ[i].X) || !test(GeomXYZ[i].Y) || !test(GeomXYZ[i].Z)))
380 				{
381 					sprintf(buffer," fix atom %d\n",i+1);
382         				gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,buffer,-1);
383 				}
384 			}
385         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, "end\n", -1);
386 		}
387 	}
388 	else
389 	{
390 		sprintf(buffer,"\ncharge %d\n",totalCharge);
391         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
392 		sprintf(buffer,"\ngeometry\n");
393         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
394         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,"\t",-1);
395 		sprintf(buffer,"zmatrix\n");
396         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord, buffer, -1);
397         	for(i=0;i<NcentersZmat;i++)
398         	{
399 			SAtomsProp prop = prop_atom_get(Geom[i].Symb);
400   			gchar *line;
401         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,"\t",-1);
402 			line=g_strdup_printf("%s",Geom[i].Symb);
403         		if(Geom[i].Nentry>NUMBER_ENTRY_0) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NR,Geom[i].R);
404         		if(Geom[i].Nentry>NUMBER_ENTRY_R) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NAngle,Geom[i].Angle);
405         		if(Geom[i].Nentry>NUMBER_ENTRY_ANGLE) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NDihedral,Geom[i].Dihedral);
406   			line=g_strdup_printf("%s\n",line);
407  			prop = prop_atom_get(Geom[i].Symb);
408         		gabedit_text_insert (GABEDIT_TEXT(text), NULL,NULL, &prop.color,line,-1);
409 			g_free(line);
410         	}
411         	if(NVariables>0)
412 		{
413 			gint nV = 0;
414         		for(i=0;i<NVariables;i++)
415         		{
416         			if(Variables[i].Used)
417 				{
418         			gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,"\tvariables\n",-1);
419 				nV++;
420 				break;
421 				}
422         		}
423         		for(i=0;i<NVariables;i++)
424         		{
425         			if(Variables[i].Used)
426 				{
427   				gchar* line=g_strdup_printf("\t%s\t%s\n",Variables[i].Name,Variables[i].Value);
428         			gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,line,-1);
429 				g_free(line);
430 				}
431         		}
432 			if(nV>0)
433 			{
434         			gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,"\t",-1);
435 				gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord,"end\n",-1);
436 			}
437 
438 		}
439 		gabedit_text_insert (GABEDIT_TEXT(text), NULL, &nwchemColorFore.keyWord, &nwchemColorBack.keyWord,"end\n",-1);
440 	}
441 
442 }
443 /************************************************************************************************************/
putNWChemMoleculeInfoInTextEditor()444 void putNWChemMoleculeInfoInTextEditor()
445 {
446 	putNWChemMoleculeInTextEditor();
447 }
448 /************************************************************************************************************/
449 /*
450 static GtkWidget* addRadioButtonToATable(GtkWidget* table, GtkWidget* friendButton, gchar* label, gint i, gint j, gint k)
451 {
452 	GtkWidget *newButton;
453 
454 	if(friendButton)
455 		newButton = gtk_radio_button_new_with_label( gtk_radio_button_get_group (GTK_RADIO_BUTTON (friendButton)), label);
456 	else
457 		newButton = gtk_radio_button_new_with_label( NULL, label);
458 
459 	gtk_table_attach(GTK_TABLE(table),newButton,j,j+k,i,i+1,
460 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
461 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
462                   2,2);
463 
464 	g_object_set_data(G_OBJECT (newButton), "Label",NULL);
465 	g_object_set_data(G_OBJECT (newButton), "Type",NULL);
466 	return newButton;
467 }
468 */
469 /********************************************************************************/
setSpinMultiplicityComboSpinMultiplicity(GtkWidget * comboSpinMultiplicity,gint spin)470 static void setSpinMultiplicityComboSpinMultiplicity(GtkWidget *comboSpinMultiplicity, gint spin)
471 {
472 	GtkWidget *entry = NULL;
473 	gchar* t = NULL;
474 	if(!comboSpinMultiplicity) return;
475 	entry = GTK_BIN (comboSpinMultiplicity)->child;
476 	t = g_strdup_printf("%d",spin);
477 	gtk_entry_set_text(GTK_ENTRY(entry),t);
478 	g_free(t);
479 }
480 /************************************************************************************************************/
setComboSpinMultiplicity(GtkWidget * comboSpinMultiplicity)481 static void setComboSpinMultiplicity(GtkWidget *comboSpinMultiplicity)
482 {
483 	GList *glist = NULL;
484 	gint i;
485 	gint nlist = 0;
486 	gchar** list = NULL;
487 	gint k;
488 	gint kinc;
489 	gint ne = nwchemMolecule.numberOfValenceElectrons - totalCharge;
490 
491 	if(ne%2==0) nlist = ne/2+1;
492 	else nlist = (ne+1)/2;
493 
494 	if(nlist<1) return;
495 	list = g_malloc(nlist*sizeof(gchar*));
496 	if(!list) return;
497 	for(i=0;i<nlist;i++)
498 		list[i] = g_malloc(10*sizeof(gchar));
499 
500 
501 	if(GTK_IS_WIDGET(comboSpinMultiplicity)) gtk_widget_set_sensitive(comboSpinMultiplicity, TRUE);
502 	if(ne%2==0) k = 1;
503 	else k = 2;
504 
505 	kinc = 2;
506 	for(i=0;i<nlist;i++)
507 	{
508 		sprintf(list[i],"%d",k);
509 		k+=kinc;
510 	}
511 
512   	for(i=0;i<nlist;i++) glist = g_list_append(glist,list[i]);
513 
514   	gtk_combo_box_entry_set_popdown_strings( comboSpinMultiplicity, glist) ;
515   	g_list_free(glist);
516 	if( SpinMultiplicities[0]%2 == atoi(list[0])%2) setSpinMultiplicityComboSpinMultiplicity(comboSpinMultiplicity, SpinMultiplicities[0]);
517 	else SpinMultiplicities[0] = atoi(list[0]);
518 	if(list)
519 	{
520 		for(i=0;i<nlist;i++) if(list[i]) g_free(list[i]);
521 		g_free(list);
522 	}
523 }
524 /********************************************************************************/
setChargeComboCharge(GtkWidget * comboCharge,gint charge)525 static void setChargeComboCharge(GtkWidget *comboCharge, gint charge)
526 {
527 	GtkWidget *entry = NULL;
528 	gchar* t = NULL;
529 	if(!comboCharge) return;
530 	entry = GTK_BIN (comboCharge)->child;
531 	t = g_strdup_printf("%d",charge);
532 	gtk_entry_set_text(GTK_ENTRY(entry),t);
533 	g_free(t);
534 }
535 /********************************************************************************/
setComboCharge(GtkWidget * comboCharge)536 static void setComboCharge(GtkWidget *comboCharge)
537 {
538 	GList *glist = NULL;
539 	gint i;
540 	gint nlist;
541 	gchar** list = NULL;
542 	gint k;
543 
544 	nlist = nwchemMolecule.numberOfValenceElectrons*2-2+1;
545 
546 	if(nlist<1) return;
547 	list = g_malloc(nlist*sizeof(gchar*));
548 	if(!list) return;
549 	for(i=0;i<nlist;i++)
550 		list[i] = g_malloc(10*sizeof(gchar));
551 
552 
553 	sprintf(list[0],"0");
554 	k = 1;
555 	for(i=1;i<nlist-1;i+=2)
556 	{
557 		sprintf(list[i],"+%d",k);
558 		sprintf(list[i+1],"%d",-k);
559 		k += 1;
560 	}
561 
562   	for(i=0;i<nlist;i++) glist = g_list_append(glist,list[i]);
563 
564   	gtk_combo_box_entry_set_popdown_strings( comboCharge, glist) ;
565   	g_list_free(glist);
566 	if(list)
567 	{
568 		for(i=0;i<nlist;i++) if(list[i]) g_free(list[i]);
569 		g_free(list);
570 	}
571 	setChargeComboCharge(comboCharge, totalCharge);
572 }
573 /**********************************************************************/
changedEntrySpinMultiplicity(GtkWidget * entry,gpointer data)574 static void changedEntrySpinMultiplicity(GtkWidget *entry, gpointer data)
575 {
576 	G_CONST_RETURN gchar* entryText = NULL;
577 
578 	if(!GTK_IS_WIDGET(entry)) return;
579 
580 	entryText = gtk_entry_get_text(GTK_ENTRY(entry));
581 	if(strlen(entryText)<1)return;
582 
583 	spinMultiplicity=atoi(entryText);
584 	if(spinMultiplicity==1)
585 	{
586 		/* OK RHF*/
587 		setNWChemSCFMethod(TRUE);
588 	}
589 	else
590 	{
591 		/* remove RHF from list*/
592 		setNWChemSCFMethod(FALSE);
593 	}
594 }
595 /**********************************************************************/
changedEntryCharge(GtkWidget * entry,gpointer data)596 static void changedEntryCharge(GtkWidget *entry, gpointer data)
597 {
598 	G_CONST_RETURN gchar* entryText = NULL;
599 	GtkWidget* comboSpinMultiplicity = NULL;
600 	GtkWidget* labelNumberOfElectrons = NULL;
601 
602 	if(!GTK_IS_WIDGET(entry)) return;
603 
604 	entryText = gtk_entry_get_text(GTK_ENTRY(entry));
605 	if(strlen(entryText)<1)return;
606 
607 	totalCharge = atoi(entryText);
608 	TotalCharges[0] = totalCharge;
609 
610 	comboSpinMultiplicity  = g_object_get_data(G_OBJECT (entry), "ComboSpinMultiplicity");
611 	if(GTK_IS_WIDGET(comboSpinMultiplicity)) setComboSpinMultiplicity(comboSpinMultiplicity);
612 
613 	labelNumberOfElectrons = g_object_get_data(G_OBJECT (entry), "LabelNumberOfElectrons");
614 
615 	if(GTK_IS_WIDGET(labelNumberOfElectrons))
616 	{
617 		gint ne = nwchemMolecule.numberOfValenceElectrons - totalCharge;
618 		gchar buffer[BSIZE];
619 		sprintf(buffer, "Number of electrons = %d",ne);
620 		gtk_label_set_text(GTK_LABEL(labelNumberOfElectrons),buffer);
621 	}
622 }
623 /**********************************************************************/
addComboListToATable(GtkWidget * table,gchar ** list,gint nlist,gint i,gint j,gint k)624 static GtkWidget* addComboListToATable(GtkWidget* table,
625 		gchar** list, gint nlist, gint i, gint j, gint k)
626 {
627 	GtkWidget *entry = NULL;
628 	GtkWidget *combo = NULL;
629 
630 	combo = create_combo_box_entry(list, nlist, TRUE, -1, -1);
631 
632 	gtk_table_attach(GTK_TABLE(table),combo,j,j+k,i,i+1,
633 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
634 		(GtkAttachOptions)	(GTK_FILL | GTK_SHRINK),
635                   2,2);
636 	entry = GTK_BIN (combo)->child;
637 	g_object_set_data(G_OBJECT (entry), "Combo",combo);
638 	gtk_widget_set_size_request(GTK_WIDGET(entry),(gint)(ScreenHeight*0.2),-1);
639 
640 	return entry;
641 }
642 /***********************************************************************************************/
addNWChemChargeToTable(GtkWidget * table,gint i)643 static GtkWidget *addNWChemChargeToTable(GtkWidget *table, gint i)
644 {
645 	GtkWidget* entryCharge = NULL;
646 	GtkWidget* comboCharge = NULL;
647 	gint nlistCharge = 1;
648 	gchar* listCharge[] = {"0"};
649 
650 	add_label_table(table,_("Charge"),(gushort)i,0);
651 	add_label_table(table,":",(gushort)i,1);
652 	entryCharge = addComboListToATable(table, listCharge, nlistCharge, i, 2, 1);
653 	comboCharge  = g_object_get_data(G_OBJECT (entryCharge), "Combo");
654 	gtk_widget_set_sensitive(entryCharge, FALSE);
655 
656 	return comboCharge;
657 }
658 /***********************************************************************************************/
addNWChemSpinToTable(GtkWidget * table,gint i)659 static GtkWidget *addNWChemSpinToTable(GtkWidget *table, gint i)
660 {
661 	GtkWidget* entrySpinMultiplicity = NULL;
662 	GtkWidget* comboSpinMultiplicity = NULL;
663 	gint nlistspinMultiplicity = 1;
664 	gchar* listspinMultiplicity[] = {"0"};
665 
666 	add_label_table(table,_("Spin multiplicity"),(gushort)i,0);
667 	add_label_table(table,":",(gushort)i,1);
668 	entrySpinMultiplicity = addComboListToATable(table, listspinMultiplicity, nlistspinMultiplicity, i, 2, 1);
669 	comboSpinMultiplicity  = g_object_get_data(G_OBJECT (entrySpinMultiplicity), "Combo");
670 	gtk_widget_set_sensitive(entrySpinMultiplicity, FALSE);
671 
672 	g_signal_connect(G_OBJECT(entrySpinMultiplicity),"changed", G_CALLBACK(changedEntrySpinMultiplicity),NULL);
673 	return comboSpinMultiplicity;
674 }
675 /***********************************************************************************************/
addLabelNumberOfElectronsToTable(GtkWidget * table,gint i,GtkWidget * comboCharge)676 static GtkWidget *addLabelNumberOfElectronsToTable(GtkWidget *table, gint i, GtkWidget *comboCharge)
677 {
678 	GtkWidget* labelNumberOfElectrons = NULL;
679 	GtkWidget* hbox = NULL;
680 	GtkWidget* entryCharge = GTK_BIN(comboCharge)->child;
681 
682 	labelNumberOfElectrons = gtk_label_new(" ");
683 	hbox = gtk_hbox_new(0,FALSE);
684 	gtk_box_pack_start (GTK_BOX (hbox), labelNumberOfElectrons, FALSE, FALSE, 0);
685 	gtk_table_attach(GTK_TABLE(table),hbox,0,0+3,i,i+1,
686 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
687 		(GtkAttachOptions)	(GTK_FILL | GTK_SHRINK),
688                   2,2);
689 
690 	g_object_set_data(G_OBJECT (entryCharge), "LabelNumberOfElectrons", labelNumberOfElectrons);
691 	g_signal_connect(G_OBJECT(entryCharge),"changed", G_CALLBACK(changedEntryCharge),NULL);
692 	return labelNumberOfElectrons;
693 }
694 /***********************************************************************************************/
createNWChemChargeMultiplicityFrame(GtkWidget * box)695 void createNWChemChargeMultiplicityFrame(GtkWidget *box)
696 {
697 	GtkWidget* frame;
698 	GtkWidget* sep;
699 	GtkWidget* labelNumberOfElectrons;
700 	GtkWidget* vboxFrame;
701 	GtkWidget* comboSpinMultiplicity = NULL;
702 	GtkWidget* comboCharge = NULL;
703 	GtkWidget *table = NULL;
704 	gint i;
705 
706 	totalCharge = TotalCharges[0];
707 	spinMultiplicity=SpinMultiplicities[0];
708 
709 	table = gtk_table_new(3,5,FALSE);
710 
711 	frame = gtk_frame_new (_("Charge & Multiplicty"));
712 	gtk_widget_show (frame);
713 	gtk_box_pack_start (GTK_BOX (box), frame, TRUE, TRUE, 3);
714 	gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
715 
716 	vboxFrame = gtk_vbox_new (FALSE, 3);
717 	gtk_widget_show (vboxFrame);
718 	gtk_container_add (GTK_CONTAINER (frame), vboxFrame);
719 
720 	gtk_box_pack_start (GTK_BOX (vboxFrame), table, TRUE, TRUE, 0);
721 
722 	i = 0;
723 	comboCharge = addNWChemChargeToTable(table, i);
724 	i = 1;
725 	comboSpinMultiplicity = addNWChemSpinToTable(table, i);
726 	i = 2;
727 	sep = gtk_hseparator_new ();;
728 	gtk_table_attach(GTK_TABLE(table),sep,0,0+3,i,i+1,
729 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
730 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
731                   2,2);
732 
733 	i = 3;
734 	labelNumberOfElectrons=addLabelNumberOfElectronsToTable(table, i, comboCharge);
735 
736 	if(GTK_IS_COMBO_BOX(comboCharge))
737 		g_object_set_data(G_OBJECT (GTK_BIN(comboCharge)->child), "ComboSpinMultiplicity", comboSpinMultiplicity);
738 	setComboCharge(comboCharge);
739 	setComboSpinMultiplicity(comboSpinMultiplicity);
740 	if(GTK_IS_WIDGET(labelNumberOfElectrons))
741 	{
742 		gint ne = nwchemMolecule.numberOfValenceElectrons - totalCharge;
743 		gchar buffer[BSIZE];
744 		sprintf(buffer, "Number of electrons = %d",ne);
745 		gtk_label_set_text(GTK_LABEL(labelNumberOfElectrons),buffer);
746 	}
747 
748 	/* activate sensitivity */
749 	/*
750 	if(GTK_IS_WIDGET(comboMethod)) setComboMethod(comboMethod);
751 	g_object_set_data(G_OBJECT (box), "EntryMethod", GTK_BIN(comboMethod)->child);
752 	*/
753 }
754 /************************************************************************************************************/
755