msym_error_t findPermutation(msym_symmetry_operation_t *sop, int l, double (*v[l])[3], msym_thresholds_t *t, msym_permutation_t *perm){ msym_error_t ret = MSYM_SUCCESS; double m[3][3]; symmetryOperationMatrix(sop, m); perm->p = malloc(sizeof(int[l])); memset(perm->p, -1, sizeof(int[l])); //TODO: 2s complement perm->p_length = l; for(int i = 0; i < l;i++){ int j; double r[3]; mvmul(*v[i], m, r); for(j = 0;j < l;j++){ if(vequal(r, *v[j],t->permutation)){ perm->p[i] = j; break; } } if(j == l) { char buf[16]; symmetryOperationName(sop, sizeof(buf), buf); msymSetErrorDetails("Unable to determine permutation for symmetry operation %s",buf); ret = MSYM_PERMUTATION_ERROR; goto err; } } if(MSYM_SUCCESS != (ret = setPermutationCycles(perm))) goto err; return ret; err: free(perm->p); return ret; }
msym_error_t generateOrbitalTransforms(int sopsl, msym_symmetry_operation_t sops[sopsl], int l, double transform[sopsl][2*l+1][2*l+1]){ msym_error_t ret = MSYM_SUCCESS; int kdim = ipow(3,l), norbs = 2*l+1; double (*mkron)[kdim][kdim] = malloc(sizeof(double[2][kdim][kdim])); double (*poly)[kdim] = malloc(sizeof(double[norbs][kdim])); for(int m = -l; m <= l;m++){ if(MSYM_SUCCESS != (ret = orbitalPolynomial(l,m,poly[m+l]))) goto err; //Normalization vlnorm(kdim, poly[m+l]); } for(int i = 0;i < sopsl;i++){ double M[3][3]; mkron[0][0][0] = 1.0; symmetryOperationMatrix(&sops[i], M); for(int j = 0, d = 1;j < l;j++, d *= 3){ kron(3,M,d,mkron[j%2],3*d,mkron[(j+1)%2]); } mmlmul(norbs, kdim, poly, kdim, mkron[l%2], mkron[(l+1)%2]); mmtlmul(norbs, kdim, mkron[(l+1)%2], norbs, poly, transform[i]); /* Scaling for(int j = 0; j < norbs;j++){ double scale = vldot(kdim, poly[j], poly[j]); vlscale(1.0/scale, norbs, transform[i][j], transform[i][j]); }*/ } err: free(mkron); free(poly); return ret; }
msym_error_t findSymmetryOperationPermutations(int l, msym_symmetry_operation_t sops[l], msym_thresholds_t *t, msym_permutation_t **rperm){ msym_error_t ret = MSYM_SUCCESS; //Don't block allocate this, it's a pain to keep track of the pointers msym_permutation_t *permutations = malloc(sizeof(msym_permutation_t[l])); for(int i = 0; i < l;i++){ permutations[i].p = malloc(sizeof(int[l])); memset(permutations[i].p, -1, sizeof(int[l])); permutations[i].p_length = l; } double (*msops)[3][3] = malloc(sizeof(double[l][3][3])); for(int i = 0; i < l;i++){ symmetryOperationMatrix(&sops[i], msops[i]); } for(int i = 0; i < l;i++){ if((sops[i].type == PROPER_ROTATION && sops[i].order == 0) || sops[i].type == IDENTITY){ for(int j = 0;j < l;j++) permutations[i].p[j] = j; } else { for(int j = 0; j < l;j++){ int k; double rsop[3][3]; mmmul(msops[i], msops[j], rsop); for(k = 0;k < l;k++){ if(mequal(rsop,msops[k],t->permutation)){ permutations[i].p[j] = k; break; } } if(k == l){ char buf1[16]; char buf2[16]; symmetryOperationName(&sops[i], sizeof(buf1), buf1); symmetryOperationName(&sops[j], sizeof(buf2), buf2); msymSetErrorDetails("Unable to determine permutation for symmetry operation %s and %s",buf1, buf2); ret = MSYM_PERMUTATION_ERROR; goto err; } } } } for(int i = 0; i < l;i++){ if(MSYM_SUCCESS != (ret = setPermutationCycles(&permutations[i]))) goto err; } free(msops); *rperm = permutations; return ret; err: free(msops); for(int i = 0; i < l;i++){ free(permutations[i].p); } free(permutations); *rperm = NULL; return ret; }