📄 field-smob.c
字号:
void field_mapLB(SCM dest, function f, SCM_list src){ field_smob *pd = assert_field_smob(dest); field_smob **ps; int i, j; CHK_MALLOC(ps, field_smob *, src.num_items); for (j = 0; j < src.num_items; ++j) { ps[j] = assert_field_smob(src.items[j]); CHECK(fields_conform(pd, ps[j]), "fields for field-map! must conform"); } for (i = 0; i < pd->N; ++i) { list arg_list = SCM_EOL; SCM result; for (j = src.num_items - 1; j >= 0; --j) { SCM item = SCM_EOL; switch (ps[j]->type) { case RSCALAR_FIELD_SMOB: item = gh_double2scm(ps[j]->f.rs[i]); break; case CVECTOR_FIELD_SMOB: item = cvector32scm(cscalar32cvector3(ps[j]->f.cv+3*i)); break; } arg_list = gh_cons(item, arg_list); } result = gh_apply(f, arg_list); switch (pd->type) { case RSCALAR_FIELD_SMOB: pd->f.rs[i] = gh_scm2double(result); break; case CVECTOR_FIELD_SMOB: cvector32cscalar3(pd->f.cv+3*i, scm2cvector3(result)); break; } } free(ps); if (src.num_items == 1 && ps[0]->type == pd->type) pd->type_char = ps[0]->type_char; else if (src.num_items > 1) switch (pd->type) { case RSCALAR_FIELD_SMOB: pd->type_char = 'R'; break; case CVECTOR_FIELD_SMOB: pd->type_char = 'c'; break; } update_curfield(pd);}/*************************************************************************/static cvector3 cvector3_conj(cvector3 c){ cvector3 cc; cc.x = cnumber_conj(c.x); cc.y = cnumber_conj(c.y); cc.z = cnumber_conj(c.z); return cc;}/* Compute the integral of f(r, {fields}) over the cell. */cnumber integrate_fieldL(function f, SCM_list fields){ int i, j, k, n1, n2, n3, n_other, n_last, rank, last_dim;#ifdef HAVE_MPI int local_n2, local_y_start, local_n3;#endif real s1, s2, s3, c1, c2, c3; int ifield; field_smob **pf; cnumber integral = {0,0}; CHK_MALLOC(pf, field_smob *, fields.num_items); for (ifield = 0; ifield < fields.num_items; ++ifield) { pf[ifield] = assert_field_smob(fields.items[ifield]); CHECK(fields_conform(pf[0], pf[ifield]), "fields for integrate-fields must conform"); } if (fields.num_items > 0) { n1 = pf[0]->nx; n2 = pf[0]->ny; n3 = pf[0]->nz; n_other = pf[0]->other_dims; n_last = pf[0]->last_dim_size / (sizeof(scalar_complex)/sizeof(scalar)); last_dim = pf[0]->last_dim; } else { n1 = mdata->nx; n2 = mdata->ny; n3 = mdata->nz; n_other = mdata->other_dims; n_last = mdata->last_dim_size / (sizeof(scalar_complex)/sizeof(scalar)); last_dim = mdata->last_dim; } rank = (n3 == 1) ? (n2 == 1 ? 1 : 2) : 3; s1 = geometry_lattice.size.x / n1; s2 = geometry_lattice.size.y / n2; s3 = geometry_lattice.size.z / n3; c1 = n1 <= 1 ? 0 : geometry_lattice.size.x * 0.5; c2 = n2 <= 1 ? 0 : geometry_lattice.size.y * 0.5; c3 = n3 <= 1 ? 0 : geometry_lattice.size.z * 0.5; /* Here we have different loops over the coordinates, depending upon whether we are using complex or real and serial or parallel transforms. Each loop must define, in its body, variables (i2,j2,k2) describing the coordinate of the current point, and "index" describing the corresponding index in the curfield array. This was all stolen from maxwell_eps.c...it would be better if we didn't have to cut and paste, sigh. */#ifdef SCALAR_COMPLEX# ifndef HAVE_MPI for (i = 0; i < n1; ++i) for (j = 0; j < n2; ++j) for (k = 0; k < n3; ++k) { int i2 = i, j2 = j, k2 = k; int index = ((i * n2 + j) * n3 + k);# else /* HAVE_MPI */ if (fields.num_items > 0) { local_n2 = pf[0]->local_ny; local_y_start = pf[0]->local_y_start; } else { local_n2 = mdata->local_ny; local_y_start = mdata->local_y_start; } /* first two dimensions are transposed in MPI output: */ for (j = 0; j < local_n2; ++j) for (i = 0; i < n1; ++i) for (k = 0; k < n3; ++k) { int i2 = i, j2 = j + local_y_start, k2 = k; int index = ((j * n1 + i) * n3 + k);# endif /* HAVE_MPI */#else /* not SCALAR_COMPLEX */# ifndef HAVE_MPI for (i = 0; i < n_other; ++i) for (j = 0; j < n_last; ++j) { int index = i * n_last + j; int i2, j2, k2; switch (rank) { case 2: i2 = i; j2 = j; k2 = 0; break; case 3: i2 = i / n2; j2 = i % n2; k2 = j; break; default: i2 = j; j2 = k2 = 0; break; }# else /* HAVE_MPI */ if (fields.num_items > 0) { local_n2 = pf[0]->local_ny; local_y_start = pf[0]->local_y_start; } else { local_n2 = mdata->local_ny; local_y_start = mdata->local_y_start; } /* For a real->complex transform, the last dimension is cut in half. For a 2d transform, this is taken into account in local_ny already, but for a 3d transform we must compute the new n3: */ if (n3 > 1) { if (fields.num_items > 0) local_n3 = pf[0]->last_dim_size / 2; else local_n3 = mdata->last_dim_size / 2; } else local_n3 = 1; /* first two dimensions are transposed in MPI output: */ for (j = 0; j < local_n2; ++j) for (i = 0; i < n1; ++i) for (k = 0; k < local_n3; ++k) {# define i2 i int j2 = j + local_y_start;# define k2 k int index = ((j * n1 + i) * local_n3 + k);# endif /* HAVE_MPI */#endif /* not SCALAR_COMPLEX */ { list arg_list = SCM_EOL; cnumber integrand; vector3 p; p.x = i2 * s1 - c1; p.y = j2 * s2 - c2; p.z = k2 * s3 - c3; for (ifield = fields.num_items - 1; ifield >= 0; --ifield) { SCM item = SCM_EOL; switch (pf[ifield]->type) { case RSCALAR_FIELD_SMOB: item = gh_double2scm(pf[ifield]->f.rs[index]); break; case CVECTOR_FIELD_SMOB: item = cvector32scm(cscalar32cvector3( pf[ifield]->f.cv+3*index)); break; } arg_list = gh_cons(item, arg_list); } arg_list = gh_cons(vector32scm(p), arg_list); integrand = ctl_convert_cnumber_to_c(gh_apply(f, arg_list)); integral.re += integrand.re; integral.im += integrand.im;#ifndef SCALAR_COMPLEX { int last_index;# ifdef HAVE_MPI if (n3 == 1) last_index = j + local_y_start; else last_index = k;# else last_index = j;# endif if (last_index != 0 && 2*last_index != last_dim) { int i2c, j2c, k2c; i2c = i2 ? (n1 - i2) : 0; j2c = j2 ? (n2 - j2) : 0; k2c = k2 ? (n3 - k2) : 0; p.x = i2c * s1 - c1; p.y = j2c * s2 - c2; p.z = k2c * s3 - c3; arg_list = SCM_EOL; for (ifield = fields.num_items - 1; ifield >= 0; --ifield) { SCM item; switch (pf[ifield]->type) { case RSCALAR_FIELD_SMOB: item = gh_double2scm( pf[ifield]->f.rs[index]); break; case CVECTOR_FIELD_SMOB: item = cvector32scm( cvector3_conj(cscalar32cvector3( pf[ifield]->f.cv+3*index))); break; } arg_list = gh_cons(item, arg_list); } arg_list = gh_cons(vector32scm(p), arg_list); integrand = ctl_convert_cnumber_to_c(gh_apply(f, arg_list)); integral.re += integrand.re; integral.im += integrand.im; } }#endif } } free(pf); integral.re *= Vol / (n1 * n2 * n3); integral.im *= Vol / (n1 * n2 * n3); { cnumber integral_sum; mpi_allreduce(&integral, &integral_sum, 2, number, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); return integral_sum; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -