1 /* PsicodeMolecule.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 "../Psicode/PsicodeTypes.h"
27 #include "../Psicode/PsicodeGlobal.h"
28 #include "../Psicode/PsicodeKeywords.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 /************************************************************************************************************/
getPsicodeMultiplicity()49 gint getPsicodeMultiplicity()
50 {
51 	return spinMultiplicity;
52 }
53 /************************************************************************************************************/
initPsicodeMoleculeButtons()54 void initPsicodeMoleculeButtons()
55 {
56 }
57 /************************************************************************************************************/
initPsicodeMolecule()58 void initPsicodeMolecule()
59 {
60 	psicodeMolecule.listOfAtoms = NULL;
61 	psicodeMolecule.totalNumberOfElectrons = 0;
62 	psicodeMolecule.numberOfValenceElectrons = 0;
63 	psicodeMolecule.numberOfAtoms = 0;
64 }
65 /************************************************************************************************************/
freePsicodeMolecule()66 void freePsicodeMolecule()
67 {
68 	static gboolean first = TRUE;
69 
70 	if(first)
71 	{
72 		initPsicodeMolecule();
73 		first = FALSE;
74 		return;
75 	}
76 
77 	if(psicodeMolecule.listOfAtoms) g_free(psicodeMolecule.listOfAtoms);
78 	initPsicodeMolecule();
79 }
80 /************************************************************************************************************/
setPsicodeMoleculeFromSXYZ(gint nAtoms,gchar ** symbols,gdouble * X,gdouble * Y,gdouble * Z)81 static gint setPsicodeMoleculeFromSXYZ(gint nAtoms, gchar** symbols, gdouble* X, gdouble* Y, gdouble* Z)
82 {
83 	gint n;
84 	PsicodeAtom* atomList = NULL;
85 
86 	psicodeMolecule.listOfAtoms = NULL;
87 	psicodeMolecule.numberOfAtoms = 0;
88 	if(nAtoms<1) return 1;
89 
90 	psicodeMolecule.listOfAtoms = (PsicodeAtom*)g_malloc(sizeof(PsicodeAtom)*(nAtoms));
91 	if(psicodeMolecule.listOfAtoms==NULL) return -1;
92 
93 	psicodeMolecule.numberOfAtoms = nAtoms;
94 
95 	atomList = psicodeMolecule.listOfAtoms;
96 	for(n=0; n<psicodeMolecule.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 /************************************************************************************************************/
setPsicodeMoleculeFromGeomXYZ()131 static gboolean setPsicodeMoleculeFromGeomXYZ()
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 	psicodeMolecule.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 		psicodeMolecule.totalNumberOfElectrons += prop.atomicNumber;
161 	}
162 	psicodeMolecule.numberOfValenceElectrons = psicodeMolecule.totalNumberOfElectrons;
163 	setPsicodeMoleculeFromSXYZ(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 /************************************************************************************************************/
setPsicodeMoleculeFromGeomZMatrix()173 static gboolean setPsicodeMoleculeFromGeomZMatrix()
174 {
175 	iprogram=PROG_IS_PSICODE;
176 	if(!zmat_to_xyz()) return FALSE;
177 	delete_dummy_atoms();
178 	/* conversion_zmat_to_xyz();*/
179 	return setPsicodeMoleculeFromGeomXYZ();
180 }
181 /************************************************************************************************************/
setPsicodeMolecule()182 gboolean setPsicodeMolecule()
183 {
184 	freePsicodeMolecule();
185 	if(MethodeGeom==GEOM_IS_XYZ && setPsicodeMoleculeFromGeomXYZ()) return TRUE;
186 	if(setPsicodeMoleculeFromGeomZMatrix()) return TRUE;
187 	return FALSE;
188 }
189 /************************************************************************************************************/
setPsicodeGeometryFromInputFile(gchar * fileName)190 void setPsicodeGeometryFromInputFile(gchar* fileName)
191 {
192 	read_XYZ_from_psicode_input_file(fileName);
193 	setPsicodeMolecule();
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 = psicodeMolecule.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(psicodeMolecule.listOfAtoms[i].symbol);
239 		X[i] = psicodeMolecule.listOfAtoms[i].position[0];
240 		Y[i] = psicodeMolecule.listOfAtoms[i].position[1];
241 		Z[i] = psicodeMolecule.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 	PsicodeAtom* atomList = psicodeMolecule.listOfAtoms;
270 	for(i=0; i<psicodeMolecule.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 /*************************************************************************************************************/
putPsicodeMoleculeInTextEditor()333 static void putPsicodeMoleculeInTextEditor()
334 {
335         gchar buffer[BSIZE];
336 	gint i;
337 	gint nV = 0;
338 	gdouble x,y,z;
339 
340 	if(psicodeMolecule.numberOfAtoms<1) return;
341 
342 	if(MethodeGeom==GEOM_IS_XYZ)
343 	{
344 		sprintf(buffer,"\nmolecule mymol {\n");
345         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &psicodeColorFore.keyWord, &psicodeColorBack.keyWord, buffer, -1);
346 		sprintf(buffer," %d %d\n",totalCharge, SpinMultiplicities[0]);
347         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, buffer, -1);
348       		for (i=0;i<psicodeMolecule.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",psicodeMolecule.listOfAtoms[i].symbol, X,Y,Z);
358         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, buffer, -1);
359 		}
360 		if(strstr(getPsicodeExcitedMethod(),"EOM")||strstr(getPsicodeExcitedMethod(),"TDDFT") || strstr(getPsicodeTypeMethod(),"HL-"))
361 		{
362 			if(!testAbelianGroup())
363         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, " symmetry C1\n", -1);
364 		}
365 		nV = 0;
366         	if(NVariablesXYZ>0)
367         	for(i=0;i<NVariablesXYZ;i++)
368         	{
369         		if(VariablesXYZ[i].Used) nV++;
370         	}
371 		if(nV>0 && nV!= 3*psicodeMolecule.numberOfAtoms)
372 		{
373 			sprintf(buffer,"\nconstraints\n");
374         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, &psicodeColorFore.keyWord, &psicodeColorBack.keyWord, buffer, -1);
375       			for (i=0;i<psicodeMolecule.numberOfAtoms;i++)
376 			{
377   				if(!(!test(GeomXYZ[i].X) || !test(GeomXYZ[i].Y) || !test(GeomXYZ[i].Z)))
378 				{
379 					sprintf(buffer," fix atom %d\n",i+1);
380         				gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,buffer,-1);
381 				}
382 			}
383 		}
384 		sprintf(buffer,"}\n");
385         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &psicodeColorFore.keyWord, &psicodeColorBack.keyWord, buffer, -1);
386 	}
387 	else
388 	{
389 		sprintf(buffer,"\nmolecule mymol {\n");
390         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, &psicodeColorFore.keyWord, &psicodeColorBack.keyWord, buffer, -1);
391 		sprintf(buffer," %d %d\n",totalCharge, SpinMultiplicities[0]);
392         	gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL, buffer, -1);
393         	for(i=0;i<NcentersZmat;i++)
394         	{
395 			SAtomsProp prop = prop_atom_get(Geom[i].Symb);
396   			gchar *line;
397         		gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL," ",-1);
398 			line=g_strdup_printf("%s",Geom[i].Symb);
399         		if(Geom[i].Nentry>NUMBER_ENTRY_0) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NR,Geom[i].R);
400         		if(Geom[i].Nentry>NUMBER_ENTRY_R) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NAngle,Geom[i].Angle);
401         		if(Geom[i].Nentry>NUMBER_ENTRY_ANGLE) line=g_strdup_printf("%s\t%s\t%s",line,Geom[i].NDihedral,Geom[i].Dihedral);
402   			line=g_strdup_printf("%s\n",line);
403  			prop = prop_atom_get(Geom[i].Symb);
404         		gabedit_text_insert (GABEDIT_TEXT(text), NULL,NULL, &prop.color,line,-1);
405 			g_free(line);
406         	}
407         	if(NVariables>0)
408 		{
409 			gint nV = 0;
410         		for(i=0;i<NVariables;i++)
411         		{
412         			if(Variables[i].Used)
413 				{
414         			gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL," \n",-1);
415 				nV++;
416 				break;
417 				}
418         		}
419         		for(i=0;i<NVariables;i++)
420         		{
421         			if(Variables[i].Used)
422 				{
423   				gchar* line=g_strdup_printf(" %s\t%s\n",Variables[i].Name,Variables[i].Value);
424         			gabedit_text_insert (GABEDIT_TEXT(text), NULL, NULL, NULL,line,-1);
425 				g_free(line);
426 				}
427         		}
428 		}
429 		gabedit_text_insert (GABEDIT_TEXT(text), NULL, &psicodeColorFore.keyWord, &psicodeColorBack.keyWord,"}\n",-1);
430 	}
431 
432 }
433 /************************************************************************************************************/
putPsicodeMoleculeInfoInTextEditor()434 void putPsicodeMoleculeInfoInTextEditor()
435 {
436 	putPsicodeMoleculeInTextEditor();
437 }
438 /************************************************************************************************************/
439 /*
440 static GtkWidget* addRadioButtonToATable(GtkWidget* table, GtkWidget* friendButton, gchar* label, gint i, gint j, gint k)
441 {
442 	GtkWidget *newButton;
443 
444 	if(friendButton)
445 		newButton = gtk_radio_button_new_with_label( gtk_radio_button_get_group (GTK_RADIO_BUTTON (friendButton)), label);
446 	else
447 		newButton = gtk_radio_button_new_with_label( NULL, label);
448 
449 	gtk_table_attach(GTK_TABLE(table),newButton,j,j+k,i,i+1,
450 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
451 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
452                   2,2);
453 
454 	g_object_set_data(G_OBJECT (newButton), "Label",NULL);
455 	g_object_set_data(G_OBJECT (newButton), "Type",NULL);
456 	return newButton;
457 }
458 */
459 /********************************************************************************/
setSpinMultiplicityComboSpinMultiplicity(GtkWidget * comboSpinMultiplicity,gint spin)460 static void setSpinMultiplicityComboSpinMultiplicity(GtkWidget *comboSpinMultiplicity, gint spin)
461 {
462 	GtkWidget *entry = NULL;
463 	gchar* t = NULL;
464 	if(!comboSpinMultiplicity) return;
465 	entry = GTK_BIN (comboSpinMultiplicity)->child;
466 	t = g_strdup_printf("%d",spin);
467 	gtk_entry_set_text(GTK_ENTRY(entry),t);
468 	g_free(t);
469 }
470 /************************************************************************************************************/
setComboSpinMultiplicity(GtkWidget * comboSpinMultiplicity)471 static void setComboSpinMultiplicity(GtkWidget *comboSpinMultiplicity)
472 {
473 	GList *glist = NULL;
474 	gint i;
475 	gint nlist = 0;
476 	gchar** list = NULL;
477 	gint k;
478 	gint kinc;
479 	gint ne = psicodeMolecule.numberOfValenceElectrons - totalCharge;
480 
481 	if(ne%2==0) nlist = ne/2+1;
482 	else nlist = (ne+1)/2;
483 
484 	if(nlist<1) return;
485 	list = g_malloc(nlist*sizeof(gchar*));
486 	if(!list) return;
487 	for(i=0;i<nlist;i++)
488 		list[i] = g_malloc(10*sizeof(gchar));
489 
490 
491 	if(GTK_IS_WIDGET(comboSpinMultiplicity)) gtk_widget_set_sensitive(comboSpinMultiplicity, TRUE);
492 	if(ne%2==0) k = 1;
493 	else k = 2;
494 
495 	kinc = 2;
496 	for(i=0;i<nlist;i++)
497 	{
498 		sprintf(list[i],"%d",k);
499 		k+=kinc;
500 	}
501 
502   	for(i=0;i<nlist;i++) glist = g_list_append(glist,list[i]);
503 
504   	gtk_combo_box_entry_set_popdown_strings( comboSpinMultiplicity, glist) ;
505   	g_list_free(glist);
506 	if( SpinMultiplicities[0]%2 == atoi(list[0])%2) setSpinMultiplicityComboSpinMultiplicity(comboSpinMultiplicity, SpinMultiplicities[0]);
507 	else SpinMultiplicities[0] = atoi(list[0]);
508 	if(list)
509 	{
510 		for(i=0;i<nlist;i++) if(list[i]) g_free(list[i]);
511 		g_free(list);
512 	}
513 }
514 /********************************************************************************/
setChargeComboCharge(GtkWidget * comboCharge,gint charge)515 static void setChargeComboCharge(GtkWidget *comboCharge, gint charge)
516 {
517 	GtkWidget *entry = NULL;
518 	gchar* t = NULL;
519 	if(!comboCharge) return;
520 	entry = GTK_BIN (comboCharge)->child;
521 	t = g_strdup_printf("%d",charge);
522 	gtk_entry_set_text(GTK_ENTRY(entry),t);
523 	g_free(t);
524 }
525 /********************************************************************************/
setComboCharge(GtkWidget * comboCharge)526 static void setComboCharge(GtkWidget *comboCharge)
527 {
528 	GList *glist = NULL;
529 	gint i;
530 	gint nlist;
531 	gchar** list = NULL;
532 	gint k;
533 
534 	nlist = psicodeMolecule.numberOfValenceElectrons*2-2+1;
535 
536 	if(nlist<1) return;
537 	list = g_malloc(nlist*sizeof(gchar*));
538 	if(!list) return;
539 	for(i=0;i<nlist;i++)
540 		list[i] = g_malloc(10*sizeof(gchar));
541 
542 
543 	sprintf(list[0],"0");
544 	k = 1;
545 	for(i=1;i<nlist-1;i+=2)
546 	{
547 		sprintf(list[i],"+%d",k);
548 		sprintf(list[i+1],"%d",-k);
549 		k += 1;
550 	}
551 
552   	for(i=0;i<nlist;i++) glist = g_list_append(glist,list[i]);
553 
554   	gtk_combo_box_entry_set_popdown_strings( comboCharge, glist) ;
555   	g_list_free(glist);
556 	if(list)
557 	{
558 		for(i=0;i<nlist;i++) if(list[i]) g_free(list[i]);
559 		g_free(list);
560 	}
561 	setChargeComboCharge(comboCharge, totalCharge);
562 }
563 /**********************************************************************/
changedEntrySpinMultiplicity(GtkWidget * entry,gpointer data)564 static void changedEntrySpinMultiplicity(GtkWidget *entry, gpointer data)
565 {
566 	G_CONST_RETURN gchar* entryText = NULL;
567 
568 	if(!GTK_IS_WIDGET(entry)) return;
569 
570 	entryText = gtk_entry_get_text(GTK_ENTRY(entry));
571 	if(strlen(entryText)<1)return;
572 
573 	spinMultiplicity=atoi(entryText);
574 	if(spinMultiplicity==1)
575 	{
576 		/* OK RHF*/
577 		setPsicodeSCFMethod(TRUE);
578 	}
579 	else
580 	{
581 		/* remove RHF from list*/
582 		setPsicodeSCFMethod(FALSE);
583 	}
584 }
585 /**********************************************************************/
changedEntryCharge(GtkWidget * entry,gpointer data)586 static void changedEntryCharge(GtkWidget *entry, gpointer data)
587 {
588 	G_CONST_RETURN gchar* entryText = NULL;
589 	GtkWidget* comboSpinMultiplicity = NULL;
590 	GtkWidget* labelNumberOfElectrons = NULL;
591 
592 	if(!GTK_IS_WIDGET(entry)) return;
593 
594 	entryText = gtk_entry_get_text(GTK_ENTRY(entry));
595 	if(strlen(entryText)<1)return;
596 
597 	totalCharge = atoi(entryText);
598 	TotalCharges[0] = totalCharge;
599 
600 	comboSpinMultiplicity  = g_object_get_data(G_OBJECT (entry), "ComboSpinMultiplicity");
601 	if(GTK_IS_WIDGET(comboSpinMultiplicity)) setComboSpinMultiplicity(comboSpinMultiplicity);
602 
603 	labelNumberOfElectrons = g_object_get_data(G_OBJECT (entry), "LabelNumberOfElectrons");
604 
605 	if(GTK_IS_WIDGET(labelNumberOfElectrons))
606 	{
607 		gint ne = psicodeMolecule.numberOfValenceElectrons - totalCharge;
608 		gchar buffer[BSIZE];
609 		sprintf(buffer, "Number of electrons = %d",ne);
610 		gtk_label_set_text(GTK_LABEL(labelNumberOfElectrons),buffer);
611 	}
612 }
613 /**********************************************************************/
addComboListToATable(GtkWidget * table,gchar ** list,gint nlist,gint i,gint j,gint k)614 static GtkWidget* addComboListToATable(GtkWidget* table,
615 		gchar** list, gint nlist, gint i, gint j, gint k)
616 {
617 	GtkWidget *entry = NULL;
618 	GtkWidget *combo = NULL;
619 
620 	combo = create_combo_box_entry(list, nlist, TRUE, -1, -1);
621 
622 	gtk_table_attach(GTK_TABLE(table),combo,j,j+k,i,i+1,
623 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
624 		(GtkAttachOptions)	(GTK_FILL | GTK_SHRINK),
625                   2,2);
626 	entry = GTK_BIN (combo)->child;
627 	g_object_set_data(G_OBJECT (entry), "Combo",combo);
628 	gtk_widget_set_size_request(GTK_WIDGET(entry),(gint)(ScreenHeight*0.2),-1);
629 
630 	return entry;
631 }
632 /***********************************************************************************************/
addPsicodeChargeToTable(GtkWidget * table,gint i)633 static GtkWidget *addPsicodeChargeToTable(GtkWidget *table, gint i)
634 {
635 	GtkWidget* entryCharge = NULL;
636 	GtkWidget* comboCharge = NULL;
637 	gint nlistCharge = 1;
638 	gchar* listCharge[] = {"0"};
639 
640 	add_label_table(table,_("Charge"),(gushort)i,0);
641 	add_label_table(table,":",(gushort)i,1);
642 	entryCharge = addComboListToATable(table, listCharge, nlistCharge, i, 2, 1);
643 	comboCharge  = g_object_get_data(G_OBJECT (entryCharge), "Combo");
644 	gtk_widget_set_sensitive(entryCharge, FALSE);
645 
646 	return comboCharge;
647 }
648 /***********************************************************************************************/
addPsicodeSpinToTable(GtkWidget * table,gint i)649 static GtkWidget *addPsicodeSpinToTable(GtkWidget *table, gint i)
650 {
651 	GtkWidget* entrySpinMultiplicity = NULL;
652 	GtkWidget* comboSpinMultiplicity = NULL;
653 	gint nlistspinMultiplicity = 1;
654 	gchar* listspinMultiplicity[] = {"0"};
655 
656 	add_label_table(table,_("Spin multiplicity"),(gushort)i,0);
657 	add_label_table(table,":",(gushort)i,1);
658 	entrySpinMultiplicity = addComboListToATable(table, listspinMultiplicity, nlistspinMultiplicity, i, 2, 1);
659 	comboSpinMultiplicity  = g_object_get_data(G_OBJECT (entrySpinMultiplicity), "Combo");
660 	gtk_widget_set_sensitive(entrySpinMultiplicity, FALSE);
661 
662 	g_signal_connect(G_OBJECT(entrySpinMultiplicity),"changed", G_CALLBACK(changedEntrySpinMultiplicity),NULL);
663 	return comboSpinMultiplicity;
664 }
665 /***********************************************************************************************/
addLabelNumberOfElectronsToTable(GtkWidget * table,gint i,GtkWidget * comboCharge)666 static GtkWidget *addLabelNumberOfElectronsToTable(GtkWidget *table, gint i, GtkWidget *comboCharge)
667 {
668 	GtkWidget* labelNumberOfElectrons = NULL;
669 	GtkWidget* hbox = NULL;
670 	GtkWidget* entryCharge = GTK_BIN(comboCharge)->child;
671 
672 	labelNumberOfElectrons = gtk_label_new(" ");
673 	hbox = gtk_hbox_new(0,FALSE);
674 	gtk_box_pack_start (GTK_BOX (hbox), labelNumberOfElectrons, FALSE, FALSE, 0);
675 	gtk_table_attach(GTK_TABLE(table),hbox,0,0+3,i,i+1,
676 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
677 		(GtkAttachOptions)	(GTK_FILL | GTK_SHRINK),
678                   2,2);
679 
680 	g_object_set_data(G_OBJECT (entryCharge), "LabelNumberOfElectrons", labelNumberOfElectrons);
681 	g_signal_connect(G_OBJECT(entryCharge),"changed", G_CALLBACK(changedEntryCharge),NULL);
682 	return labelNumberOfElectrons;
683 }
684 /***********************************************************************************************/
createPsicodeChargeMultiplicityFrame(GtkWidget * box)685 void createPsicodeChargeMultiplicityFrame(GtkWidget *box)
686 {
687 	GtkWidget* frame;
688 	GtkWidget* sep;
689 	GtkWidget* labelNumberOfElectrons;
690 	GtkWidget* vboxFrame;
691 	GtkWidget* comboSpinMultiplicity = NULL;
692 	GtkWidget* comboCharge = NULL;
693 	GtkWidget *table = NULL;
694 	gint i;
695 
696 	totalCharge = TotalCharges[0];
697 	spinMultiplicity=SpinMultiplicities[0];
698 
699 	table = gtk_table_new(3,5,FALSE);
700 
701 	frame = gtk_frame_new (_("Charge & Multiplicty"));
702 	gtk_widget_show (frame);
703 	gtk_box_pack_start (GTK_BOX (box), frame, TRUE, TRUE, 3);
704 	gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
705 
706 	vboxFrame = gtk_vbox_new (FALSE, 3);
707 	gtk_widget_show (vboxFrame);
708 	gtk_container_add (GTK_CONTAINER (frame), vboxFrame);
709 
710 	gtk_box_pack_start (GTK_BOX (vboxFrame), table, TRUE, TRUE, 0);
711 
712 	i = 0;
713 	comboCharge = addPsicodeChargeToTable(table, i);
714 	i = 1;
715 	comboSpinMultiplicity = addPsicodeSpinToTable(table, i);
716 	i = 2;
717 	sep = gtk_hseparator_new ();;
718 	gtk_table_attach(GTK_TABLE(table),sep,0,0+3,i,i+1,
719 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
720 		(GtkAttachOptions)	(GTK_FILL | GTK_EXPAND),
721                   2,2);
722 
723 	i = 3;
724 	labelNumberOfElectrons=addLabelNumberOfElectronsToTable(table, i, comboCharge);
725 
726 	if(GTK_IS_COMBO_BOX(comboCharge))
727 		g_object_set_data(G_OBJECT (GTK_BIN(comboCharge)->child), "ComboSpinMultiplicity", comboSpinMultiplicity);
728 	setComboCharge(comboCharge);
729 	setComboSpinMultiplicity(comboSpinMultiplicity);
730 	if(GTK_IS_WIDGET(labelNumberOfElectrons))
731 	{
732 		gint ne = psicodeMolecule.numberOfValenceElectrons - totalCharge;
733 		gchar buffer[BSIZE];
734 		sprintf(buffer, "Number of electrons = %d",ne);
735 		gtk_label_set_text(GTK_LABEL(labelNumberOfElectrons),buffer);
736 	}
737 
738 	/* activate sensitivity */
739 	/*
740 	if(GTK_IS_WIDGET(comboMethod)) setComboMethod(comboMethod);
741 	g_object_set_data(G_OBJECT (box), "EntryMethod", GTK_BIN(comboMethod)->child);
742 	*/
743 }
744 /************************************************************************************************************/
745