ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
statistics_fluid.c
Go to the documentation of this file.
00001 /*
00002   Copyright (C) 2010,2011,2012,2013 The ESPResSo project
00003   Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 
00004     Max-Planck-Institute for Polymer Research, Theory Group
00005   
00006   This file is part of ESPResSo.
00007   
00008   ESPResSo is free software: you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation, either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   ESPResSo is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
00020 */
00021 /** \file statistics_fluid.c
00022  *
00023  * Fluid related analysis functions.
00024  * Implementation of \ref statistics_fluid.h.
00025  *
00026  */
00027 
00028 #include <mpi.h>
00029 #include "utils.h"
00030 #include "communication.h"
00031 #include "lb.h"
00032 #include "lb-boundaries.h"
00033 #include "statistics_fluid.h"
00034 
00035 #ifdef LB
00036 
00037 //#include <fftw3.h>
00038 
00039 /** Caclulate mass of the LB fluid.
00040  * \param result Fluid mass
00041  */
00042 void lb_calc_fluid_mass(double *result) {
00043   int x, y, z, index;
00044   double sum_rho=0.0, rho=0.0;
00045 
00046   for (x=1; x<=lblattice.grid[0]; x++) {
00047     for (y=1; y<=lblattice.grid[1]; y++) {
00048       for (z=1; z<=lblattice.grid[2]; z++) {
00049         index = get_linear_index(x,y,z,lblattice.halo_grid);
00050 
00051         lb_calc_local_rho(index,&rho);
00052         //fprintf(stderr,"(%d,%d,%d) %e\n",x,y,z,rho);
00053         sum_rho += rho;
00054 
00055       }
00056     }
00057   }
00058 
00059   MPI_Reduce(&sum_rho, result, 1, MPI_DOUBLE, MPI_SUM, 0, comm_cart);
00060 }
00061 
00062 /** Calculate momentum of the LB fluid.
00063  * \param result Fluid momentum
00064  */
00065 void lb_calc_fluid_momentum(double *result) {
00066 
00067     int x, y, z, index;
00068     double j[3], momentum[3] = { 0.0, 0.0, 0.0 };
00069 
00070     for (x=1; x<=lblattice.grid[0]; x++) {
00071         for (y=1; y<=lblattice.grid[1]; y++) {
00072             for (z=1; z<=lblattice.grid[2]; z++) {
00073                 index = get_linear_index(x,y,z,lblattice.halo_grid);
00074 
00075                 lb_calc_local_j(index,j);
00076                 momentum[0] += j[0] + lbfields[index].force[0];
00077                 momentum[1] += j[1] + lbfields[index].force[1];
00078                 momentum[2] += j[2] + lbfields[index].force[2];
00079 
00080             }
00081         }
00082     }
00083 
00084     momentum[0] *= lblattice.agrid/lbpar.tau;
00085     momentum[1] *= lblattice.agrid/lbpar.tau;
00086     momentum[2] *= lblattice.agrid/lbpar.tau;
00087 
00088     MPI_Reduce(momentum, result, 3, MPI_DOUBLE, MPI_SUM, 0, comm_cart);
00089     
00090 }
00091 
00092 /** Calculate temperature of the LB fluid.
00093  * \param result Fluid temperature
00094  */
00095 void lb_calc_fluid_temp(double *result) {
00096   int x, y, z, index;
00097   double rho, j[3];
00098   double temp = 0.0;
00099 
00100   for (x=1; x<=lblattice.grid[0]; x++) {
00101     for (y=1; y<=lblattice.grid[1]; y++) {
00102       for (z=1; z<=lblattice.grid[2]; z++) {
00103         index = get_linear_index(x,y,z,lblattice.halo_grid);
00104         
00105         lb_calc_local_fields(index, &rho, j, NULL);
00106 
00107         temp += scalar(j,j);
00108       }
00109     }
00110   }
00111 
00112   temp *= 1./(3.*lbpar.rho*lblattice.grid_volume*lbpar.tau*lbpar.tau*lblattice.agrid)/n_nodes;
00113 
00114   MPI_Reduce(&temp, result, 1, MPI_DOUBLE, MPI_SUM, 0, comm_cart);
00115 }
00116 
00117 void lb_collect_boundary_forces(double *result) {
00118 #ifdef LB_BOUNDARIES
00119   double* boundary_forces=malloc(3*n_lb_boundaries*sizeof(double));
00120 
00121   for (int i = 0; i < n_lb_boundaries; i++) 
00122     for (int j = 0; j < 3; j++)
00123       boundary_forces[3*i+j]=lb_boundaries[i].force[j];
00124 
00125   MPI_Reduce(boundary_forces, result, 3*n_lb_boundaries, MPI_DOUBLE, MPI_SUM, 0, comm_cart);
00126   free(boundary_forces);
00127 #endif
00128 }
00129 #define REQ_DENSPROF 702
00130 
00131 /** Calculate a density profile of the fluid. */
00132 void lb_calc_densprof(double *result, int *params) {
00133 
00134   int index, dir[3], grid[3];
00135   int newroot=0, subrank, involved=0;
00136   double *profile;
00137   MPI_Comm slice_comm;
00138   MPI_Status status;
00139 
00140   if (this_node !=0) params = malloc(3*sizeof(int));
00141 
00142   MPI_Bcast(params, 3, MPI_INT, 0, comm_cart);
00143 
00144   int pdir = params[0];
00145   int x1   = params[1];
00146   int x2   = params[2];
00147 
00148   dir[pdir] = 0;
00149   dir[(pdir+1)%3] = x1;
00150   dir[(pdir+2)%3] = x2;
00151 
00152   newroot = map_lattice_to_node(&lblattice, dir, grid);
00153   map_node_array(this_node, node_pos);
00154 
00155   if (     (grid[(pdir+1)%3] == node_pos[(pdir+1)%3])
00156         && (grid[(pdir+2)%3] == node_pos[(pdir+2)%3]) ) {
00157     involved = 1;
00158   }
00159 
00160   MPI_Comm_split(comm_cart, involved, this_node, &slice_comm);
00161   MPI_Comm_rank(slice_comm, &subrank);
00162 
00163   if (this_node == newroot)
00164     result = realloc(result,box_l[pdir]/lblattice.agrid*sizeof(double));
00165 
00166   if (involved) {
00167 
00168     profile = malloc(lblattice.grid[pdir]*sizeof(double));
00169       
00170     //dir[(pdir+1)%3] += 1;
00171     //dir[(pdir+2)%3] += 1;
00172     for (dir[pdir]=1;dir[pdir]<=lblattice.grid[pdir];dir[pdir]++) {
00173 
00174       index = get_linear_index(dir[0],dir[1],dir[2],lblattice.halo_grid);
00175       lb_calc_local_rho(index,&profile[dir[pdir]-1]);
00176       //profile[dir[pdir]-1] = *lbfluid[index].rho;
00177 
00178       //if (dir[pdir]==lblattice.grid[pdir]) {
00179       //        int i;
00180       //        fprintf(stderr,"(%d,%d,%d)\n",dir[0],dir[1],dir[2]);
00181       //        fprintf(stderr,"%d\n",lbfluid[index].boundary);
00182       //        for (i=0;i<lbmodel.n_veloc;i++) fprintf(stderr,"local_n[%p][%d]=%.12e\n",lbfluid[index].n,i,lbfluid[index].n[i]+lbmodel.coeff[i][0]*lbpar.rho);
00183       //        fprintf(stderr,"local_rho=%e\n",*lbfluid[index].rho);
00184       //}
00185 
00186   }
00187 
00188     MPI_Gather(profile, lblattice.grid[pdir], MPI_DOUBLE, result, lblattice.grid[pdir], MPI_DOUBLE, 0, slice_comm);
00189     
00190     free(profile);
00191 
00192   }
00193 
00194   MPI_Comm_free(&slice_comm);
00195 
00196   if (newroot != 0) {
00197     if (this_node == newroot) {
00198       MPI_Send(result, lblattice.grid[pdir]*node_grid[pdir], MPI_DOUBLE, 0, REQ_DENSPROF, comm_cart);
00199       free(result);
00200     }
00201     if (this_node == 0) {
00202       MPI_Recv(result, lblattice.grid[pdir]*node_grid[pdir], MPI_DOUBLE, newroot, REQ_DENSPROF, comm_cart, &status);
00203     }
00204   }
00205 
00206   if (this_node != 0) free(params);
00207 
00208 }
00209 
00210 #define REQ_VELPROF 701
00211 
00212 /** Calculate a velocity profile for the LB fluid. */   
00213 void lb_calc_velprof(double *result, int *params) {
00214 
00215   int index, dir[3], grid[3];
00216   int newroot=0, subrank, involved=0;
00217   double rho, j[3], *velprof;
00218   MPI_Comm slice_comm;
00219   MPI_Status status;
00220 
00221   if (this_node != 0) params = malloc(4*sizeof(int));
00222 
00223   MPI_Bcast(params, 4, MPI_INT, 0, comm_cart);
00224 
00225   int vcomp = params[0];
00226   int pdir  = params[1];
00227   int x1    = params[2];
00228   int x2    = params[3];
00229 
00230   dir[pdir] = 0;
00231   dir[(pdir+1)%3] = x1;
00232   dir[(pdir+2)%3] = x2;
00233 
00234   //fprintf(stderr,"%d: (%d,%d,%d)\n",this_node,dir[0],dir[1],dir[2]);
00235 
00236   newroot = map_lattice_to_node(&lblattice, dir, grid);
00237   map_node_array(this_node, node_pos);
00238 
00239   //fprintf(stderr,"%d: newroot=%d (%d,%d,%d)\n",this_node,newroot,grid[0],grid[1],grid[2]);
00240 
00241   if (    (grid[(pdir+1)%3] == node_pos[(pdir+1)%3])
00242        && (grid[(pdir+2)%3] == node_pos[(pdir+2)%3]) ) {
00243     involved = 1;
00244   }
00245 
00246   MPI_Comm_split(comm_cart, involved, this_node, &slice_comm);
00247   MPI_Comm_rank(slice_comm, &subrank);
00248 
00249   if (this_node == newroot) 
00250     result = realloc(result,box_l[pdir]/lblattice.agrid*sizeof(double));
00251 
00252   //fprintf(stderr,"%d (%d,%d): result=%p vcomp=%d pdir=%d x1=%d x2=%d involved=%d\n",this_node,subrank,newroot,result,vcomp,pdir,x1,x2,involved);
00253 
00254   if (involved) {
00255 
00256     velprof = malloc(lblattice.grid[pdir]*sizeof(double));
00257 
00258     //dir[(pdir+1)%3] += 1;
00259     //dir[(pdir+2)%3] += 1;
00260     for (dir[pdir]=1;dir[pdir]<=lblattice.grid[pdir];dir[pdir]++) {
00261       
00262       index = get_linear_index(dir[0],dir[1],dir[2],lblattice.halo_grid);
00263       lb_calc_local_fields(index, &rho, j, NULL);
00264       
00265       //fprintf(stderr,"%p %d %.12e %.12e %d\n",lbfluid[0],index,rho,j[0],vcomp);
00266 
00267       if (rho < ROUND_ERROR_PREC) {
00268         velprof[dir[pdir]-1] = 0.0;
00269       } else {
00270         //velprof[dir[pdir]-1] = local_j / (SQR(lbpar.agrid)*lbpar.tau);
00271         velprof[dir[pdir]-1] = j[vcomp]/rho * lblattice.agrid/lbpar.tau;
00272         //fprintf(stderr,"%f %f %f\n",velprof[dir[pdir]-1],local_j,local_rho);
00273       }
00274 
00275       //if (dir[pdir]==lblattice.grid[pdir]) {
00276       //        int i;
00277       //        fprintf(stderr,"(%d,%d,%d)\n",dir[0],dir[1],dir[2]);
00278       //        fprintf(stderr,"%d\n",lbfluid[index].boundary);
00279       //        for (i=0;i<lbmodel.n_veloc;i++) fprintf(stderr,"local_n[%p][%d]=%.12e\n",lbfluid[index].n,i,lbfluid[index].n[i]+lbmodel.coeff[i][0]*lbpar.rho);
00280       //        fprintf(stderr,"local_rho=%e\n",local_rho);
00281       //        fprintf(stderr,"local_j=%e\n",local_j);
00282       //}
00283 
00284     }
00285     
00286     MPI_Gather(velprof, lblattice.grid[pdir], MPI_DOUBLE, result, lblattice.grid[pdir], MPI_DOUBLE, newroot, slice_comm);
00287 
00288     free(velprof);
00289 
00290   } 
00291 
00292   MPI_Comm_free(&slice_comm);
00293 
00294   if (newroot != 0) {
00295     if (this_node == newroot) {
00296       MPI_Send(result, lblattice.grid[pdir]*node_grid[pdir], MPI_DOUBLE, 0, REQ_VELPROF, comm_cart);
00297       free(result);
00298     }
00299     if (this_node == 0) {
00300       //fprintf(stderr,"%d: I'm just here!\n",this_node);
00301       MPI_Recv(result, lblattice.grid[pdir]*node_grid[pdir], MPI_DOUBLE, newroot, REQ_VELPROF, comm_cart, &status);
00302       //fprintf(stderr,"%d: And now I'm here!\n",this_node);
00303     }
00304   }
00305 
00306   if (this_node !=0) free(params);
00307 
00308 }
00309 
00310 #endif /* LB */
00311