int matrix3x3_inverse(const matrix3x3* matrix, matrix3x3* result){ double det = matrix3x3_determinant(matrix); if (det==0) return -1; double invdet=1/det; matrix3x3 matrix_t; if (matrix==result){ matrix3x3_copy(matrix, &matrix_t); matrix=&matrix_t; } result->m[0][0] = (matrix->m[1][1] * matrix->m[2][2] - matrix->m[2][1] * matrix->m[1][2]) * invdet; result->m[0][1] = -(matrix->m[0][1] * matrix->m[2][2] - matrix->m[2][1] * matrix->m[0][2]) * invdet; result->m[0][2] = (matrix->m[0][1] * matrix->m[1][2] - matrix->m[1][1] * matrix->m[0][2]) * invdet; result->m[1][0] = -(matrix->m[1][0] * matrix->m[2][2] - matrix->m[2][0] * matrix->m[1][2]) * invdet; result->m[1][1] = (matrix->m[0][0] * matrix->m[2][2] - matrix->m[2][0] * matrix->m[0][2]) * invdet; result->m[1][2] = -(matrix->m[0][0] * matrix->m[1][2] - matrix->m[1][0] * matrix->m[0][2]) * invdet; result->m[2][0] = (matrix->m[1][0] * matrix->m[2][1] - matrix->m[2][0] * matrix->m[1][1]) * invdet; result->m[2][1] = -(matrix->m[0][0] * matrix->m[2][1] - matrix->m[2][0] * matrix->m[0][1]) * invdet; result->m[2][2] = (matrix->m[0][0] * matrix->m[1][1] - matrix->m[1][0] * matrix->m[0][1]) * invdet; return 0; }
/* Initialize the dielectric function of the global mdata structure, along with other geometry data. Should be called from init-params, or in general when global input vars have been loaded and mdata allocated. */ void init_epsilon(void) { int i; int tree_depth, tree_nobjects; number no_size; no_size = 2.0 / ctl_get_number("infinity"); mpi_one_printf("Mesh size is %d.\n", mesh_size); no_size_x = geometry_lattice.size.x <= no_size; no_size_y = geometry_lattice.size.y <= no_size || dimensions < 2; no_size_z = geometry_lattice.size.z <= no_size || dimensions < 3; Rm.c0 = vector3_scale(no_size_x ? 1 : geometry_lattice.size.x, geometry_lattice.basis.c0); Rm.c1 = vector3_scale(no_size_y ? 1 : geometry_lattice.size.y, geometry_lattice.basis.c1); Rm.c2 = vector3_scale(no_size_z ? 1 : geometry_lattice.size.z, geometry_lattice.basis.c2); mpi_one_printf("Lattice vectors:\n"); mpi_one_printf(" (%g, %g, %g)\n", Rm.c0.x, Rm.c0.y, Rm.c0.z); mpi_one_printf(" (%g, %g, %g)\n", Rm.c1.x, Rm.c1.y, Rm.c1.z); mpi_one_printf(" (%g, %g, %g)\n", Rm.c2.x, Rm.c2.y, Rm.c2.z); Vol = fabs(matrix3x3_determinant(Rm)); mpi_one_printf("Cell volume = %g\n", Vol); Gm = matrix3x3_inverse(matrix3x3_transpose(Rm)); mpi_one_printf("Reciprocal lattice vectors (/ 2 pi):\n"); mpi_one_printf(" (%g, %g, %g)\n", Gm.c0.x, Gm.c0.y, Gm.c0.z); mpi_one_printf(" (%g, %g, %g)\n", Gm.c1.x, Gm.c1.y, Gm.c1.z); mpi_one_printf(" (%g, %g, %g)\n", Gm.c2.x, Gm.c2.y, Gm.c2.z); if (eigensolver_nwork > MAX_NWORK) { mpi_one_printf("(Reducing nwork = %d to maximum: %d.)\n", eigensolver_nwork, MAX_NWORK); eigensolver_nwork = MAX_NWORK; } matrix3x3_to_arr(R, Rm); matrix3x3_to_arr(G, Gm); /* we must do this to correct for a non-orthogonal lattice basis: */ geom_fix_objects(); mpi_one_printf("Geometric objects:\n"); if (mpi_is_master()) for (i = 0; i < geometry.num_items; ++i) { display_geometric_object_info(5, geometry.items[i]); if (geometry.items[i].material.which_subclass == MEDIUM) printf("%*sepsilon = %g, mu = %g\n", 5 + 5, "", geometry.items[i].material. subclass.medium_data->epsilon, geometry.items[i].material. subclass.medium_data->mu); } destroy_geom_box_tree(geometry_tree); /* destroy any tree from previous runs */ { geom_box b0; b0.low = vector3_plus(geometry_center, vector3_scale(-0.5, geometry_lattice.size)); b0.high = vector3_plus(geometry_center, vector3_scale(0.5, geometry_lattice.size)); /* pad tree boundaries to allow for sub-pixel averaging */ b0.low.x -= geometry_lattice.size.x / mdata->nx; b0.low.y -= geometry_lattice.size.y / mdata->ny; b0.low.z -= geometry_lattice.size.z / mdata->nz; b0.high.x += geometry_lattice.size.x / mdata->nx; b0.high.y += geometry_lattice.size.y / mdata->ny; b0.high.z += geometry_lattice.size.z / mdata->nz; geometry_tree = create_geom_box_tree0(geometry, b0); } if (verbose && mpi_is_master()) { printf("Geometry object bounding box tree:\n"); display_geom_box_tree(5, geometry_tree); } geom_box_tree_stats(geometry_tree, &tree_depth, &tree_nobjects); mpi_one_printf("Geometric object tree has depth %d and %d object nodes" " (vs. %d actual objects)\n", tree_depth, tree_nobjects, geometry.num_items); reset_epsilon(); }