s_Kernel_MessageBox(int argc, VALUE *argv, VALUE self)
{
char *str, *title, *s;
- int buttons, icon;
+ int buttons, icon, retval;
VALUE sval, tval, bval, ival;
rb_scan_args(argc, argv, "22", &sval, &tval, &bval, &ival);
str = StringValuePtr(sval);
else
rb_raise(rb_eMolbyError, "the icon specification should be either :info, :warning or :error");
} else icon = 1;
- MyAppCallback_messageBox(str, title, buttons, icon);
- return Qnil;
+ retval = MyAppCallback_messageBox(str, title, buttons, icon);
+ return (retval ? Qtrue : Qfalse);
}
/*
/*
* call-seq:
+ * hartree_to_kcal(val)
+ *
+ * Convert hartree to kcal/mol
+ */
+static VALUE
+s_Kernel_HartreeToKcal(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d * 627.5094740630557);
+}
+
+/*
+ * call-seq:
+ * kcal_to_hartree(val)
+ *
+ * Convert kcal/mol to hartree
+ */
+static VALUE
+s_Kernel_KcalToHartree(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d / 627.5094740630557);
+}
+
+/*
+ * call-seq:
+ * hartree_to_kj(val)
+ *
+ * Convert hartree to kJ/mol
+ */
+static VALUE
+s_Kernel_HartreeToKJ(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d * 2625.4996394798253);
+}
+
+/*
+ * call-seq:
+ * kj_to_hartree(val)
+ *
+ * Convert kJ/mol to hartree
+ */
+static VALUE
+s_Kernel_KJToHartree(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d / 2625.4996394798253);
+}
+
+/*
+ * call-seq:
+ * bohr_to_angstrom(val)
+ *
+ * Convert bohr to angstrom
+ */
+static VALUE
+s_Kernel_BohrToAngstrom(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d * 0.529177210903);
+}
+
+/*
+ * call-seq:
+ * angstrom_to_bohr(val)
+ *
+ * Convert angstrom to bohr
+ */
+static VALUE
+s_Kernel_AngstromToBohr(VALUE self, VALUE fval)
+{
+ double d = NUM2DBL(rb_Float(fval));
+ return rb_float_new(d / 0.529177210903);
+}
+
+/*
+ * call-seq:
* stdout.write(str)
*
* Put the message in the main text view in black color.
sNonEmptySym = ID2SYM(rb_intern("non_empty"));
sSelectionSym = ID2SYM(rb_intern("selection"));
sMolProc = rb_eval_string("lambda { |m| m != nil }");
+ rb_define_variable("$is_a_molecule_proc", &sMolProc);
sNonEmptyProc = rb_eval_string("lambda { |m| m.is_a?(Molecule) && m.natoms > 0 }");
+ rb_define_variable("$is_molecule_not_empty_proc", &sNonEmptyProc);
sSelectionProc = rb_eval_string("lambda { |m| m.is_a?(Molecule) && m.selection.count > 0 }");
+ rb_define_variable("$has_molecule_selection_proc", &sSelectionProc);
sTrueProc = rb_eval_string("lambda { |m| true }");
- rb_global_variable(&sMolProc);
- rb_global_variable(&sNonEmptyProc);
- rb_global_variable(&sSelectionProc);
- rb_global_variable(&sTrueProc);
+ rb_define_variable("$always_true_proc", &sTrueProc);
}
if (pval == Qnil) {
s_Ruby_UpdateUI_handler(VALUE data)
{
void **p = (void **)data;
- int index = (int)p[0];
+ int index = (intptr_t)p[0];
Molecule *mol = (Molecule *)p[1];
int *outChecked = (int *)p[2];
char **outTitle = (char **)p[3];
*
* Call subprocess. A progress dialog window is displayed, with a message
* "Running #{process_name}...".
+ * cmd is either a single string of an array of string. If it is a single string, then
+ * it will be given to wxExecute as a single argument. In this case, the string can be
+ * split into arguments by whitespace. If this behavior is not intended, then use an array
+ * containing a single string.
* A callback proc can be given, which is called periodically during execution. If the proc returns
* nil or false, then the execution will be interrupted.
* If stdout_file or stderr_file is a filename, then the message will be sent to the file; if the
VALUE save_interruptFlag;
int n, exitstatus, pid;
char *sout, *serr;
+ const char *pnamestr, **cmdargv;
FILE *fpout, *fperr;
rb_scan_args(argc, argv, "23", &cmd, &procname, &cproc, &stdout_val, &stderr_val);
}
save_interruptFlag = s_SetInterruptFlag(self, Qnil);
- n = MyAppCallback_callSubProcess(StringValuePtr(cmd), StringValuePtr(procname), (cproc == Qnil ? NULL : s_Kernel_CallSubProcess_Callback), (cproc == Qnil ? NULL : (void *)cproc), fpout, fperr, &exitstatus, &pid);
+ if (procname != Qnil)
+ pnamestr = StringValuePtr(procname);
+ else pnamestr = NULL;
+ if (rb_obj_is_kind_of(cmd, rb_cString)) {
+ cmdargv = calloc(sizeof(cmdargv[0]), 3);
+ cmdargv[0] = StringValuePtr(cmd);
+ cmdargv[1] = "";
+ cmdargv[2] = NULL;
+ } else {
+ cmd = rb_ary_to_ary(cmd);
+ cmdargv = calloc(sizeof(cmdargv[0]), RARRAY_LEN(cmd) + 1);
+ for (n = 0; n < RARRAY_LEN(cmd); n++) {
+ cmdargv[n] = StringValuePtr(RARRAY_PTR(cmd)[n]);
+ }
+ cmdargv[n] = NULL;
+ }
+ n = MyAppCallback_callSubProcess(cmdargv, pnamestr, (cproc == Qnil ? NULL : s_Kernel_CallSubProcess_Callback), (cproc == Qnil ? NULL : (void *)cproc), fpout, fperr, &exitstatus, &pid);
s_SetInterruptFlag(self, save_interruptFlag);
-
+ free(cmdargv);
+
if (fpout != NULL && fpout != (FILE *)1)
fclose(fpout);
if (fperr != NULL && fperr != (FILE *)1)
char *buf;
int n, exitstatus, pid;
VALUE val;
- n = MyAppCallback_callSubProcess(StringValuePtr(cmd), NULL, DUMMY_CALLBACK, &buf, NULL, NULL, &exitstatus, &pid);
+ const char *cmdargv[3];
+ cmdargv[0] = StringValuePtr(cmd);
+ cmdargv[1] = "";
+ cmdargv[2] = NULL;
+ n = MyAppCallback_callSubProcess(cmdargv, NULL, DUMMY_CALLBACK, &buf, NULL, NULL, &exitstatus, &pid);
/* fprintf(stderr, "n = %d, exitstatus = %d, pid = %d\n", n, exitstatus, pid); */
if (n >= 0 && buf != NULL) {
val = Ruby_NewEncodedStringValue(buf, 0);
static VALUE
s_Molecule_LoadSave(int argc, VALUE *argv, VALUE self, int loadFlag)
{
- VALUE rval;
+ VALUE rval, argv0;
char *argstr, *methname, *p, *type = "";
ID mid = 0;
int i;
if (argc == 0)
return Qnil;
- if (argc == 0 || (argstr = StringValuePtr(argv[0])) == NULL)
+ argv0 = argv[0]; /* Keep as a local variable to avoid GC */
+ if (argc == 0 || (argstr = StringValuePtr(argv0)) == NULL)
rb_raise(rb_eMolbyError, "the first argument must be either filename or \":filetype\"");
if (argstr[0] == ':') {
/* Call "loadXXX" (or "saveXXX") for type ":XXX" */
}
}
failure:
- rval = rb_str_to_str(argv[0]);
+ rval = rb_str_to_str(argv0);
asprintf(&p, "Failed to %s file %s", (loadFlag ? "load" : "save"), type);
s_Molecule_RaiseOnLoadSave(1, loadFlag, p, StringValuePtr(rval));
return Qnil; /* Does not reach here */
Molecule *mol;
/* Atom *ap; */
Data_Get_Struct(self, Molecule, mol);
- MoleculeSetPath(mol, StringValuePtr(argv[0]));
+ MoleculeSetPath(mol, StringValuePtr(argv0));
/* Check if all occupancy factors are zero; if that is the case, then all set to 1.0 */
/* for (i = 0, ap = mol->atoms; i < mol->natoms; i++, ap = ATOM_NEXT(ap)) {
VALUE gval, rval, wval;
IntGroup *ig;
IntGroupIterator iter;
- int nn, errno, i, j, in, status;
+ int nn, errnum, i, j, in, status;
Vector *ref;
Double *weights, dval[3];
Transform tr;
if (rb_obj_is_kind_of(rval, rb_cNumeric)) {
int fn = NUM2INT(rb_Integer(rval));
if (fn < 0 || fn >= MoleculeGetNumberOfFrames(mol)) {
- errno = 1;
+ errnum = 1;
status = fn;
goto err;
}
} else if (rb_obj_is_kind_of(rval, rb_cLAMatrix)) {
LAMatrix *m = LAMatrixFromValue(rval, NULL, 0, 0);
if (m->row * m->column < nn * 3) {
- errno = 2;
+ errnum = 2;
goto err;
}
for (i = 0; i < nn; i++) {
VALUE aval;
rval = rb_protect(rb_ary_to_ary, rval, &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
if (RARRAY_LEN(rval) < nn) {
- errno = 2;
+ errnum = 2;
goto err;
}
if (rb_obj_is_kind_of((RARRAY_PTR(rval))[0], rb_cNumeric)) {
/* Array of 3*nn numbers */
if (RARRAY_LEN(rval) < nn * 3) {
- errno = 2;
+ errnum = 2;
goto err;
}
for (i = 0; i < nn; i++) {
for (j = 0; j < 3; j++) {
aval = rb_protect(rb_Float, (RARRAY_PTR(rval))[i * 3 + j], &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
dval[j] = NUM2DBL(aval);
} else {
aval = rb_protect(rb_ary_to_ary, aval, &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
if (RARRAY_LEN(aval) < 3) {
- errno = 4;
+ errnum = 4;
status = i;
goto err;
}
for (j = 0; j < 3; j++) {
VALUE aaval = rb_protect(rb_Float, (RARRAY_PTR(aval))[j], &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
dval[j] = NUM2DBL(aaval);
} else {
wval = rb_protect(rb_ary_to_ary, wval, &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
if (RARRAY_LEN(wval) < nn) {
- errno = 5;
+ errnum = 5;
goto err;
}
for (i = 0; i < nn; i++) {
VALUE wwval = rb_protect(rb_Float, (RARRAY_PTR(wval))[i], &status);
if (status != 0) {
- errno = 3;
+ errnum = 3;
goto err;
}
weights[i] = NUM2DBL(wwval);
}
dval[0] = s_Molecule_FitCoordinates_Sub(mol, ig, ref, weights, tr);
if (dval[0] < 0) {
- errno = 6;
+ errnum = 6;
goto err;
}
- errno = 0;
+ errnum = 0;
err:
IntGroupIteratorRelease(&iter);
free(ref);
free(weights);
- if (errno == 0) {
+ if (errnum == 0) {
return rb_ary_new3(2, ValueFromTransform(&tr), rb_float_new(dval[0]));
- } else if (errno == 1) {
+ } else if (errnum == 1) {
rb_raise(rb_eMolbyError, "frame index (%d) is out of range", status);
- } else if (errno == 2) {
+ } else if (errnum == 2) {
rb_raise(rb_eMolbyError, "insufficient number of reference coordinates");
- } else if (errno == 3) {
+ } else if (errnum == 3) {
rb_jump_tag(status);
- } else if (errno == 4) {
+ } else if (errnum == 4) {
rb_raise(rb_eMolbyError, "less than 3 elements for index %d of reference coordinates", status);
- } else if (errno == 5) {
+ } else if (errnum == 5) {
rb_raise(rb_eMolbyError, "insufficient number of weight values");
- } else if (errno == 6) {
+ } else if (errnum == 6) {
rb_raise(rb_eMolbyError, "matrix calculation failed during coordinate fitting");
}
return Qnil; /* Not reached */
/*
* call-seq:
- * add_gaussian_orbital_shell(atom_index, sym, no_of_primitives)
+ * add_gaussian_orbital_shell(atom_index, sym, no_of_primitives[, additional_exponent])
*
* To be used internally. Add a gaussian orbital shell with the atom index, symmetry code,
- * and the number of primitives. Symmetry code: 0, S-type; 1, P-type; -1, SP-type; 2, D-type;
- * -2, D5-type.
+ * and the number of primitives.
+ * Additional exponent is for JANPA only; implements an additinal r^N component that
+ * appears in cartesian->spherical conversion.
+ * Symmetry code: 0, S-type; 1, P-type; -1, SP-type; 2, D-type; -2, D5-type;
+ * 3, F-type; -3, F7-type; 4, G-type; -4, G9-type.
+ * Or: "s", S-type; "p", P-type; "sp", SP-type; "d", D-type; "d5", D5-type;
+ * "f", F-type; "f7", F7-type; "g", G-type; "g9", G9-type
*/
static VALUE
-s_Molecule_AddGaussianOrbitalShell(VALUE self, VALUE aval, VALUE symval, VALUE npval)
+s_Molecule_AddGaussianOrbitalShell(int argc, VALUE *argv, VALUE self)
{
Molecule *mol;
- int sym, nprims, a_idx, n;
- Data_Get_Struct(self, Molecule, mol);
+ int sym, nprims, a_idx, n, add_exp;
+ VALUE aval, symval, npval, addval;
+ Data_Get_Struct(self, Molecule, mol);
+ rb_scan_args(argc, argv, "31", &aval, &symval, &npval, &addval);
+ if (rb_obj_is_kind_of(symval, rb_cString)) {
+ const char *p = StringValuePtr(symval);
+ if (strcasecmp(p, "s") == 0)
+ sym = 0;
+ else if (strcasecmp(p, "p") == 0)
+ sym = 1;
+ else if (strcasecmp(p, "sp") == 0)
+ sym = -1;
+ else if (strcasecmp(p, "d") == 0)
+ sym = 2;
+ else if (strcasecmp(p, "d5") == 0)
+ sym = -2;
+ else if (strcasecmp(p, "f") == 0)
+ sym = 3;
+ else if (strcasecmp(p, "f7") == 0)
+ sym = -3;
+ else if (strcasecmp(p, "g") == 0)
+ sym = 4;
+ else if (strcasecmp(p, "g9") == 0)
+ sym = -4;
+ else
+ rb_raise(rb_eArgError, "Unknown orbital type '%s'", p);
+ } else {
+ sym = NUM2INT(rb_Integer(symval));
+ }
a_idx = NUM2INT(rb_Integer(aval));
- sym = NUM2INT(rb_Integer(symval));
nprims = NUM2INT(rb_Integer(npval));
- n = MoleculeAddGaussianOrbitalShell(mol, a_idx, sym, nprims);
+ if (addval != Qnil)
+ add_exp = NUM2INT(rb_Integer(addval));
+ else add_exp = 0;
+ n = MoleculeAddGaussianOrbitalShell(mol, a_idx, sym, nprims, add_exp);
if (n == -1)
rb_raise(rb_eMolbyError, "Molecule is emptry");
else if (n == -2)
* call_subprocess_async(cmd [, end_callback [, timer_callback [, standard_output_file [, error_output_file]]]])
*
* Call subprocess asynchronically.
+ * cmd is either a single string of an array of string. If it is a single string, then
+ * it will be given to wxExecute as a single argument. In this case, the string can be
+ * split into arguments by whitespace. If this behavior is not intended, then use an array
+ * containing a single string.
* If end_callback is given, it will be called (with two arguments self and termination status)
* when the subprocess terminated.
* If timer_callback is given, it will be called (also with two arguments, self and timer count).
VALUE cmd, end_proc, timer_proc, stdout_val, stderr_val;
Molecule *mol;
char *sout, *serr;
+ const char **cmdargv;
int n;
FILE *fpout, *fperr;
rb_scan_args(argc, argv, "14", &cmd, &end_proc, &timer_proc, &stdout_val, &stderr_val);
/* Register procs as instance variables */
rb_ivar_set(self, rb_intern("end_proc"), end_proc);
rb_ivar_set(self, rb_intern("timer_proc"), timer_proc);
- n = MoleculeCallback_callSubProcessAsync(mol, StringValuePtr(cmd), s_Molecule_CallSubProcessAsync_EndCallback, (timer_proc == Qnil ? NULL : s_Molecule_CallSubProcessAsync_TimerCallback), fpout, fperr);
+
+ if (rb_obj_is_kind_of(cmd, rb_cString)) {
+ cmdargv = calloc(sizeof(cmdargv[0]), 3);
+ cmdargv[0] = StringValuePtr(cmd);
+ cmdargv[1] = "";
+ cmdargv[2] = NULL;
+ } else {
+ cmd = rb_ary_to_ary(cmd);
+ cmdargv = calloc(sizeof(cmdargv[0]), RARRAY_LEN(cmd) + 1);
+ for (n = 0; n < RARRAY_LEN(cmd); n++) {
+ cmdargv[n] = StringValuePtr(RARRAY_PTR(cmd)[n]);
+ }
+ cmdargv[n] = NULL;
+ }
+ n = MoleculeCallback_callSubProcessAsync(mol, cmdargv, s_Molecule_CallSubProcessAsync_EndCallback, (timer_proc == Qnil ? NULL : s_Molecule_CallSubProcessAsync_TimerCallback), fpout, fperr);
if (fpout != NULL && fpout != (FILE *)1)
fclose(fpout);
if (fperr != NULL && fperr != (FILE *)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_orbital_shell", s_Molecule_AddGaussianOrbitalShell, -1);
rb_define_method(rb_cMolecule, "add_gaussian_primitive_coefficients", s_Molecule_AddGaussianPrimitiveCoefficients, 3);
rb_define_method(rb_cMolecule, "get_gaussian_shell_info", s_Molecule_GetGaussianShellInfo, 1);
rb_define_method(rb_cMolecule, "get_gaussian_primitive_coefficients", s_Molecule_GetGaussianPrimitiveCoefficients, 1);
rb_define_method(rb_mKernel, "play_sound", s_Kernel_PlaySound, -1);
rb_define_method(rb_mKernel, "stop_sound", s_Kernel_StopSound, 0);
rb_define_method(rb_mKernel, "export_to_clipboard", s_Kernel_ExportToClipboard, 1);
+ rb_define_method(rb_mKernel, "hartree_to_kcal", s_Kernel_HartreeToKcal, 1);
+ rb_define_method(rb_mKernel, "hartree_to_kj", s_Kernel_HartreeToKJ, 1);
+ rb_define_method(rb_mKernel, "kcal_to_hartree", s_Kernel_KcalToHartree, 1);
+ rb_define_method(rb_mKernel, "kj_to_hartree", s_Kernel_KJToHartree, 1);
+ rb_define_method(rb_mKernel, "bohr_to_angstrom", s_Kernel_BohrToAngstrom, 1);
+ rb_define_method(rb_mKernel, "angstrom_to_bohr", s_Kernel_AngstromToBohr, 1);
/* class IO */
rb_define_method(rb_cIO, "gets_any_eol", s_IO_gets_any_eol, 0);
"%s\n"
"FFTW 3.3.2, http://www.fftw.org/\n"
" Copyright (C) 2003, 2007-11 Matteo Frigo"
- " and Massachusetts Institute of Technology",
+ " and Massachusetts Institute of Technology\n"
+ "JANPA 2.01, https://janpa.sourceforge.net/\n"
+ " Copyright (C) 2014, Tymofii Nikolaienko",
MyAppCallback_getGUIDescriptionString(),
gRubyVersion, gRubyCopyright);
} else {
"%s\n"
"FFTW 3.3.2, http://www.fftw.org/\n"
" Copyright (C) 2003, 2007-11 Matteo Frigo"
- " and Massachusetts Institute of Technology",
+ " and Massachusetts Institute of Technology\n"
+ "JANPA 2.01, https://janpa.sourceforge.net/\n"
+ " Copyright (C) 2014, Tymofii Nikolaienko",
gRubyVersion, gRubyCopyright);
}