/* Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve */ #include #include #include #include /* Macintosh extras (Courtesy Jon Tischler ) */ #if defined(__THINK__) || defined(__MWERKS__) #include #define CONSOLE_LINES 36 /* number of lines to use for console */ #define CONSOLE_COLUMNS 90 /* number of columns to use for console */ #ifdef __MWERKS__ #include #endif #endif #define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr))) #define AppFree(ptr, n) free(ptr) #define SGCOREDEF__ #include "sginfo.h" #if USE_GS_SI static int PrimitiveRotMx(const int *CCMx_LP, int *RotMx, const int *CCMx_PL, int deterCCMx_LP) { int i; int BufMx[9]; /* Mp = Tlp . Mz . Tpl */ RotMxMultiply(BufMx, RotMx, CCMx_PL); RotMxMultiply(RotMx, CCMx_LP, BufMx); for (i = 0; i < 9; i++) { if (RotMx[i] % deterCCMx_LP) { SetSgError("Internal Error: PrimitiveRotMx()"); return -1; } } for (i = 0; i < 9; i++) RotMx[i] /= deterCCMx_LP; return 0; } static int Find_si(T_SgInfo * SgInfo) { static const int Tab_si_Vector[] = { 1, 0, 0, 0, /* h */ 0, 1, 0, 1, /* k */ 0, 0, 1, 2, /* l */ 1, 1, 0, 0, /* h+k */ 1, -1, 0, 0, /* h-k */ 0, 1, 1, 1, /* k+l */ 0, 1, -1, 1, /* k-l */ 1, 0, 1, 1, /* h+l */ 1, 0, -1, 1, /* h-l */ 1, 1, 1, 0, /* h+k+l */ 1, 1, -1, 0, /* h+k-l */ 1, -1, 1, 0, /* h-k+l */ -1, 1, 1, 0, /* -h+k+l */ 2, 1, -1, 0, /* 2h+k-l */ 2, -1, 1, 0, /* 2h-k+l */ -1, 2, 1, 0, /* -h+2k+l */ 1, 2, -1, 0, /* h+2k-l */ -1, 1, 2, 0, /* -h+k+2l */ 1, -1, 2, 0 /* h-k+2l */ }; static int nTab_si_Vector = sizeof Tab_si_Vector / sizeof(*Tab_si_Vector) / 4; int deterCCMx_LP, CCMx_PL[9]; int i, itabsiv; int nLoopInv, iLoopInv, n_si_v, i_si_v; int n, m, l; int IsFine; int item[3]; int R_I[9], si_Buf[9]; int iList; T_RTMx *lsmx; const int *tabsiv; if (SgInfo->LatticeInfo->Code != 'P') { deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); if (deterCCMx_LP < 1) goto ReturnError; } nLoopInv = Sg_nLoopInv(SgInfo); SgInfo->n_si_Vector = n_si_v = 0; for (i = 0; i < 9; i++) SgInfo->si_Vector[i] = 0; for (i = 0; i < 3; i++) { SgInfo->si_Modulus[i] = 1; item[i] = 1; } tabsiv = Tab_si_Vector; for (itabsiv = 0; itabsiv < nTab_si_Vector; itabsiv++, tabsiv += 4) { IsFine = 1; m = -1; for (iList = 0; IsFine && iList < SgInfo->nList; iList++) { lsmx = &SgInfo->ListSeitzMx[iList]; for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++) { if (iLoopInv == 0) for (i = 0; i < 9; i++) { if (i % 4) R_I[i] = lsmx->s.R[i]; else R_I[i] = lsmx->s.R[i] - 1; } else for (i = 0; i < 9; i++) { if (i % 4) R_I[i] = -lsmx->s.R[i]; else R_I[i] = -lsmx->s.R[i] - 1; } if (SgInfo->LatticeInfo->Code != 'P') { if (PrimitiveRotMx(SgInfo->CCMx_LP, R_I, CCMx_PL, deterCCMx_LP) < 0) return -1; } for (i = 0; IsFine && i < 3; i++) { n = tabsiv[0] * R_I[i * 3 + 0]; n += tabsiv[1] * R_I[i * 3 + 1]; n += tabsiv[2] * R_I[i * 3 + 2]; n = abs(n); if (n == 1) IsFine = 0; else if (m < 2) m = n; else if (n > 0 && n != m) IsFine = 0; } } } if (IsFine) { #if DEBUG_Find_si fprintf(stdout, "H-Kt %2d %2d %2d %d\n", tabsiv[0], tabsiv[1], tabsiv[2], m); #endif l = tabsiv[3]; while (item[l] > 1) { /* just "if", see break's */ if (m == item[l]) break; if (m == 3 && (SgInfo->XtalSystem != XS_Trigonal || SgInfo->UniqueDirCode != '=')) break; if (m == 4 && (SgInfo->XtalSystem == XS_Triclinic || SgInfo->XtalSystem == XS_Monoclinic)) break; if (m == 2) break; /* if (m > 1 || m != 4) break; */ n_si_v--; item[l] = 1; break; } if (item[l] == 1) { if (itabsiv > 12) n_si_v = 0; item[l] = m; SgInfo->si_Modulus[n_si_v] = m; n = n_si_v * 3; for (i = 0; i < 3; i++) SgInfo->si_Vector[n++] = tabsiv[i]; n_si_v++; } } } #if DEBUG_Find_si fprintf(stdout, "H-Kt\n"); #endif if (SgInfo->LatticeInfo->Code != 'P') { #if DEBUG_Find_si for (i = 0; i < n_si_v; i++) fprintf(stdout, "H-Kp %2d %2d %2d %d\n", SgInfo->si_Vector[i * 3 + 0], SgInfo->si_Vector[i * 3 + 1], SgInfo->si_Vector[i * 3 + 2], SgInfo->si_Modulus[i]); fprintf(stdout, "H-Kp\n"); #endif for (i_si_v = 0; i_si_v < n_si_v; i_si_v++) { for (i = 0; i < 3; i++) { si_Buf[i_si_v * 3 + i] = SgInfo->si_Vector[i_si_v * 3 + 0] * CCMx_PL[i * 3 + 0] + SgInfo->si_Vector[i_si_v * 3 + 1] * CCMx_PL[i * 3 + 1] + SgInfo->si_Vector[i_si_v * 3 + 2] * CCMx_PL[i * 3 + 2]; } } for (i = 0; i < i_si_v * 3; i++) { if (si_Buf[i] % deterCCMx_LP) { n = i / 3; n *= 3; fprintf(stdout, " %3d %3d %3d\n", si_Buf[n + 0], si_Buf[n + 1], si_Buf[n + 2]); goto ReturnError; } SgInfo->si_Vector[i] = si_Buf[i] / deterCCMx_LP; } } SgInfo->n_si_Vector = n_si_v; return n_si_v; ReturnError: SetSgError("Internal Error: Find_si()"); return -1; } static int Try_GS_si(T_SgInfo * SgInfo) { int h, k, l, iList; int Maxh, Maxk, Maxl; int Minh, Mink, Minl; int nTestField, *TestField; int nProperty, *Property, *pp; int IsFine, would_be, is; SgInfo->n_si_Vector = -1; nTestField = 12 * 12 * 12; AppMalloc(TestField, nTestField); if (TestField == NULL) { SetSgError("Not enough core"); return -1; } MarkLegalOrigins(SgInfo, TestField); Maxh = Maxk = Maxl = 7; SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); nProperty = (Maxh - Minh + 1) * (Maxk - Mink + 1) * (Maxl - Minl + 1); AppMalloc(Property, nProperty); if (Property == NULL) { SetSgError("Not enough core"); AppFree(TestField, nTestField); return -1; } pp = Property; for (h = Minh; h <= Maxh; h++) for (k = Mink; k <= Maxk; k++) for (l = Minl; l <= Maxl; l++) { iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL); if (SgError != NULL) { AppFree(Property, nProperty); AppFree(TestField, nTestField); return -1; } if (iList == 0) *pp++ = Verify_si(h, k, l, TestField); else *pp++ = -1; } if (Find_si(SgInfo) >= 0) { IsFine = 1; pp = Property; for (h = Minh; IsFine && h <= Maxh; h++) for (k = Mink; IsFine && k <= Maxk; k++) for (l = Minl; IsFine && l <= Maxl; l++) { is = *pp++; if (is >= 0) { would_be = Is_si(SgInfo, h, k, l); if (is != would_be) IsFine = 0; } } if (IsFine) { AppFree(Property, nProperty); AppFree(TestField, nTestField); return 0; } } SetSgError("Internal Error: Can't determine s.i. vectors and moduli"); AppFree(Property, nProperty); AppFree(TestField, nTestField); return -1; } #endif /* USE_GS_SI */ static const char *progn = "sginfo"; static void progerror(const char *message) { fflush(stdout); fprintf(stderr, "%s: %s\n", progn, message); exit(1); } static void NotEnoughCore(void) { progerror("Not enough core"); } static void PrintClearSgError(int ClearError, int CertainSgError) { if (CertainSgError && SgError == NULL) SetSgError("Internal Error: SgError not set but should be"); if (SgError) { fprintf(stdout, "%s: %s\n", progn, SgError); if (ClearError == 0) exit(1); SgError = NULL; } } static int str_icmp(const char *s, const char *t) { char cs, ct; while (*s || *t) { cs = toupper(*s++); ct = toupper(*t++); if (cs < ct) return -1; if (cs > ct) return 1; } return 0; } static int str_ibegin(const char *s1, const char *s2) { /* string ignore-case *//* begin */ char u1, u2; while (*s1 && *s2) { u1 = toupper(*s1++); u2 = toupper(*s2++); if (u1 < u2) return -1; else if (u1 > u2) return 1; } if (*s2) return -1; return 0; } static const char *LegendTabSgName[] = { "", " Extensions", " ----------", " Monoclinic unique axis b unique axis c unique axis a", " abc c-ba abc ba-c abc -acb", " ------------ ------------ ------------", " cell choice 1 :b1 :-b1 :c1 :-c1 :a1 :-a1", " 2 :b2 :-b2 :c2 :-c2 :a2 :-a2", " 3 :b3 :-b3 :c3 :-c3 :a3 :-a3", "", " Orthorhombic :ba-c change of basis abc -> ba-c", " :1 origin choice 1", " :2ba-c origin choice 2, change of basis abc -> ba-c", "", " Tetragonal :1 origin choice 1", " Cubic :2 origin choice 2", "", " Trigonal :H hexagonal axes", " :R rhombohedral axes", "", " Number Schoenflies Hermann-Mauguin Hall", " ------ ----------- --------------- ----", NULL, }; static void ListTabSgName(int WantedSgNumber, int VolLetter, FILE * fpout) { int i; const char *sgl, *ext, **ltsgn; const T_TabSgName *tsgn, *show, *show_later; if (WantedSgNumber == -1) for (ltsgn = LegendTabSgName; *ltsgn; ltsgn++) fprintf(fpout, "%s\n", *ltsgn); if (VolLetter == '1') VolLetter = 'I'; else VolLetter = toupper(VolLetter); show = show_later = NULL; for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { if (WantedSgNumber == -1 || WantedSgNumber == tsgn->SgNumber) { if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) { if (VolLetter == 'I') { ext = tsgn->Extension; if (*ext == '-') ext++; if (tsgn->Extension[0] == 'b' && (tsgn->Extension[1] == '\0' || tsgn->Extension[1] == '1')) show_later = tsgn; else if (ext[0] == 'c') { if (ext[1] == '\0') show = tsgn; else { i = 0; for (sgl = tsgn->SgLabels; *sgl; sgl++) if (*sgl == '=') i++; if (i == 2) show = tsgn; } } } else if (VolLetter == 'A') { if (tsgn->Extension[0] != '-' && tsgn->Extension[0] != 'a') show = tsgn; } else show = tsgn; } else if (tsgn->Extension[0] == 'H' && VolLetter == 'I') show_later = tsgn; else if (VolLetter == 'A' || VolLetter == 'I') { if (tsgn->Extension[0] == '\0' || tsgn->Extension[1] == '\0') show = tsgn; } else show = tsgn; if (show) { putc(' ', fpout); PrintTabSgNameEntry(show, 1, 0, fpout); putc('\n', fpout); show = NULL; if (show_later) { putc(' ', fpout); PrintTabSgNameEntry(show_later, 1, 0, fpout); putc('\n', fpout); show_later = NULL; } } } } } static void ListCIF(FILE * fpout) { int n; const char **loop, *lbl; const T_TabSgName *tsgn; static const char *loop_monoclinic_extensions[] = { "_monoclinic_extension # cf. _symmetry_space_group_id", "_monoclinic_axis # cf. IT Vol. A 1983 sec. 2.16.", "_monoclinic_setting # cf. IT Vol. A 1983 tab. 2.16.1.", "_monoclinic_cellchoice # cf. IT Vol. A 1983 sec. 2.16.(i) & fig. 2.6.4.", "", " b b abc 1", " b1 b abc 1", " b2 b abc 2", " b3 b abc 3", "-b b c-ba 1", "-b1 b c-ba 1", "-b2 b c-ba 2", "-b3 b c-ba 3", " c c abc 1", " c1 c abc 1", " c2 c abc 2", " c3 c abc 3", "-c c ba-c 1", "-c1 c ba-c 1", "-c2 c ba-c 2", "-c3 c ba-c 3", " a a abc 1", " a1 a abc 1", " a2 a abc 2", " a3 a abc 3", "-a a -acb 1", "-a1 a -acb 1", "-a2 a -acb 2", "-a3 a -acb 3", NULL }; static const char *loop_symmetry_space_group[] = { "_symmetry_space_group_id", "_symmetry_space_group_name_sch", "_symmetry_space_group_name_h-m # recognised IUCr CIF data names", "_symmetry_space_group_name_hall # recognised IUCr CIF data names", NULL }; fprintf(fpout, "data_ notation\n\n"); fprintf(fpout, "loop_\n"); for (loop = loop_monoclinic_extensions; *loop; loop++) { if ((*loop)[0]) fprintf(fpout, " %s", *loop); putc('\n', fpout); } putc('\n', fpout); putc('\n', fpout); fprintf(fpout, "loop_\n"); for (loop = loop_symmetry_space_group; *loop; loop++) { if ((*loop)[0]) fprintf(fpout, " %s", *loop); putc('\n', fpout); } putc('\n', fpout); for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) { n = fprintf(fpout, " %3d", tsgn->SgNumber); if (tsgn->Extension[0]) n += fprintf(fpout, ":%s", tsgn->Extension); if (tsgn->SgNumber < 1 || tsgn->SgNumber > 230) { SetSgError("Internal Error: ListCIF()"); return; } while (n < 14) { putc(' ', fpout); n++; } putc(' ', fpout); n++; n += fprintf(fpout, "%s", SchoenfliesSymbols[tsgn->SgNumber]); while (n < 22) { putc(' ', fpout); n++; } putc(' ', fpout); n++; n += PrintFullHM_SgName(tsgn, '_', fpout); while (n < 36) { putc(' ', fpout); n++; } putc(' ', fpout); for (lbl = tsgn->HallSymbol; *lbl; lbl++) { if (*lbl == ' ' && lbl != tsgn->HallSymbol) putc('_', fpout); else putc(*lbl, fpout); } putc('\n', fpout); } } static void PutAllXYZ(const T_SgInfo * SgInfo, FILE * fpout) { int iList, f, i; int nTrV, iTrV, nLoopInv, iLoopInv; const int *TrV; T_RTMx SMx; const T_RTMx *lsmx; const char *xyz; char buf0[8], buf1[8], buf2[8]; nLoopInv = Sg_nLoopInv(SgInfo); nTrV = SgInfo->LatticeInfo->nTrVector; TrV = SgInfo->LatticeInfo->TrVector; for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { if (iLoopInv == 0) f = 1; else f = -1; lsmx = SgInfo->ListSeitzMx; if (nLoopInv > 1 || nTrV > 1) putc('#', fpout); if (nTrV > 1) fprintf(fpout, " +(%s %s %s)", FormatFraction(TrV[0], STBF, 0, buf0, sizeof buf0 / sizeof(*buf0)), FormatFraction(TrV[1], STBF, 0, buf1, sizeof buf1 / sizeof(*buf1)), FormatFraction(TrV[2], STBF, 0, buf2, sizeof buf2 / sizeof(*buf2))); if (nLoopInv > 1) fprintf(fpout, " Inversion-Flag = %d", iLoopInv); if (nLoopInv > 1 || nTrV > 1) putc('\n', fpout); for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { for (i = 0; i < 9; i++) SMx.s.R[i] = f * lsmx->s.R[i]; for (i = 0; i < 3; i++) SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ", ", NULL, 0); if (xyz) fprintf(fpout, "%s\n", xyz); else { SetSgError("Internal Error: PutAllXYZ()"); return; } } } } putc('\n', fpout); } static void PutMaple(const T_SgInfo * SgInfo, FILE * fpout) { int iList, f, i; int nTrV, iTrV, nLoopInv, iLoopInv; const int *TrV; T_RTMx SMx; const T_RTMx *lsmx; int iMatrix; char buf0[8], buf1[8], buf2[8]; iMatrix = 0; nLoopInv = Sg_nLoopInv(SgInfo); nTrV = SgInfo->LatticeInfo->nTrVector; TrV = SgInfo->LatticeInfo->TrVector; for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { if (iLoopInv == 0) f = 1; else f = -1; lsmx = SgInfo->ListSeitzMx; if (nLoopInv > 1 || nTrV > 1) putc('#', fpout); if (nTrV > 1) fprintf(fpout, " +(%s %s %s)", FormatFraction(TrV[0], STBF, 0, buf0, sizeof buf0 / sizeof(*buf0)), FormatFraction(TrV[1], STBF, 0, buf1, sizeof buf1 / sizeof(*buf1)), FormatFraction(TrV[2], STBF, 0, buf2, sizeof buf2 / sizeof(*buf2))); if (nLoopInv > 1) fprintf(fpout, " Inversion-Flag = %d", iLoopInv); if (nLoopInv > 1 || nTrV > 1) putc('\n', fpout); for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { for (i = 0; i < 9; i++) SMx.s.R[i] = f * lsmx->s.R[i]; for (i = 0; i < 3; i++) SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); fprintf(fpout, "m%d", ++iMatrix); PrintMapleRTMx(&SMx, 1, STBF, NULL, fpout); } } } putc('\n', fpout); } static void PutSpaceSymFile(const T_SgInfo * SgInfo, FILE * fpout) { unsigned int SgID; int iList, SuppressMx, f, i; int nTrV, iTrV, nLoopInv, iLoopInv; const int *TrV; const T_RTMx *lsmx; const T_TabSgName *tsgn; tsgn = SgInfo->TabSgName; if (tsgn && tsgn->SgLabels == NULL) tsgn = NULL; SgID = 0; if (tsgn != NULL) SgID = SgID_Number(tsgn); fprintf(fpout, "%u '", SgID); if (tsgn != NULL) PrintFullHM_SgName(tsgn, 0, fpout); else if (SgInfo->HallSymbol[0]) fprintf(fpout, "%s", SgInfo->HallSymbol); else fprintf(fpout, "Unknown"); putc('\'', fpout); putc('\n', fpout); nLoopInv = Sg_nLoopInv(SgInfo); nTrV = SgInfo->LatticeInfo->nTrVector; TrV = SgInfo->LatticeInfo->TrVector; iList = SgInfo->OrderL; if (iList > 1) { iList--; SuppressMx = 1; } else SuppressMx = 0; fprintf(fpout, "%d\n", iList); for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) { for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) { if (iLoopInv == 0) f = 1; else f = -1; lsmx = SgInfo->ListSeitzMx; for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) { if (SuppressMx == 0) { for (i = 0; i < 3; i++) fprintf(fpout, " %12.8f %12.8f %12.8f %12.8f\n", (double) f * lsmx->s.R[3 * i + 0], (double) f * lsmx->s.R[3 * i + 1], (double) f * lsmx->s.R[3 * i + 2], (double) iModPositive(f * lsmx->s.T[i] + TrV[i], STBF) / STBF); putc(':', fpout); putc('\n', fpout); } SuppressMx = 0; } } } } static void PutShelx(const T_SgInfo * SgInfo, FILE * fpout) { int Latt_N = 0, iList; const T_RTMx *lsmx; const char *xyz; if (SgInfo->InversionOffOrigin != 0) fprintf(fpout, "***WARNING***: %s\n", "Shelx manual: the origin MUST lie on a center of symmetry"); switch (SgInfo->LatticeInfo->Code) { case 'P': Latt_N = 1; break; case 'A': Latt_N = 5; break; case 'B': Latt_N = 6; break; case 'C': Latt_N = 7; break; case 'I': Latt_N = 2; break; case 'R': if (SgInfo->ExtraInfo == EI_Obverse) Latt_N = 3; break; case 'S': case 'T': SetSgError("Shelx supports R-obverse only"); return; case 'F': Latt_N = 4; break; default: goto ReturnError; } /* N must be made negative if the structure is non-centrosymmetric */ if (SgInfo->Centric != -1) Latt_N = -Latt_N; fprintf(fpout, "LATT %2d\n", Latt_N); lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { xyz = RTMx2XYZ(lsmx, 1, STBF, 1, 1, 0, ", ", NULL, 0); if (xyz) fprintf(fpout, "SYMM %s\n", xyz); else goto ReturnError; } putc('\n', fpout); return; ReturnError: SetSgError("Internal Error: PutShelx()"); return; } static void PutSchakal(const T_SgInfo * SgInfo, FILE * fpout) { int iList, nMx, i; int nTrV, iTrV; const int *TrV; T_RTMx SMx; const T_RTMx *lsmx; const char *xyz; if (Sg_nLoopInv(SgInfo) == 2) fprintf(fpout, "DU -x,-y,-z\n"); nTrV = SgInfo->LatticeInfo->nTrVector; TrV = SgInfo->LatticeInfo->TrVector; if (nTrV > 1) { fprintf(fpout, "DU"); InitRotMx(SMx.s.R, 1); TrV += 3; for (iTrV = 1; iTrV < nTrV; iTrV++, TrV += 3) { for (i = 0; i < 3; i++) SMx.s.T[i] = TrV[i]; xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ",", NULL, 0); if (xyz) { if (iTrV > 1) fprintf(fpout, " ;"); fprintf(fpout, " %s", xyz); } else { putc('\n', fpout); goto ReturnError; } } putc('\n', fpout); } nMx = 0; lsmx = &SgInfo->ListSeitzMx[1]; for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) { xyz = RTMx2XYZ(lsmx, 1, STBF, 0, 0, 1, ",", NULL, 0); if (xyz) { if (nMx % 4 == 0) { if (nMx) putc('\n', fpout); fprintf(fpout, "SY %s", xyz); } else fprintf(fpout, " ; %s", xyz); } else { putc('\n', fpout); goto ReturnError; } nMx++; } if (nMx) putc('\n', fpout); putc('\n', fpout); return; ReturnError: SetSgError("Internal Error: PutSchakal()"); return; } static void Simple_hklList(T_SgInfo * SgInfo, int Maxh, int Maxk, int Maxl, int ListSysAbsent) { int h, k, l, iList, restriction, M, n, i; int Minh, Mink, Minl; int uvw[3]; int CCMx_PL[9], deterCCMx_LP = 0, hP, kP, lP; if (SgInfo->LatticeInfo->Code != 'P') { deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); if (deterCCMx_LP < 1) goto ReturnError; } SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); fprintf(stdout, ">Begin hklList\n"); for (h = Minh; h <= Maxh; h++) for (k = Mink; k <= Maxk; k++) for (l = Minl; l <= Maxl; l++) { iList = IsSysAbsent_hkl(SgInfo, h, k, l, &restriction); if (SgError != NULL) return; M = BuildEq_hkl(SgInfo, NULL, h, k, l); if (SgError != NULL) return; if (iList == 0) { if ((iList = IsSuppressed_hkl(SgInfo, Minh, Mink, Minl, Maxk, Maxl, h, k, l)) != 0) n = fprintf(stdout, "# %3d %3d %3d %3d [%d]", h, k, l, M, iList); else n = fprintf(stdout, " %3d %3d %3d %3d", h, k, l, M); if (restriction >= 0) { while (n < 27) { n++; putc(' ', stdout); } n += fprintf(stdout, " %2d/%d", restriction, STBF); } while (n < 34) { n++; putc(' ', stdout); } if (Is_si(SgInfo, h, k, l) == 1) n += fprintf(stdout, " s.i."); while (n < 41) { n++; putc(' ', stdout); } Set_uvw(SgInfo, h, k, l, uvw); for (i = 0; i < SgInfo->n_si_Vector; i++) n += fprintf(stdout, " %3d", uvw[i]); if (SgInfo->LatticeInfo->Code != 'P') { hP = h * CCMx_PL[0] + k * CCMx_PL[3] + l * CCMx_PL[6]; kP = h * CCMx_PL[1] + k * CCMx_PL[4] + l * CCMx_PL[7]; lP = h * CCMx_PL[2] + k * CCMx_PL[5] + l * CCMx_PL[8]; if (hP % deterCCMx_LP || kP % deterCCMx_LP || lP % deterCCMx_LP) goto ReturnError; hP /= deterCCMx_LP; kP /= deterCCMx_LP; lP /= deterCCMx_LP; while (n < 55) { n++; putc(' ', stdout); } n += fprintf(stdout, " P %3d %3d %3d", hP, kP, lP); } putc('\n', stdout); } else if (ListSysAbsent) fprintf(stdout, "# %3d %3d %3d %3d (%d)\n", h, k, l, M, iList); } fprintf(stdout, ">End hklList\n"); return; ReturnError: SetSgError("Internal Error: Simple_hklList()"); return; } /* **************************************************************************** some code for the handling of lattice constants */ #include typedef struct { double a, b, c; double alpha, beta, gamma; double sa, sb, sg; double ca, cb, cg; double v; char calcs, calcc; } T_LatticeConstants; #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #define PIover180 (M_PI / 180.) #define EpsPI (1.e-6) /* ARBITRARY */ static double sinC(double arg) { if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) return 1.; else return sin(arg); } static double cosC(double arg) { if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) return 0.; else return cos(arg); } static int Lc2RLc(T_LatticeConstants * lc, T_LatticeConstants * rlc) { /* Transformation Lattice Constants -> Reciprocal Lattice Constants after Kleber, W., 17. Aufl., Verlag Technik GmbH Berlin 1990, P.352 */ double D; if (lc->calcs) { lc->sa = sinC(lc->alpha); lc->sb = sinC(lc->beta); lc->sg = sinC(lc->gamma); lc->calcs = 0; } if (lc->calcc) { lc->ca = cosC(lc->alpha); lc->cb = cosC(lc->beta); lc->cg = cosC(lc->gamma); lc->calcc = 0; } D = 1. - lc->ca * lc->ca - lc->cb * lc->cb - lc->cg * lc->cg + 2. * lc->ca * lc->cb * lc->cg; if (D < 0.) return -1; lc->v = lc->a * lc->b * lc->c * sqrt(D); if (lc->v == 0.) return -1; if (lc->sa == 0. || lc->sb == 0. || lc->sg == 0.) return -1; if (rlc != NULL) { rlc->a = lc->b * lc->c * lc->sa / lc->v; rlc->b = lc->c * lc->a * lc->sb / lc->v; rlc->c = lc->a * lc->b * lc->sg / lc->v; rlc->ca = (lc->cb * lc->cg - lc->ca) / (lc->sb * lc->sg); rlc->cb = (lc->cg * lc->ca - lc->cb) / (lc->sg * lc->sa); rlc->cg = (lc->ca * lc->cb - lc->cg) / (lc->sa * lc->sb); rlc->alpha = acos(rlc->ca); rlc->beta = acos(rlc->cb); rlc->gamma = acos(rlc->cg); rlc->sa = sinC(rlc->alpha); rlc->sb = sinC(rlc->beta); rlc->sg = sinC(rlc->gamma); rlc->v = 1. / lc->v; rlc->calcs = 0; rlc->calcc = 0; } return 0; } static void Lc2MetricalMx(T_LatticeConstants * lc, double *G) { G[0] = lc->a * lc->a; G[1] = G[3] = lc->a * lc->b * lc->cg; G[2] = G[6] = lc->a * lc->c * lc->cb; G[4] = lc->b * lc->b; G[5] = G[7] = lc->b * lc->c * lc->ca; G[8] = lc->c * lc->c; } static int HarmonizeSgLatCon(T_SgInfo * SgInfo, T_LatticeConstants * lc, int np) { switch (SgInfo->XtalSystem) { case XS_Triclinic: if (np != 6) goto IllUnitCell; break; case XS_Monoclinic: if (np != 4 && np != 6) goto IllUnitCell; switch (SgInfo->UniqueRefAxis) { case 'x': lc->beta = lc->gamma = 90. * PIover180; break; case 'y': if (np != 6) lc->beta = lc->alpha; lc->alpha = lc->gamma = 90. * PIover180; break; case 'z': if (np != 6) lc->gamma = lc->alpha; lc->alpha = lc->beta = 90. * PIover180; break; default: goto IntErr; } break; case XS_Orthorhombic: if (np != 3 && np != 6) goto IllUnitCell; lc->alpha = lc->beta = lc->gamma = 90. * PIover180; break; case XS_Tetragonal: if (np != 2 && np != 6) goto IllUnitCell; switch (SgInfo->UniqueRefAxis) { case 'x': lc->c = lc->b; break; case 'y': lc->c = lc->a; break; case 'z': if (np != 6) lc->c = lc->b; lc->b = lc->a; break; default: goto IntErr; } lc->alpha = lc->beta = lc->gamma = 90. * PIover180; break; case XS_Trigonal: if (np != 2 && np != 6) goto IllUnitCell; if (SgInfo->UniqueDirCode == '*') { if (np != 6) lc->alpha = lc->b * PIover180; lc->c = lc->b = lc->a; lc->gamma = lc->beta = lc->alpha; break; } case XS_Hexagonal: if (np != 2 && np != 6) goto IllUnitCell; switch (SgInfo->UniqueRefAxis) { case 'x': lc->c = lc->b; lc->alpha = 120. * PIover180; lc->beta = lc->gamma = 90. * PIover180; break; case 'y': lc->c = lc->a; lc->beta = 120. * PIover180; lc->alpha = lc->gamma = 90. * PIover180; break; case 'z': if (np != 6) lc->c = lc->b; lc->b = lc->a; lc->gamma = 120. * PIover180; lc->alpha = lc->beta = 90. * PIover180; break; default: goto IntErr; } break; case XS_Cubic: if (np != 1 && np != 6) goto IllUnitCell; lc->c = lc->b = lc->a; lc->alpha = lc->beta = lc->gamma = 90. * PIover180; break; default: goto IntErr; } return 0; IntErr:SetSgError("Internal Error: HarmonizeSgLatCon()"); return -1; IllUnitCell:SetSgError("Error: Illegal UnitCell or SpaceGroup"); return -1; } static void MxMultiply(double *ab, double *a, double *b, int ma, int na, int nb) { int i, j, k; double *ai, *aij, *bk, *bkj; ai = a; for (i = 0; i < ma; i++) { bk = b; for (k = 0; k < nb; k++) { aij = ai; bkj = bk; *ab = 0.; for (j = 0; j < na; j++) { *ab += (*aij) * (*bkj); aij++; bkj += nb; } ab++; bk++; } ai += na; } } static int TransformLatticeConstants(T_LatticeConstants * LatConA, int np, T_LatticeConstants * LatConB, T_SgInfo * SgInfo, int *InvCBMxR) { int i, j; double GA[9], GB[9], GAR[9], R[9], Rt[9]; if (HarmonizeSgLatCon(SgInfo, LatConA, np) != 0) return -1; LatConA->calcs = 1; LatConA->calcc = 1; /* just to check LatConA and to compute sin and cos of angles */ if (Lc2RLc(LatConA, LatConB) != 0) { SetSgError("Error: Illegal UnitCell"); return -1; } Lc2MetricalMx(LatConA, GA); for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) { R[i * 3 + j] = InvCBMxR[i * 3 + j] / (double) CRBF; Rt[i * 3 + j] = InvCBMxR[j * 3 + i] / (double) CRBF; } MxMultiply(GAR, GA, R, 3, 3, 3); MxMultiply(GB, Rt, GAR, 3, 3, 3); if (GB[0] < 0. || GB[4] < 0. || GB[8] < 0.) goto ReturnError; LatConB->a = sqrt(GB[0]); LatConB->b = sqrt(GB[4]); LatConB->c = sqrt(GB[8]); LatConB->alpha = GB[5] / LatConB->b / LatConB->c; LatConB->beta = GB[2] / LatConB->c / LatConB->a; LatConB->gamma = GB[1] / LatConB->a / LatConB->b; if (LatConB->alpha < -1. || LatConB->alpha > 1. || LatConB->beta < -1. || LatConB->beta > 1. || LatConB->gamma < -1. || LatConB->gamma > 1.) goto ReturnError; LatConB->alpha = acos(LatConB->alpha); LatConB->beta = acos(LatConB->beta); LatConB->gamma = acos(LatConB->gamma); LatConB->calcs = 1; LatConB->calcc = 1; return 0; ReturnError: SetSgError("InternalError: Corrupt InvCBMxR"); return -1; } /* **************************************************************************** */ static void usage(void) { static const char *quick_help[] = { "-Hall|VolA|VolI select conventions", "-ListTable[=#] print [parts of] internal table", "-CIF print internal table in CIF format", "-XYZ print something like \"-x, y+1/2, z\"", "-AllXYZ print all symmetry operations", "-Maple print symmetry matrices in Maple format", "-Space print symmetry file for AVS SpaceModule", "-Shelx print Shelx LATT & SYMM cards", "-Schakal print Schakal DU & SY cards", "-hklList print simple hkl listing", "-Standard compute transformation to \"standard\" setting", "-UnitCell=\"a..g\" unit cell constants a, b, c, alpha, beta, gamma", "-v be more verbose", "-Verify debug option: verify transformations", "-ClearError debug option: clear errors and continue", NULL }; const char **qh; fprintf(stderr, "usage: %s [options] [SpaceGroupName_or_# [SpaceGroupName_or_#]]\n", progn); for (qh = quick_help; *qh; qh++) fprintf(stderr, " %s\n", *qh); putc('\n', stderr); fprintf(stderr, "examples: %s 68\n", progn); fprintf(stderr, " %s C2/m:c2 -XYZ\n", progn); fprintf(stderr, " %s \"Oh^3\" -Shelx\n", progn); fprintf(stderr, " %s -Hall \"-F 4y 2\" -Standard\n", progn); fprintf(stderr, " %s -VolI 15 -VolA 15\n", progn); fprintf(stderr, " %s -ListTable=68\n", progn); exit(1); } static void ShowCBMx(T_RTMx * CBMx, T_RTMx * InvCBMx, int F_Maple) { if (F_Maple) { PrintMapleRTMx(CBMx, CRBF, CTBF, " CBMx", stdout); PrintMapleRTMx(InvCBMx, CRBF, CTBF, "InvCBMx", stdout); } else { fprintf(stdout, " CBMx = %s\n", RTMx2XYZ(CBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); fprintf(stdout, "InvCBMx = %s\n", RTMx2XYZ(InvCBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); } } typedef struct { int Convention; const char *SgName; const T_TabSgName *InpTSgN; const T_TabSgName *RefTSgN; T_RTMx CBMx, InvCBMx; } T_SgList; int main(int argc, char *argv[]) { int i, n, HaveSpace, pos_hsym; int F_Convention, Last_F_Convention; int F_ListTable, F_CIF; int F_XYZ, F_AllXYZ, F_Maple; int F_Space, F_Shelx, F_Schakal; int F_hklList; int F_Standard, F_UnitCell; int F_Verbose, F_Verify, F_ClearError; T_LatticeConstants LatConA, LatConB; char *cp, xtrac; const char *SgName; const T_TabSgName *tsgn; T_SgInfo SpgrInfo[2], BC_SgInfo, *SgInfo; int nSgList, iSgList; T_SgList SgList[2]; T_RTMx *CBMx, *InvCBMx; T_RTMx CCBMx, CInvCBMx; /* Macintosh extras (Courtesy Jon Tischler ) */ #ifdef __THINK__ console_options.nrows = CONSOLE_LINES; console_options.ncols = CONSOLE_COLUMNS; console_options.title = "\psgInfo version 1.0.1"; #endif #ifdef __MWERKS__ SIOUXSettings.autocloseonquit = FALSE; SIOUXSettings.asktosaveonclose = TRUE; SIOUXSettings.columns = CONSOLE_COLUMNS; SIOUXSettings.rows = CONSOLE_LINES; #endif #if defined(__THINK__) || defined(__MWERKS__) argc = ccommand(&argv); #endif nSgList = 0; F_Convention = 'A'; Last_F_Convention = 0; F_ListTable = 0; F_CIF = 0; F_XYZ = 0; F_AllXYZ = 0; F_Maple = 0; F_Space = 0; F_Shelx = 0; F_Schakal = 0; F_hklList = 0; F_Standard = 0; F_UnitCell = 0; F_Verbose = 0; F_Verify = 0; F_ClearError = 0; for (i = 1; i < argc; i++) { if (str_icmp(argv[i], "-Hall") == 0) { F_Convention = 'H'; Last_F_Convention = 0; } else if (str_icmp(argv[i], "-VolA") == 0) { F_Convention = 'A'; Last_F_Convention = 'A'; } else if (str_icmp(argv[i], "-VolI") == 0 || str_icmp(argv[i], "-Vol1") == 0) { F_Convention = 'I'; Last_F_Convention = 'I'; } else if (str_ibegin(argv[i], "-ListTable") == 0) { cp = argv[i] + 10; if (*cp == '\0') F_ListTable = -1; else if (*cp++ == '=') { n = sscanf(cp, "%d%c", &F_ListTable, &xtrac); if (n != 1 || F_ListTable < 1 || F_ListTable > 230) usage(); } else usage(); } else if (str_icmp(argv[i], "-CIF") == 0) F_CIF = 1; else if (str_icmp(argv[i], "-XYZ") == 0) F_XYZ = 1; else if (str_icmp(argv[i], "-AllXYZ") == 0) F_AllXYZ = 1; else if (str_icmp(argv[i], "-Maple") == 0) F_Maple = 1; else if (str_icmp(argv[i], "-Space") == 0) F_Space = 1; else if (str_icmp(argv[i], "-Shelx") == 0) F_Shelx = 1; else if (str_icmp(argv[i], "-Schakal") == 0) F_Schakal = 1; else if (str_icmp(argv[i], "-hklList") == 0) F_hklList = 1; else if (str_icmp(argv[i], "-Standard") == 0) F_Standard = 1; else if (str_ibegin(argv[i], "-UnitCell=") == 0) { F_UnitCell = sscanf(&argv[i][10], "%lf%lf%lf%lf%lf%lf", &LatConA.a, &LatConA.b, &LatConA.c, &LatConA.alpha, &LatConA.beta, &LatConA.gamma); if (F_UnitCell < 1) usage(); if (F_UnitCell > 3) LatConA.alpha *= PIover180; if (F_UnitCell > 4) LatConA.beta *= PIover180; if (F_UnitCell > 5) LatConA.gamma *= PIover180; } else if (str_icmp(argv[i], "-v") == 0) F_Verbose = 1; else if (str_icmp(argv[i], "-Verify") == 0) F_Verify = 1; else if (str_icmp(argv[i], "-ClearError") == 0) F_ClearError = 1; else if (nSgList < 2) { SgName = argv[i]; while (*SgName == ' ' || *SgName == '\t') SgName++; if (F_Convention == 'H' && isdigit(*SgName)) SgList[nSgList].Convention = 'A'; else SgList[nSgList].Convention = F_Convention; SgList[nSgList].SgName = SgName; SgList[nSgList].InpTSgN = NULL; SgList[nSgList].RefTSgN = NULL; nSgList++; } else usage(); } if (F_ListTable) { ListTabSgName(F_ListTable, Last_F_Convention, stdout); PrintClearSgError(1, 0); putc('\n', stdout); } if (F_CIF) { ListCIF(stdout); PrintClearSgError(1, 0); putc('\n', stdout); } if (nSgList == 0) { if (F_ListTable == 0 && F_CIF == 0) usage(); else exit(0); } if (F_Space == 0) { putc('#', stdout); for (i = 0; i < argc; i++) { putc(' ', stdout); HaveSpace = 0; if (i) { for (n = 0; argv[i][n]; n++) { if (isspace(argv[i][n])) { HaveSpace = 1; break; } } } if (HaveSpace == 0) fprintf(stdout, "%s", argv[i]); else { putc('"', stdout); for (n = 0; argv[i][n]; n++) if (argv[i][n] == '"') putc('+', stdout); else putc(argv[i][n], stdout); putc('"', stdout); } } putc('\n', stdout); } BC_SgInfo.MaxList = 0; BC_SgInfo.ListSeitzMx = NULL; BC_SgInfo.ListRotMxInfo = NULL; for (iSgList = 0; iSgList < nSgList; iSgList++) { if (iSgList) putc('\n', stdout); if (nSgList > 1 || F_Standard) fprintf(stdout, "Setting %c:\n\n", "AB"[iSgList]); SgInfo = &SpgrInfo[iSgList]; SgInfo->MaxList = 192; SgInfo->ListSeitzMx = malloc(SgInfo->MaxList * sizeof(*SgInfo->ListSeitzMx)); if (SgInfo->ListSeitzMx == NULL) NotEnoughCore(); #ifndef No_ListRotMxInfo SgInfo->ListRotMxInfo = malloc(SgInfo->MaxList * sizeof(*SgInfo->ListRotMxInfo)); if (SgInfo->ListRotMxInfo == NULL) NotEnoughCore(); #else SgInfo->ListRotMxInfo = NULL; #endif F_Convention = SgList[iSgList].Convention; SgName = SgList[iSgList].SgName; tsgn = NULL; if (F_Convention == 'A' || F_Convention == 'I') { tsgn = FindTabSgNameEntry(SgName, F_Convention); if (tsgn == NULL) { PrintClearSgError(1, 0); progerror("Error: Unknown Space Group Symbol"); } if (F_Space == 0) { fprintf(stdout, "Space Group "); PrintTabSgNameEntry(tsgn, 0, 0, stdout); putc('\n', stdout); } SgName = tsgn->HallSymbol; } SgList[iSgList].InpTSgN = tsgn; InitSgInfo(SgInfo); SgInfo->TabSgName = tsgn; if (tsgn) SgInfo->GenOption = 1; pos_hsym = ParseHallSymbol(SgName, SgInfo); if (SgError != NULL) { fprintf(stdout, " %s\n", SgName); for (i = 0; i < pos_hsym; i++) putc('-', stdout); fprintf(stdout, "---^\n"); fprintf(stdout, "%s\n", SgError); exit(1); } if (CompleteSgInfo(SgInfo) != 0) PrintClearSgError(F_ClearError, 1); if (tsgn == NULL && F_Space == 0) { if (SgInfo->TabSgName) { fprintf(stdout, "Space Group "); PrintTabSgNameEntry(SgInfo->TabSgName, 0, 0, stdout); putc('\n', stdout); } else fprintf(stdout, "Hall Symbol %s\n", SgInfo->HallSymbol); } PrintClearSgError(F_ClearError, 0); #if USE_GS_SI if (Try_GS_si(SgInfo) < 0) #else if (Set_si(SgInfo) < 0) #endif PrintClearSgError(F_ClearError, 1); if (F_Space == 0) { ListSgInfo(SgInfo, F_XYZ, F_Verbose, stdout); PrintClearSgError(F_ClearError, 0); } if (F_AllXYZ) { PutAllXYZ(SgInfo, stdout); PrintClearSgError(F_ClearError, 0); } if (F_Maple) { PutMaple(SgInfo, stdout); PrintClearSgError(F_ClearError, 0); } if (F_Space) { PutSpaceSymFile(SgInfo, stdout); PrintClearSgError(F_ClearError, 0); } if (F_Shelx) { PutShelx(SgInfo, stdout); PrintClearSgError(F_ClearError, 0); } if (F_Schakal) { PutSchakal(SgInfo, stdout); PrintClearSgError(F_ClearError, 0); } if (F_hklList) { Simple_hklList(SgInfo, 4, 4, 4, F_Verbose); PrintClearSgError(F_ClearError, 0); } if (nSgList > 1 || F_Standard) { CBMx = &SgList[iSgList].CBMx; InvCBMx = &SgList[iSgList].InvCBMx; SgList[iSgList].RefTSgN = FindReferenceSpaceGroup(SgInfo, CBMx, InvCBMx); PrintClearSgError(F_ClearError, 0); if (SgList[iSgList].RefTSgN) { if (F_Verbose || F_Verify) { fprintf(stdout, "Change of Basis => Reference Setting "); PrintTabSgNameEntry(SgList[iSgList].RefTSgN, 0, 0, stdout); putc('\n', stdout); ShowCBMx(CBMx, InvCBMx, F_Maple); PrintClearSgError(F_ClearError, 0); } if (F_Verify) { if (BC_SgInfo.MaxList == 0) { BC_SgInfo.MaxList = 192; BC_SgInfo.ListSeitzMx = malloc(BC_SgInfo.MaxList * sizeof(*BC_SgInfo.ListSeitzMx)); if (BC_SgInfo.ListSeitzMx == NULL) NotEnoughCore(); BC_SgInfo.ListRotMxInfo = malloc(BC_SgInfo.MaxList * sizeof(*BC_SgInfo.ListRotMxInfo)); if (BC_SgInfo.ListRotMxInfo == NULL) NotEnoughCore(); } InitSgInfo(&BC_SgInfo); if (TransformSgInfo(SgInfo, CBMx, InvCBMx, &BC_SgInfo) == 0) CompleteSgInfo(&BC_SgInfo); if (SgError) { PrintClearSgError(F_ClearError, 0); SgList[iSgList].RefTSgN = NULL; } else if (BC_SgInfo.TabSgName != SgList[iSgList].RefTSgN) { fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); SetSgError("Verify Error: Wrong CBMx/InvCBMx"); PrintClearSgError(F_ClearError, 0); SgList[iSgList].RefTSgN = NULL; } else fprintf(stdout, "Verify O.K.\n\n"); } } tsgn = SgList[iSgList].RefTSgN; if (tsgn && F_Standard && nSgList == 1) { if (Last_F_Convention == 'A' || Last_F_Convention == 'I') SgList[nSgList].Convention = Last_F_Convention; else SgList[nSgList].Convention = 'A'; SgList[nSgList].SgName = SchoenfliesSymbols[tsgn->SgNumber]; SgList[nSgList].InpTSgN = NULL; SgList[nSgList].RefTSgN = NULL; nSgList++; } } } if (nSgList == 2 && SgList[0].RefTSgN && SgList[1].RefTSgN && SgList[0].RefTSgN->SgNumber == SgList[1].RefTSgN->SgNumber) { putc('\n', stdout); fprintf(stdout, "Change of Basis Setting A -> Setting B:\n"); RTMxMultiply(&CCBMx, &SgList[1].InvCBMx, &SgList[0].CBMx, CRBF, CRBF * CTBF); RTMxMultiply(&CInvCBMx, &SgList[0].InvCBMx, &SgList[1].CBMx, CRBF, CRBF * CTBF); for (i = 0; i < 12; i++) { if (CCBMx.a[i] % CRBF) break; if (CInvCBMx.a[i] % CRBF) break; CCBMx.a[i] /= CRBF; CInvCBMx.a[i] /= CRBF; } if (i < 12) { SetSgError("Internal Error: Can't combine CBMx's"); PrintClearSgError(1, 1); } else { ShowCBMx(&CCBMx, &CInvCBMx, F_Maple); PrintClearSgError(F_ClearError, 0); if (F_Verify) { InitSgInfo(&BC_SgInfo); if (TransformSgInfo(&SpgrInfo[0], &CCBMx, &CInvCBMx, &BC_SgInfo) == 0) CompleteSgInfo(&BC_SgInfo); if (SgError) PrintClearSgError(F_ClearError, 1); else if (strcmp(SpgrInfo[1].HallSymbol, BC_SgInfo.HallSymbol) != 0) { fprintf(stdout, "Hall Symbol %s\n", SpgrInfo[1].HallSymbol); fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); SetSgError("Verify Error: Wrong CBMx/InvCBMx"); PrintClearSgError(F_ClearError, 1); } else fprintf(stdout, "Verify O.K.\n"); } if (F_UnitCell) { putc('\n', stdout); if (TransformLatticeConstants(&LatConA, F_UnitCell, &LatConB, &SpgrInfo[0], CInvCBMx.s.R) != 0) PrintClearSgError(0, 1); fprintf(stdout, "Setting A UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", LatConA.a, LatConA.b, LatConA.c, LatConA.alpha / PIover180, LatConA.beta / PIover180, LatConA.gamma / PIover180); fprintf(stdout, "Setting B UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", LatConB.a, LatConB.b, LatConB.c, LatConB.alpha / PIover180, LatConB.beta / PIover180, LatConB.gamma / PIover180); } } putc('\n', stdout); } exit(0); /* old VAX didn't like "return 0;" */ return 0; }