OSDN Git Service

On importing Gamess output, the energy values are read and set as the property.
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Sat, 14 Jun 2014 11:15:57 +0000 (11:15 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Sat, 14 Jun 2014 11:15:57 +0000 (11:15 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@548 a2be9bc6-48de-4e38-9406-05402d4bc13c

MolLib/MolAction.c
MolLib/MolAction.h
MolLib/Molecule.c
MolLib/Molecule.h
MolLib/Ruby_bind/ruby_bind.c
Scripts/commands.rb
Scripts/gamess.rb
Scripts/loadsave.rb
wxSources/RubyDialogFrame.cpp
wxSources/menu.mm

index 91c044c..06a774a 100644 (file)
@@ -50,6 +50,7 @@ const char *gMolActionSetAtomVelocities = "atomVelocity:GV";
 const char *gMolActionSetAtomForces   = "atomForce:GV";
 const char *gMolActionInsertFrames    = "insertFrames:GVV";
 const char *gMolActionRemoveFrames    = "removeFrames:G";
+const char *gMolActionReorderFrames   = "reorderFrames:I";
 const char *gMolActionSetProperty     = "setProperty:iGD";
 const char *gMolActionSetSelection    = "selection:G";
 const char *gMolActionChangeResidueNumber = "changeResSeq:Gi";
@@ -1307,6 +1308,33 @@ s_MolActionRemoveFrames(Molecule *mol, MolAction *action, MolAction **actp)
 }
 
 static int
+s_MolActionReorderFrames(Molecule *mol, MolAction *action, MolAction **actp)
+{
+       Int *ip, *ip2, i, n;
+
+       ip = action->args[0].u.arval.ptr;
+       
+       /*  Prepare undo data (and error check)  */
+       n = MoleculeGetNumberOfFrames(mol);
+       ip2 = (Int *)malloc(sizeof(Int) * n);
+       for (i = 0; i < n; i++) {
+               if (ip[i] < 0 || ip[i] >= n) {
+                       free(ip2);
+                       return -1;
+               }
+               ip2[ip[i]] = i;
+       }
+
+       MoleculeReorderFrames(mol, ip);
+       
+       *actp = MolActionNew(gMolActionReorderFrames, n, ip2);
+       (*actp)->frame = mol->cframe;
+       free(ip2);
+       
+       return 0;
+}
+
+static int
 s_MolActionSetProperty(Molecule *mol, MolAction *action, MolAction **actp)
 {
        Int idx, n1, no_undo;
@@ -1908,6 +1936,9 @@ MolActionPerform(Molecule *mol, MolAction *action)
                if ((result = s_MolActionRemoveFrames(mol, action, &act2)) != 0)
                        return result;
                needsSymmetryAmendment = 1;
+       } else if (strcmp(action->name, gMolActionReorderFrames) == 0) {
+               if ((result = s_MolActionReorderFrames(mol, action, &act2)) != 0)
+                       return result;
        } else if (strcmp(action->name, gMolActionSetProperty) == 0) {
                if ((result = s_MolActionSetProperty(mol, action, &act2)) != 0)
                        return result;
index c893191..85754a8 100644 (file)
@@ -51,6 +51,7 @@ extern const char *gMolActionSetAtomVelocities;
 extern const char *gMolActionSetAtomForces;
 extern const char *gMolActionInsertFrames;
 extern const char *gMolActionRemoveFrames;
+extern const char *gMolActionReorderFrames;
 extern const char *gMolActionSetProperty;
 extern const char *gMolActionSetSelection;
 extern const char *gMolActionChangeResidueNumber;
index b8dedb0..222d747 100755 (executable)
@@ -479,10 +479,6 @@ MoleculeClear(Molecule *mp)
                ParameterRelease(mp->par);
                mp->par = NULL;
        }
-       if (mp->bset != NULL) {
-               BasisSetRelease(mp->bset);
-               mp->bset = NULL;
-       }
        if (mp->atoms != NULL) {
                for (i = 0; i < mp->natoms; i++)
                        AtomClean(mp->atoms + i);
@@ -538,13 +534,7 @@ MoleculeClear(Molecule *mp)
                mp->bset = NULL;
        }
        if (mp->mcube != NULL) {
-               free(mp->mcube->dp);
-               free(mp->mcube->radii);
-               free(mp->mcube->c[0].cubepoints);
-               free(mp->mcube->c[0].triangles);
-               free(mp->mcube->c[1].cubepoints);
-               free(mp->mcube->c[1].triangles);
-               free(mp->mcube);
+               MoleculeDeallocateMCube(mp->mcube);
                mp->mcube = NULL;
        }
        if (mp->molprops != NULL) {
@@ -1966,10 +1956,9 @@ MoleculeLoadPsfFile(Molecule *mp, const char *fname, char **errbuf)
        if (fn > 1) {
                for (i = 0; i < mp->natoms; i++) {
                        ap = ATOM_AT_INDEX(mp->atoms, i);
-                       ap->frames = (Vector *)malloc(sizeof(Vector) * fn);
+                       NewArray(&ap->frames, &ap->nframes, sizeof(Vector), fn);
                        if (ap->frames == NULL)
                                goto panic;
-                       ap->nframes = fn;
                        for (j = 0; j < fn; j++)
                                ap->frames[j] = frames[mp->natoms * j + i];
                }
@@ -2542,17 +2531,22 @@ MoleculeGetMOCoefficients(Molecule *mol, Int idx, Double *energy, Int *ncoeffs,
        return 0;
 }
 
-/*  Allocate BasisSet record. rflag: UHF, 0; RHF, 1; ROHF, 2
+/*  Allocate BasisSet record. rflag: 0, UHF; 1, RHF; 2, ROHF; -1, clear
     ne_alpha: number of alpha electrons, ne_beta: number of beta electrons
     The natoms and pos are copied from mol.  */
 int
 MoleculeAllocateBasisSetRecord(Molecule *mol, Int rflag, Int ne_alpha, Int ne_beta)
 {
        BasisSet *bset;
-/*     int i;
-       Atom *ap; */
        if (mol == NULL || mol->natoms == 0)
                return -1;  /*  Molecule is empty  */
+       if (rflag < 0) {
+               if (mol->bset != NULL) {
+                       BasisSetRelease(mol->bset);
+                       mol->bset = NULL;
+               }
+               return 0;
+       }
        bset = mol->bset;
        if (bset == NULL) {
                bset = mol->bset = (BasisSet *)calloc(sizeof(BasisSet), 1);
@@ -5100,7 +5094,10 @@ MoleculeDeserialize(const char *data, Int length, Int *timep)
                        for (i = 0, ap = mp->atoms; i < mp->natoms; i++, ap = ATOM_NEXT(ap)) {
                                if (ap->nframes == 0)
                                        continue;
-                               ap->frames = (Vector *)malloc(sizeof(Vector) * ap->nframes);
+                               n = ap->nframes;
+                               ap->frames = NULL;
+                               ap->nframes = 0;
+                               NewArray(&ap->frames, &ap->nframes, sizeof(Vector), n);
                                if (ap->frames == NULL)
                                        goto out_of_memory;
                                memmove(ap->frames, ptr, sizeof(Vector) * ap->nframes);
@@ -10095,17 +10092,14 @@ MoleculeInsertFrames(Molecule *mp, IntGroup *group, const Vector *inFrame, const
        
        /*  Expand ap->frames for all atoms  */
        for (i = 0, ap = mp->atoms; i < mp->natoms; i++, ap = ATOM_NEXT(ap)) {
-               if (ap->frames == NULL)
-                       vp = (Vector *)calloc(sizeof(Vector), n_new);
-               else
-                       vp = (Vector *)realloc(ap->frames, sizeof(Vector) * n_new);
-               if (vp == NULL) {
+               Int n = ap->nframes;
+               AssignArray(&ap->frames, &ap->nframes, sizeof(Vector), n_new - 1, NULL);
+               if (ap->frames == NULL) {
                        __MoleculeUnlock(mp);
                        return -1;
                }
-               for (j = ap->nframes; j < n_new; j++)
-                       vp[j] = ap->r;
-               ap->frames = vp;
+               for (j = n; j < n_new; j++)
+                       ap->frames[j] = ap->r;
        }
        if (mp->cell != NULL) {
                j = mp->nframe_cells;
@@ -10304,11 +10298,12 @@ MoleculeRemoveFrames(Molecule *mp, IntGroup *inGroup, Vector *outFrame, Vector *
                        mult = sizeof(Vector);
                        vp = ap->frames;
                        if (vp == NULL) {
-                               ap->frames = vp = (Vector *)calloc(sizeof(Vector), n_old);
-                               if (vp == NULL) {
+                               NewArray(&ap->frames, &ap->nframes, sizeof(Vector), n_old);
+                               if (ap->frames == NULL) {
                                        __MoleculeUnlock(mp);
                                        return -1;
                                }
+                               vp = ap->frames;
                        }
                        old_count = ap->nframes;
                } else {
@@ -10367,9 +10362,10 @@ MoleculeRemoveFrames(Molecule *mp, IntGroup *inGroup, Vector *outFrame, Vector *
                                prp->propvals = (Double *)realloc(prp->propvals, sizeof(Double));
                        }
                } else {
-                       if (i < mp->natoms)
-                               ap->frames = (Vector *)realloc(ap->frames, sizeof(Vector) * s);
-                       else if (i == mp->natoms) {
+                       if (i < mp->natoms) {
+                               AssignArray(&ap->frames, &ap->nframes, sizeof(Vector), s - 1, NULL);
+                               ap->nframes = s;
+                       } else if (i == mp->natoms) {
                                AssignArray(&mp->frame_cells, &mp->nframe_cells, sizeof(Vector) * 4, s - 1, NULL);
                                mp->nframe_cells = s;
                        } else {
@@ -10414,7 +10410,7 @@ MoleculeSelectFrame(Molecule *mp, int frame, int copyback)
                        /*  Write the current coordinate back to the frame array  */
                        ap->frames[cframe] = ap->r;
                }
-               if (frame != cframe && frame >= 0 && frame < ap->nframes) {
+               if ((frame != cframe || copyback == 0) && frame >= 0 && frame < ap->nframes) {
                        /*  Read the coordinate from the frame array  */
                        ap->r = ap->frames[frame];
                        modified = 1;
@@ -10431,7 +10427,7 @@ MoleculeSelectFrame(Molecule *mp, int frame, int copyback)
                        vp[3] = mp->cell->origin;
                }
                /*  Set the cell from the frame array  */
-               if (frame != cframe && frame >= 0 && frame < mp->nframe_cells) {
+               if ((frame != cframe || copyback == 0) && frame >= 0 && frame < mp->nframe_cells) {
                        MoleculeSetPeriodicBox(mp, &mp->frame_cells[frame * 4], &mp->frame_cells[frame * 4 + 1], &mp->frame_cells[frame * 4 + 2], &mp->frame_cells[frame * 4 + 3], mp->cell->flags, 0);
                        modified = 1;
                        MoleculeAmendBySymmetry(mp, NULL, NULL, NULL);
@@ -10456,6 +10452,76 @@ MoleculeFlushFrames(Molecule *mp)
        return nframes;
 }
 
+int
+MoleculeReorderFrames(Molecule *mp, const Int *old_idx)
+{
+       Int *ip, i, j, n, nframes;
+       Double *dp;
+       Atom *ap;
+       MolProp *prp;
+       if (mp == NULL || old_idx == NULL)
+               return 0;
+       nframes = MoleculeGetNumberOfFrames(mp);
+       MoleculeFlushFrames(mp);
+       ip = (Int *)malloc(sizeof(Int) * nframes);
+       if (ip == NULL)
+               return -1;  /*  Out of memory  */
+       memset(ip, 0, sizeof(Int) * nframes);
+       /*  Check the argument  */
+       for (i = 0; i < nframes; i++) {
+               j = old_idx[i];
+               if (j < 0 || j >= nframes || ip[j] != 0) {
+                       free(ip);
+                       return -2;  /*  Bad argument  */
+               }
+               ip[j] = 1;
+       }
+       free(ip);
+       dp = (Double *)malloc(sizeof(Double) * nframes * 12);
+       for (i = 0, ap = mp->atoms, prp = mp->molprops; i <= mp->natoms + mp->nmolprops; i++) {
+               for (j = 0; j < nframes; j++) {
+                       n = old_idx[j];
+                       if (i < mp->natoms) {
+                               ((Vector *)dp)[j] = (n < ap->nframes ? ap->frames[n] : ap->r);
+                       } else if (i == mp->natoms) {
+                               if (mp->cell != NULL) {
+                                       if (n < mp->nframe_cells && mp->frame_cells != NULL)
+                                               memmove(dp + j * 12, mp->frame_cells + n * 4, sizeof(Vector) * 4);
+                                       else {
+                                               ((Vector *)dp)[j * 4] = mp->cell->axes[0];
+                                               ((Vector *)dp)[j * 4] = mp->cell->axes[1];
+                                               ((Vector *)dp)[j * 4] = mp->cell->axes[2];
+                                               ((Vector *)dp)[j * 4] = mp->cell->origin;
+                                       }
+                               }
+                       } else {
+                               dp[j] = prp->propvals[n];
+                       }
+               }
+               for (j = 0; j < nframes; j++) {
+                       if (i < mp->natoms) {
+                               if (ap->nframes <= j)
+                                       AssignArray(&ap->frames, &ap->nframes, sizeof(Vector), nframes - 1, NULL);
+                               ap->frames[j] = ((Vector *)dp)[j];
+                       } else if (i == mp->natoms) {
+                               if (mp->cell != NULL) {
+                                       AssignArray(&mp->frame_cells, &mp->nframe_cells, sizeof(Vector) * 4, nframes - 1, NULL);
+                                       memmove(mp->frame_cells + j * 4, dp + j * 12, sizeof(Vector) * 4);
+                               }
+                       } else {
+                               prp->propvals[j] = dp[j];
+                       }
+               }
+               if (i < mp->natoms)
+                       ap = ATOM_NEXT(ap);
+               else if (i > mp->natoms)
+                       prp++;
+       }
+       free(dp);
+       MoleculeSelectFrame(mp, mp->cframe, 0);
+       return 0;
+}
+
 #pragma mark ====== Molecule Propeties ======
 
 int
@@ -10479,7 +10545,7 @@ MoleculeCreateProperty(Molecule *mp, const char *name)
                return -10000;
        AssignArray(&mp->molprops, &mp->nmolprops, sizeof(MolProp), mp->nmolprops, prp);
        free(prp);
-       return mp->nmolprops;
+       return mp->nmolprops - 1;
 }
 
 int
@@ -11942,3 +12008,15 @@ end:
        
        return retval;
 }
+
+void
+MoleculeDeallocateMCube(MCube *mcube)
+{
+       free(mcube->dp);
+       free(mcube->radii);
+       free(mcube->c[0].cubepoints);
+       free(mcube->c[0].triangles);
+       free(mcube->c[1].cubepoints);
+       free(mcube->c[1].triangles);
+       free(mcube);
+}
index 1e4736f..18cac8f 100755 (executable)
@@ -386,6 +386,8 @@ typedef struct Molecule {
 
 int strlen_limit(const char *s, int limit);
 
+void BasisSetRelease(BasisSet *bset);
+
 Molecule *MoleculeNew(void);
 int MoleculeLoadFile(Molecule *mp, const char *fname, const char *ftype, char **errbuf);
 int MoleculeLoadPsfFile(Molecule *mp, const char *fname, char **errbuf);
@@ -560,6 +562,7 @@ int MoleculeInsertFrames(Molecule *mp, IntGroup *group, const Vector *inFrame, c
 int MoleculeRemoveFrames(Molecule *mp, IntGroup *group, Vector *outFrame, Vector *outFrameCell);
 int MoleculeSelectFrame(Molecule *mp, int frame, int copyback);
 int MoleculeFlushFrames(Molecule *mp);
+int MoleculeReorderFrames(Molecule *mp, const Int *old_idx);
 
 int MoleculeCreateProperty(Molecule *mp, const char *name);
 int MoleculeLookUpProperty(Molecule *mp, const char *name);
@@ -580,6 +583,7 @@ int MoleculeOutputCube(Molecule *mp, Int index, const char *fname, const char *c
 
 MCube *MoleculeClearMCube(Molecule *mol, Int nx, Int ny, Int nz, const Vector *origin, Double dx, Double dy, Double dz);
 int MoleculeUpdateMCube(Molecule *mol, int idn);
+void MoleculeDeallocateMCube(MCube *mcube);
 
 extern char *gMoleculePasteboardType;
 extern char *gParameterPasteboardType;
index 081a6d3..60ca518 100644 (file)
@@ -7712,39 +7712,6 @@ s_Molecule_EachFrame(VALUE self)
 
 /*
  *  call-seq:
- *     set_atom_attr(index, key, value)
- *
- *  Set the atom attribute for the specified atom.
- *  This operation is undoable.
- */
-static VALUE
-s_Molecule_SetAtomAttr(VALUE self, VALUE idx, VALUE key, VALUE val)
-{
-       Molecule *mol;
-       VALUE aref, oldval;
-    Data_Get_Struct(self, Molecule, mol);
-       aref = ValueFromMoleculeAndIndex(mol, s_Molecule_AtomIndexFromValue(mol, idx));
-       oldval = s_AtomRef_GetAttr(aref, key);
-       if (val == Qundef)
-               return oldval;
-       s_AtomRef_SetAttr(aref, key, val);
-       return val;
-}
-
-/*
- *  call-seq:
- *     get_atom_attr(index, key)
- *
- *  Get the atom attribute for the specified atom.
- */
-static VALUE
-s_Molecule_GetAtomAttr(VALUE self, VALUE idx, VALUE key)
-{
-       return s_Molecule_SetAtomAttr(self, idx, key, Qundef);
-}
-
-/*
- *  call-seq:
  *     get_coord_from_frame(index, group = nil)
  *
  *  Copy the coordinates from the indicated frame. If group is specified, only the specified atoms
@@ -7802,9 +7769,93 @@ s_Molecule_GetCoordFromFrame(int argc, VALUE *argv, VALUE self)
                }
                IntGroupIteratorRelease(&iter);
        }
+       /*  Copy the extra properties  */
        IntGroupRelease(ig);
+       for (i = 0; i < mol->nmolprops; i++) {
+               Double *dp = (Double *)malloc(sizeof(Double));
+               ig = IntGroupNew();
+               IntGroupAdd(ig, mol->cframe, 1);
+               *dp = mol->molprops[i].propvals[index];
+               MolActionCreateAndPerform(mol, gMolActionSetProperty, i, ig, 1, dp);
+               free(dp);
+               IntGroupRelease(ig);
+       }
+       
+       return self;
+}
+
+/*
+ *  call-seq:
+ *     reorder_frames(old_indices)
+ *
+ *  Reorder the frames. The argument is an array of integers that specify the 'old' 
+ *  frame numbers. Thus, if the argument is [2,0,1], then the new frames 0/1/2 are the
+ *  same as the old frames 2/0/1, respectively.
+ *  The argument must have the same number of integers as the number of frames.
+ */
+static VALUE
+s_Molecule_ReorderFrames(VALUE self, VALUE aval)
+{
+       Molecule *mol;
+       Int *ip, *ip2, i, n, nframes;
+    Data_Get_Struct(self, Molecule, mol);
+       aval = rb_ary_to_ary(aval);
+       nframes = MoleculeGetNumberOfFrames(mol);
+       if (RARRAY_LEN(aval) != nframes)
+               rb_raise(rb_eMolbyError, "The argument must have the same number of integers as the number of frames");
+       ip2 = (Int *)calloc(sizeof(Int), nframes);
+       ip = (Int *)calloc(sizeof(Int), nframes);
+       for (i = 0; i < nframes; i++) {
+               n = NUM2INT(rb_Integer(RARRAY_PTR(aval)[i]));
+               if (n < 0 || n >= nframes || ip2[n] != 0) {
+                       free(ip2);
+                       free(ip);
+                       if (n < 0 || n >= nframes)
+                               rb_raise(rb_eMolbyError, "The argument (%d) is out of range", n);
+                       else
+                               rb_raise(rb_eMolbyError, "The argument has duplicated entry (%d)", n);
+               }
+               ip2[n] = 1;
+               ip[i] = n;
+       }
+       free(ip2);
+       MolActionCreateAndPerform(mol, gMolActionReorderFrames, nframes, ip);
+       free(ip);
        return self;
 }
+       
+/*
+ *  call-seq:
+ *     set_atom_attr(index, key, value)
+ *
+ *  Set the atom attribute for the specified atom.
+ *  This operation is undoable.
+ */
+static VALUE
+s_Molecule_SetAtomAttr(VALUE self, VALUE idx, VALUE key, VALUE val)
+{
+       Molecule *mol;
+       VALUE aref, oldval;
+    Data_Get_Struct(self, Molecule, mol);
+       aref = ValueFromMoleculeAndIndex(mol, s_Molecule_AtomIndexFromValue(mol, idx));
+       oldval = s_AtomRef_GetAttr(aref, key);
+       if (val == Qundef)
+               return oldval;
+       s_AtomRef_SetAttr(aref, key, val);
+       return val;
+}
+
+/*
+ *  call-seq:
+ *     get_atom_attr(index, key)
+ *
+ *  Get the atom attribute for the specified atom.
+ */
+static VALUE
+s_Molecule_GetAtomAttr(VALUE self, VALUE idx, VALUE key)
+{
+       return s_Molecule_SetAtomAttr(self, idx, key, Qundef);
+}
 
 /*
  *  call-seq:
@@ -10209,6 +10260,31 @@ s_Molecule_Elpot(VALUE self, VALUE ival)
 
 /*
  *  call-seq:
+ *     clear_basis_set
+ *
+ *  Clear the existing basis set info. All gaussian coefficients, MO energies and coefficients,
+ *  cube and marching cube information are discarded. This operation is _not_ undoable!
+ */
+static VALUE
+s_Molecule_ClearBasisSet(VALUE self)
+{
+       Molecule *mol;
+    Data_Get_Struct(self, Molecule, mol);
+       if (mol != NULL) {
+               if (mol->bset != NULL) {
+                       BasisSetRelease(mol->bset);
+                       mol->bset = NULL;
+               }
+               if (mol->mcube != NULL) {
+                       MoleculeDeallocateMCube(mol->mcube);
+                       mol->mcube = NULL;
+               }
+       }
+       return self;
+}
+
+/*
+ *  call-seq:
  *     add_gaussian_orbital_shell(sym, nprims, atom_index)
  *
  *  To be used internally. Add a gaussian orbital shell with symmetry code, number of primitives,
@@ -10264,25 +10340,27 @@ s_Molecule_AddGaussianPrimitiveCoefficients(VALUE self, VALUE expval, VALUE cval
 
 /*
  *  call-seq:
- *     mo_type
+ *     clear_mo_coefficients
  *
- *  Returns either "RHF", "UHF", or "ROHF". If no MO info is present, returns nil.
+ *  Clear the existing MO coefficients.
  */
 static VALUE
-s_Molecule_MOType(VALUE self)
+s_Molecule_ClearMOCoefficients(VALUE self)
 {
        Molecule *mol;
-    Data_Get_Struct(self, Molecule, mol);
-       if (mol != NULL && mol->bset != NULL) {
-               const char *s;
-               int rflag = mol->bset->rflag;
-               if (rflag == 0)
-                       s = "UHF";
-               else if (rflag == 2)
-                       s = "ROHF";
-               else s = "RHF";
-               return rb_str_new2(s);
-       } else return Qnil;
+       Data_Get_Struct(self, Molecule, mol);
+       if (mol->bset != NULL) {
+               if (mol->bset->moenergies != NULL) {
+                       free(mol->bset->moenergies);
+                       mol->bset->moenergies = NULL;
+               }
+               if (mol->bset->mo != NULL) {
+                       free(mol->bset->mo);
+                       mol->bset->mo = NULL;
+               }
+               mol->bset->nmos = 0;
+       }
+       return self;
 }
 
 /*
@@ -10385,6 +10463,108 @@ s_Molecule_GetMOEnergy(VALUE self, VALUE ival)
        return rb_float_new(energy);
 }
 
+static VALUE sTypeSym, sAlphaSym, sBetaSym;
+
+static inline void
+s_InitMOInfoKeys(void)
+{
+       if (sTypeSym == 0) {
+               sTypeSym = ID2SYM(rb_intern("type"));
+               sAlphaSym = ID2SYM(rb_intern("alpha"));
+               sBetaSym = ID2SYM(rb_intern("beta"));
+       }
+}
+
+/*
+ *  call-seq:
+ *     set_mo_info(hash)
+ *
+ *  Set the MO info. hash keys: :type=>"RHF"|"UHF"|"ROHF",
+ *  :alpha=>integer, :beta=>integer
+ */
+static VALUE
+s_Molecule_SetMOInfo(VALUE self, VALUE hval)
+{
+       Molecule *mol;
+       VALUE aval;
+       Int rflag, na, nb, n;
+       char *s;
+    Data_Get_Struct(self, Molecule, mol);
+       if (mol->bset != NULL) {
+               rflag = mol->bset->rflag;
+               na = mol->bset->ne_alpha;
+               nb = mol->bset->ne_beta;
+       } else {
+               rflag = 1;
+               na = 0;
+               nb = 0;
+       }
+       if (hval != Qnil) {
+               if ((aval = rb_hash_aref(hval, sTypeSym)) != Qnil) {
+                       s = StringValuePtr(aval);
+                       if (strcasecmp(s, "RHF") == 0)
+                               rflag = 1;
+                       else if (strcasecmp(s, "UHF") == 0)
+                               rflag = 0;
+                       else if (strcasecmp(s, "ROHF") == 0)
+                               rflag = 2;
+               }
+               if ((aval = rb_hash_aref(hval, sAlphaSym)) != Qnil) {
+                       n = NUM2INT(rb_Integer(aval));
+                       if (n >= 0)
+                               na = n;
+               }
+               if ((aval = rb_hash_aref(hval, sBetaSym)) != Qnil) {
+                       n = NUM2INT(rb_Integer(aval));
+                       if (n >= 0)
+                               nb = n;
+               }
+               MoleculeAllocateBasisSetRecord(mol, rflag, na, nb);
+       }
+       return self;
+}
+
+/*
+ *  call-seq:
+ *     get_mo_info(key)
+ *
+ *  Get the MO info. The key is as described in set_mo_info.
+ */
+static VALUE
+s_Molecule_GetMOInfo(VALUE self, VALUE kval)
+{
+       Molecule *mol;
+    Data_Get_Struct(self, Molecule, mol);
+       if (mol->bset == NULL)
+               rb_raise(rb_eMolbyError, "No MO information is defined");
+       if (kval == sTypeSym) {
+               switch (mol->bset->rflag) {
+                       case 0: return rb_str_new2("UHF");
+                       case 1: return rb_str_new2("RHF");
+                       case 2: return rb_str_new2("ROHF");
+                       default: return rb_str_to_str(INT2NUM(mol->bset->rflag));
+               }
+       } else if (kval == sAlphaSym) {
+               return INT2NUM(mol->bset->ne_alpha);
+       } else if (kval == sBetaSym) {
+               return INT2NUM(mol->bset->ne_beta);
+       } else return Qnil;
+}
+
+/*
+ *  call-seq:
+ *     mo_type
+ *
+ *  Returns either "RHF", "UHF", or "ROHF". If no MO info is present, raises exception.
+ */
+static VALUE
+s_Molecule_MOType(VALUE self)
+{
+       return s_Molecule_GetMOInfo(self, sTypeSym);
+}
+
+
+#if 0
 /*
  *  call-seq:
  *     allocate_basis_set_record(rflag, ne_alpha, ne_beta)
@@ -10410,6 +10590,7 @@ s_Molecule_AllocateBasisSetRecord(VALUE self, VALUE rval, VALUE naval, VALUE nbv
                rb_raise(rb_eMolbyError, "Unknown error");
        return self;
 }
+#endif
 
 /*
  *  call-seq:
@@ -10688,7 +10869,7 @@ s_Molecule_PropertyNames(VALUE self)
 {
        Molecule *mol;
        VALUE rval, nval;
-       int i, n;
+       int i;
     Data_Get_Struct(self, Molecule, mol);
        rval = rb_ary_new();
        for (i = mol->nmolprops - 1; i >= 0; i--) {
@@ -11105,6 +11286,7 @@ Init_Molby(void)
        rb_define_alias(rb_cMolecule, "create_frames", "create_frame");
        rb_define_alias(rb_cMolecule, "insert_frames", "insert_frame");
        rb_define_alias(rb_cMolecule, "remove_frames", "remove_frame");
+       rb_define_method(rb_cMolecule, "reorder_frames", s_Molecule_ReorderFrames, 1);
        rb_define_method(rb_cMolecule, "each_frame", s_Molecule_EachFrame, 0);
        rb_define_method(rb_cMolecule, "get_coord_from_frame", s_Molecule_GetCoordFromFrame, -1);
        rb_define_method(rb_cMolecule, "register_undo", s_Molecule_RegisterUndo, -1);
@@ -11203,13 +11385,17 @@ Init_Molby(void)
        rb_define_method(rb_cMolecule, "set_surface_attr", s_Molecule_SetSurfaceAttr, 1);
        rb_define_method(rb_cMolecule, "nelpots", s_Molecule_NElpots, 0);
        rb_define_method(rb_cMolecule, "elpot", s_Molecule_Elpot, 1);
+       rb_define_method(rb_cMolecule, "clear_basis_set", s_Molecule_ClearBasisSet, 0);
        rb_define_method(rb_cMolecule, "add_gaussian_orbital_shell", s_Molecule_AddGaussianOrbitalShell, 3);
        rb_define_method(rb_cMolecule, "add_gaussian_primitive_coefficients", s_Molecule_AddGaussianPrimitiveCoefficients, 3);
        rb_define_method(rb_cMolecule, "mo_type", s_Molecule_MOType, 0);
+       rb_define_method(rb_cMolecule, "clear_mo_coefficients", s_Molecule_ClearMOCoefficients, 0);
        rb_define_method(rb_cMolecule, "set_mo_coefficients", s_Molecule_SetMOCoefficients, 3);
        rb_define_method(rb_cMolecule, "get_mo_coefficients", s_Molecule_GetMOCoefficients, 1);
        rb_define_method(rb_cMolecule, "get_mo_energy", s_Molecule_GetMOEnergy, 1);
-       rb_define_method(rb_cMolecule, "allocate_basis_set_record", s_Molecule_AllocateBasisSetRecord, 3);
+       rb_define_method(rb_cMolecule, "get_mo_info", s_Molecule_GetMOInfo, 1);
+       rb_define_method(rb_cMolecule, "set_mo_info", s_Molecule_SetMOInfo, 1);
+/*     rb_define_method(rb_cMolecule, "allocate_basis_set_record", s_Molecule_AllocateBasisSetRecord, 3); */
        rb_define_method(rb_cMolecule, "search_equivalent_atoms", s_Molecule_SearchEquivalentAtoms, -1);
        
        rb_define_method(rb_cMolecule, "create_pi_anchor", s_Molecule_CreatePiAnchor, -1);
@@ -11381,6 +11567,8 @@ Init_Molby(void)
 
        s_ID_equal = rb_intern("==");
        g_RubyID_call = rb_intern("call");
+       
+       s_InitMOInfoKeys();
 }
 
 #pragma mark ====== External functions ======
index fe9451f..3b7cc7f 100755 (executable)
@@ -100,24 +100,56 @@ class Molecule
        end
   end
 
+  def cmd_reverse_frames
+    n = nframes
+    return if n == 0
+       hash = Dialog.run("Reverse Frames") {
+         layout(2,
+           item(:text, :title=>"Start"),
+           item(:textfield, :width=>120, :tag=>"start", :value=>"0"),
+               item(:text, :title=>"End"),
+               item(:textfield, :width=>120, :tag=>"end", :value=>(n - 1).to_s))
+       }
+       if hash[:status] == 0
+         sframe = Integer(hash["start"])
+         eframe = Integer(hash["end"])
+         return if sframe > eframe
+         eframe = n - 1 if eframe >= n
+         frames = (0...sframe).to_a + (sframe..eframe).to_a.reverse + ((eframe + 1)...n).to_a
+         reorder_frames(frames)
+       end
+  end
+
   def cmd_extra_properties
     mol = self
-       on_document_modified = lambda { |m|
-       }
        get_count = lambda { |it| mol.nframes }
-       get_value = lambda { |it, row, col| sprintf("%.8g", mol.get_property(col, row)) rescue "" }
+       get_value = lambda { |it, row, col|
+         if col == 0
+           row.to_s
+         else
+           sprintf("%.8f", mol.get_property(col - 1, row)) rescue ""
+         end
+    }
     Dialog.new("Extra Props:" + mol.name, nil, nil, :resizable=>true, :has_close_box=>true) {
-         columns = mol.property_names.map { |name| [name, 80] }
+         names = nil
+         on_document_modified = lambda { |m|
+           if (n = m.property_names) != names
+                 names = n
+                 col = [["frame", 40]] + names.map { |nn| [nn, 120] }
+                 item_with_tag("table")[:columns] = col
+               end
+               item_with_tag("table")[:refresh] = true
+         }
          layout(1,
-               item(:table, :width=>240, :height=>380, :flex=>[0,0,0,0,1,1], :tag=>"table",
-                 :columns=>columns,
+               item(:table, :width=>320, :height=>300, :flex=>[0,0,0,0,1,1], :tag=>"table",
                  :on_count=>get_count,
                  :on_get_value=>get_value),
            :flex=>[0,0,0,0,1,1]
          )
-         set_min_size(480, 200)
+         set_min_size(320, 200)
          listen(mol, "documentModified", on_document_modified)
          listen(mol, "documentWillClose", lambda { |m| close } )
+         on_document_modified.call(mol)
          show
        }
   end
@@ -155,6 +187,7 @@ register_menu("Offset residue...", :cmd_offset_residue, :non_empty)
 register_menu("Sort by residue", :cmd_sort_by_residue, :non_empty)
 register_menu("", "")
 register_menu("Delete Frames...", :cmd_delete_frames, lambda { |m| m && m.nframes > 1 } )
+register_menu("Reverse Frames...", :cmd_reverse_frames, lambda { |m| m && m.nframes > 1 } )
 register_menu("", "")
 register_menu("Open Extra Properties Window...", :cmd_extra_properties, lambda { |m| m && m.property_names.count > 0 } )
 #register_menu("cmd test", :cmd_test)
index 956faeb..065df14 100755 (executable)
@@ -404,7 +404,8 @@ class Molecule
     size = 0
     lines = []
     last_line = ""
-    
+    search_mode = 0
+
     #  Callback procs
        term_callback = lambda { |m, n|
          msg = "GAMESS execution on #{inpbase} "
@@ -469,13 +470,37 @@ class Molecule
           if line =~ /GEOMETRY SEARCH POINT NSERCH= *(\d+)/
             nserch = $1.to_i
             last_i = i
-          elsif line =~ /NSERCH:/
+                       search_mode = 1
+                       energy = nil
+                 elsif line =~ /CONSTRAINED OPTIMIZATION POINT/
+                   search_mode = 2
+                       energy = nil
+                 elsif line =~ /POINT *([0-9]+) *ON THE REACTION PATH/
+                   nserch = $1.to_i
+                       last_i = i
+          elsif line =~ /NSERCH: *([0-9]+)/
           #  print line
                        if mol
-                         dummy, n, grad = line.match(/NSERCH:[^0-9]*([0-9]+).*GRAD[^0-9]*([-.0-9]+)/).to_a
+                         n = $1
+                         line =~ /E= +([-.0-9]+)/
+                         energy = $1.to_f
+                         line =~ /GRAD\. MAX= +([-.0-9]+)/
+                         grad = $1
                          mol.show_text("Search: #{n}\nGradient: #{grad}")
+                         mol.set_property("energy", energy)
                        end
                        last_i = i
+                 elsif line =~ /TOTAL ENERGY += *([-.0-9]+)/
+                   energy = $1
+                       if mol && search_mode == 2
+                         mol.show_text("Point: #{nserch}\nEnergy: #{energy}")
+                       end
+                       energy = energy.to_f
+                 elsif line =~ /FINAL .* ENERGY IS +([-.0-9]+) *AFTER/
+                   energy = $1.to_f
+                       if mol && search_mode == 0
+                         mol.set_property("energy", energy)
+                       end
           elsif nserch > 0 && line =~ /ddikick\.x/
             last_i = -1
             break
@@ -488,6 +513,9 @@ class Molecule
                 coords.push(Vector3D[x.to_f, y.to_f, z.to_f])
               }
               mol.create_frame([coords])
+                         if search_mode == 1 && energy
+                           mol.set_property("energy", energy)
+                         end
               mol.display
               last_i = i + mol.natoms + 2
               i = last_i   #  Skip the processed lines
index f4e2ee7..38a7fe0 100755 (executable)
@@ -126,6 +126,67 @@ class Molecule
   alias :loadmdcrd :loadcrd
   alias :savemdcrd :savecrd
 
+  def sub_load_gamess_log_basis_set(lines, lineno)
+    ln = 0
+       while (line = lines[ln])
+               ln += 1
+               break if line =~ /SHELL\s+TYPE\s+PRIMITIVE/
+       end
+       ln += 1
+       i = -1
+       nprims = 0
+       sym = -10  #  undefined
+       ncomps = 0
+       while (line = lines[ln])
+               ln += 1
+               break if line =~ /TOTAL NUMBER OF BASIS SET/
+               if line =~ /^\s*$/
+                 #  End of one shell
+                 add_gaussian_orbital_shell(sym, nprims, i)
+                 nprims = 0
+                 sym = -10
+                 next
+               end
+               a = line.split
+               if a.length == 1
+                 i += 1
+                 ln += 1  #  Skip the blank line
+                 next
+               elsif a.length == 5 || a.length == 6
+                 if sym == -10
+                       case a[1]
+                       when "S"
+                         sym = 0; n = 1
+                       when "P"
+                         sym = 1; n = 3
+                       when "L"
+                         sym = -1; n = 4
+                       when "D"
+                         sym = 2; n = 6
+                       when "F"
+                         sym = 3; n = 10
+                       when "G"
+                         sym = 4; n = 15
+                       else
+                         raise MolbyError, "Unknown gaussian shell type at line #{lineno + ln}"
+                       end
+                       ncomps += n
+                 end
+                 if (a.length == 5 && sym == -1) || (a.length == 6 && sym != -1)
+                       raise MolbyError, "Wrong format in gaussian shell information at line #{lineno + ln}"
+                 end
+                 exp = Float(a[3])
+                 c = Float(a[4])
+                 csp = Float(a[5] || 0.0)
+                 add_gaussian_primitive_coefficients(exp, c, csp)
+                 nprims += 1
+               else
+                 raise MolbyError, "Error in reading basis set information at line #{lineno + ln}"
+               end
+       end
+       return ncomps
+  end
+  
   def sub_load_gamess_log(fp)
 
     if natoms == 0
@@ -136,17 +197,19 @@ class Molecule
        self.update_enabled = false
        mes = "Loading GAMESS log file"
        show_progress_panel(mes)
-       energy = 0.0
+       energy = nil
        ne_alpha = ne_beta = 0   #  number of electrons
        rflag = nil  #  0, UHF; 1, RHF; 2, ROHF
        mo_count = 0
+       search_mode = 0   #  0, no search; 1, optimize; 2, irc
        ncomps = 0   #  Number of AO terms per one MO (sum of the number of components over all shells)
        alpha_beta = nil   #  Flag to read alpha/beta MO appropriately
+       nsearch = 0  #  Search number for optimization
        begin
-               if nframes > 0
-                       create_frame
-                       frame = nframes - 1
-               end
+       #       if nframes > 0
+       #               create_frame
+       #               frame = nframes - 1
+       #       end
                n = 0
                while 1
                        line = fp.gets
@@ -156,7 +219,15 @@ class Molecule
                        line.chomp!
                        if line =~ /ATOM\s+ATOMIC\s+COORDINATES/ || line =~ /COORDINATES OF ALL ATOMS ARE/
                                set_progress_message(mes + "\nReading atomic coordinates...")
-                               first_line = (line =~ /ATOMIC/)
+                               if line =~ /ATOMIC/
+                                 first_line = true
+                                 if !new_unit
+                                   next   #  Skip initial atomic coordinates unless loading into an empty molecule
+                                 end
+                               else
+                                 first_line = false
+                                 nsearch += 1
+                               end
                                line = fp.gets    #  Skip one line
                                n = 0
                                coords = []
@@ -188,14 +259,27 @@ class Molecule
                                #               }
                                #       }
                                        new_unit = false
-                                       create_frame
+                               #       create_frame
                                else
-                                       create_frame([coords])  #  Should not be (coords)
+                                       if search_mode != 1 || nsearch > 1
+                                               #  The first frame for geometry search has the same coordinates as input
+                                               create_frame([coords])  #  Should not be (coords)
+                                       end
                                end
-                               set_property("energy", energy)
+                               set_property("energy", energy) if energy
+                       elsif line =~ /BEGINNING GEOMETRY SEARCH POINT/
+                               energy = nil   #  New search has begun, so clear the energy
+                               search_mode = 1
+                       elsif line =~ /CONSTRAINED OPTIMIZATION POINT/
+                               energy = nil   #  New search has begun, so clear the energy
+                               search_mode = 2
                        elsif line =~ /FINAL .* ENERGY IS *([-.0-9]+) AFTER/
-                           energy = $1.to_f
-                               puts energy
+                               if search_mode != 2
+                                       energy = $1.to_f
+                                       set_property("energy", energy)
+                               end
+                       elsif line =~ /TOTAL ENERGY += +([-.0-9]+)/
+                               energy = $1.to_f
                        elsif false && line =~ /EQUILIBRIUM GEOMETRY LOCATED/i
                                set_progress_message(mes + "\nReading optimized coordinates...")
                                fp.gets; fp.gets; fp.gets
@@ -209,68 +293,19 @@ class Molecule
                                        n += 1
                                        break if n >= natoms
                                end
-                               if ne_alpha > 0 && ne_beta > 0
-                                       #  Allocate basis set record again, to update the atomic coordinates
-                                       allocate_basis_set_record(rflag, ne_alpha, ne_beta)
-                               end
+                       #       if ne_alpha > 0 && ne_beta > 0
+                       #               #  Allocate basis set record again, to update the atomic coordinates
+                       #               allocate_basis_set_record(rflag, ne_alpha, ne_beta)
+                       #       end
                        elsif line =~ /ATOMIC BASIS SET/
-                               while (line = fp.gets)
-                                       break if line =~ /SHELL\s+TYPE\s+PRIMITIVE/
-                               end
-                               line = fp.gets
-                               i = -1
-                               nprims = 0
-                               sym = -10  #  undefined
-                               ncomps = 0
+                               lines = []
+                               lineno = fp.lineno
                                while (line = fp.gets)
                                        break if line =~ /TOTAL NUMBER OF BASIS SET/
                                        line.chomp!
-                                       if line =~ /^\s*$/
-                                         #  End of one shell
-                                         add_gaussian_orbital_shell(sym, nprims, i)
-                                         # puts "add_gaussian_orbital_shell #{sym}, #{nprims}, #{i}"
-                                         nprims = 0
-                                         sym = -10
-                                         next
-                                       end
-                                       a = line.split
-                                       if a.length == 1
-                                         i += 1
-                                         line = fp.gets  #  Skip the blank line
-                                         next
-                                       elsif a.length == 5 || a.length == 6
-                                         if sym == -10
-                                               case a[1]
-                                               when "S"
-                                                 sym = 0; n = 1
-                                               when "P"
-                                                 sym = 1; n = 3
-                                               when "L"
-                                                 sym = -1; n = 4
-                                               when "D"
-                                                 sym = 2; n = 6
-                                               when "F"
-                                                 sym = 3; n = 10
-                                               when "G"
-                                                 sym = 4; n = 15
-                                               else
-                                                 raise MolbyError, "Unknown gaussian shell type at line #{fp.lineno}"
-                                               end
-                                               ncomps += n
-                                         end
-                                         if (a.length == 5 && sym == -1) || (a.length == 6 && sym != -1)
-                                           raise MolbyError, "Wrong format in gaussian shell information at line #{fp.lineno}"
-                                         end
-                                         exp = Float(a[3])
-                                         c = Float(a[4])
-                                         csp = Float(a[5] || 0.0)
-                                         add_gaussian_primitive_coefficients(exp, c, csp)
-                                         nprims += 1
-                                         # puts "add_gaussian_primitive_coefficients #{exp}, #{c}, #{csp}"
-                                       else
-                                         raise MolbyError, "Error in reading basis set information at line #{fp.lineno}"
-                                       end
+                                       lines.push(line)
                                end
+                               ncomps = sub_load_gamess_log_basis_set(lines, lineno)
                        elsif line =~ /NUMBER OF OCCUPIED ORBITALS/
                                line =~ /=\s*(\d+)/
                                n = Integer($1)
@@ -294,8 +329,8 @@ class Molecule
                                alpha_beta = $1
                        elsif line =~ /^\s*(EIGENVECTORS|MOLECULAR ORBITALS)\s*$/
                                if mo_count == 0
-                                       allocate_basis_set_record(rflag, ne_alpha, ne_beta)
-                                       # puts "allocate_basis_set_record  #{rflag}, #{ne_alpha}, #{ne_beta}"
+                                       clear_mo_coefficients
+                                       set_mo_info(:type=>["UHF", "RHF", "ROHF"][rflag], :alpha=>ne_alpha, :beta=>ne_beta)
                                end
                                mo_count += 1
                                idx = 0
@@ -358,6 +393,7 @@ class Molecule
        end
        n = 0
        nf = 0
+       energy = nil
        use_input_orientation = false
        show_progress_panel("Loading Gaussian out file...")
        while 1
@@ -365,7 +401,7 @@ class Molecule
                if line == nil
                        break
                end
-               line.chomp
+               line.chomp!
                if line =~ /(Input|Standard) orientation/
                        match = $1
                        if match == "Input"
@@ -405,13 +441,23 @@ class Molecule
                        #       }
                                guess_bonds
                                new_unit = false
-                               create_frame
+                       #       create_frame
                        else
                                create_frame([coords])  #  Should not be (coords)
                        end
+                       if energy
+                               # TODO: to ensure whether the energy output line comes before
+                               # or after the atomic coordinates.
+                               set_property("energy", energy)
+                       end
                        nf += 1
+               elsif line =~ /SCF Done: *E\(\w+\) *= *([-.0-9]+)/
+                       energy = $1.to_f
                end
        end
+       if energy
+               set_property("energy", energy)
+       end
        hide_progress_panel
        (n > 0 ? true : false)
   end
index 540945b..4f93521 100644 (file)
@@ -627,6 +627,13 @@ RubyDialogCallback_show(RubyDialog *dref)
                ((RubyDialogFrame *)dref)->StartIntervalTimer(-1);
        ((RubyDialogFrame *)dref)->Show(true);
        ((RubyDialogFrame *)dref)->Raise();
+#if defined(__WXMAC__)
+       {
+               extern void AddWindowsItemWithTitle(const char *title);
+               wxString str = ((RubyDialogFrame *)dref)->GetLabel();
+               AddWindowsItemWithTitle(str.mb_str(WX_DEFAULT_CONV));
+       }
+#endif
 }
 
 void
index d29b049..b0e2440 100644 (file)
@@ -262,3 +262,16 @@ wxMenuImpl* wxMenuImpl::Create( wxMenu* peer, const wxString& title )
     wxMenuImpl* c = new wxMenuCocoaImpl( peer, menu );
     return c;
 }
+
+/*  20140614 Toshi Nagata  */
+/*  Add the frontmost window to the window menu with the given title  */
+/*  (for RubyDialog)  */
+void
+AddWindowsItemWithTitle(const char *title)
+{
+       id win = [NSApp keyWindow];
+       if (win != nil) {
+               [NSApp addWindowsItem:win title:[NSString stringWithUTF8String:title] filename:NO];
+       }
+}
+/*  End Toshi Nagata   */