/** Personalized build a TGraphError starting from a TH1F */ TGraphErrors buildGEfromH_Personalized (const TH1D & histo) { TVectorF xV(histo.GetNbinsX()); TVectorF yV(histo.GetNbinsX()); TVectorF errxV(histo.GetNbinsX()); TVectorF erryV(histo.GetNbinsX()); for (int iBin = 0; iBin<histo.GetNbinsX(); iBin++){ xV[iBin] = histo.GetBinCenter(iBin); yV[iBin] = histo.GetBinContent(iBin); errxV[iBin] = 0; // histo.GetBinWidth(iBin); erryV[iBin] = histo.GetBinError(iBin); } TGraphErrors g (xV, yV, errxV, erryV) ; return g ; }
/* pore profile calculate the effective radius in thin slices, spaced by dz */ void calc_profile (struct pprofile *prf) { int i; real deltaZ; real Rmax=prf->Rmax; real zmin=prf->z1; real zmax=prf->z2; mesg(VERBOSE,"Calculating pore profile (%d z-slices)",prf->nz); mesg(INPUT,"pore profile: Rmax <%f> zmin <%f> zmax <%f> [nm]", Rmax,zmin,zmax); prf->r=grid2_alloc(prf->nz,2); deltaZ = (zmax - zmin)/(real)prf->nz; for(i=0;i<prf->nz;i++) { fprintf(stderr,"\rIntegrating slice %6d (z=%2.3fnm) [%5.1f%%] ", i,zmin+(i+0.5)*deltaZ,((real)i+1.0)*100/(real)prf->nz); prf->r[i][0]=zmin + (i+0.5)*deltaZ; prf->r[i][1]=sqrt( xV(vljshiftcyl, Rmax, zmin+i*deltaZ, zmin+(i+1)*deltaZ) / (PI*deltaZ) ); } fprintf(stderr,"\n"); return; }
void operator()( const Grid & grid, const unsigned dir, const bool begin, SurfaceMesh & surfaceMesh ) const { //! Sanity check of direction VERIFY_MSG( (dir < Grid::dim), "Input argument for direction wrong" ); //! Dimensions of the grid const MultiIndexType gridSizes = grid.gridSizes(); //! Multi-index component to compare with const int mIndexComp = ( begin == false ? 0 : gridSizes[dir]-1 ); //! Number of elements in the structured grid const std::size_t numElements = MultiIndex::length( gridSizes ); //! Number of elements on the requested surface const std::size_t numElementsOnSurface = numElements / gridSizes[ dir ]; //! Construct parametric geometry of the element const unsigned surfaceID = detail_::convertToSurfaceID<VolumeElement::shape>( dir, begin ); //! List of indices of the parameter space vertices which form the surface typename ParameterSurface::Surface parameterSurfaceIndices = ParameterSurface::surfaceTable[ surfaceID ]; //! Interpolation points of the surface shape function boost::array< typename SurfaceShapeFun::VecDim, SurfaceShapeFun::numFun> surfaceSupportPoints; SurfaceShapeFun::supportPoints( surfaceSupportPoints ); //! Vertices of the parameter volume boost::array< typename LinearVolumeFun::VecDim, LinearVolumeFun::numFun> volumeVertices; LinearVolumeFun::supportPoints( volumeVertices ); // --> Reorder for hiearchical ordering // Then, the object ParameterFaces< shape, dim-1> can be used and // ParamaterSurface discarded. //! Iterator to surface mesh elements typename SurfaceMesh::ElementPtrIter surfElemIter = surfaceMesh.elementsBegin(); //! Linear shape function on the surface simplex LinearSimplexFun linearSimplexFun; //! Hexahedra will have two triangles per face const unsigned numSurfElementsPerElement = detail_::NumSimplicesPerElementSurface<VolumeElement::shape>::value; //! Temporary storage of surface elements and nodes std::vector<SurfaceElement*> surfaceElements; surfaceElements.reserve( numElementsOnSurface * numSurfElementsPerElement ); std::vector<SurfaceNode*> surfaceNodes; //! node counter std::size_t nodeCtr = 0; //! Go through all elements for ( std::size_t e = 0; e < numElements; e ++ ) { //! Construct multi-index from linear counter const MultiIndexType eM = MultiIndex::wrap( e, gridSizes ); //! Check if on requested boundary surface const bool onBoundary = ( eM[ dir ] == mIndexComp ); //! If so, construct the surface element(s) if ( onBoundary ) { //! Get pointer to volume element VolumeElement * vep = grid.elementPtr( eM ); //! Go through elements on the surface of the volume element for ( unsigned se = 0; se < numSurfElementsPerElement; se ++ ) { //! Create new surface element SurfaceElement * surfElem = new SurfaceElement; //! Extract the surface simplex's vertices boost::array<unsigned, numSurfSimplexVertices> surfSimplex; detail_::ExtractSurfaceSimplex<VolumeElement::shape>()( parameterSurfaceIndices, se, surfSimplex ); //! Set volume element pointer surfElem -> setVolumeElementPointer( vep ); //! Access to surface elements geometry nodes typename SurfaceElement::NodePtrIter nodePtrIter = surfElem -> nodesBegin(); //! Go through the parameter points of the surface element typename SurfaceElement::ParamIter paramIter = surfElem -> parametricBegin(); typename SurfaceElement::ParamIter paramEnd = surfElem -> parametricEnd(); for ( unsigned p = 0; paramIter != paramEnd; ++paramIter, ++nodePtrIter, p++ ) { //! .. typename base::Vector<surfaceDim>::Type eta = surfaceSupportPoints[ p ]; typename LinearSimplexFun::FunArray phi; linearSimplexFun.evaluate( eta, phi ); typename base::Vector<volumeDim>::Type xi = base::constantVector<volumeDim>( 0. ); for ( unsigned s = 0; s < phi.size(); s ++ ) { xi += phi[s] * volumeVertices[ surfSimplex[s] ]; } *paramIter = xi; //! evaluate geometry at the parameter point const typename VolumeElement::Node::VecDim x = base::Geometry<VolumeElement>()( vep, xi ); //! convert to vector and pass to node std::vector<double> xV( x.size() ); for ( int d = 0; d < x.size(); d ++ ) xV[d] = x[d]; SurfaceNode * surfNode = new SurfaceNode; surfNode -> setX( xV.begin() ); surfNode -> setID( nodeCtr++ ); *nodePtrIter = surfNode; surfaceNodes.push_back( surfNode ); } // end loop over surface element's nodes //! Store element pointer surfaceElements.push_back( surfElem ); } // end loop over simplices per volume element } // end condition if volume element lies on requested bdry }// end loop over all volume elements surfaceMesh.allocate( surfaceNodes.size(), surfaceElements.size() ); std::copy( surfaceNodes.begin(), surfaceNodes.end(), surfaceMesh.nodesBegin() ); std::copy( surfaceElements.begin(), surfaceElements.end(), surfaceMesh.elementsBegin() ); return; }
/* volume of a domain */ real volume (struct potpars *pp, struct pdb_ATOM model[], struct domain *dom, struct pprofile *prf) { real vol, Rmax, zmin, zmax; real min; /* global (hopefully) minimum in the total potential */ int i,first,last; /* take all atoms of this and neighboring domains: "Take them out. All of them!" (Senator Palpartine aka Darth Sidious) */ first = (dom->prev) ? dom->prev->first_site : dom->first_site; last = (dom->next) ? dom->next->last_site : dom->last_site; pp->ncenters=last-first + 1; mesg(SUB1,"volume(): Using %d atoms (%d -> %d), centered on domain '%s'.", pp->ncenters,first,last,dom->description); Rmax = (prf->bSet) ? prf->Rmax : dom->rho1/10.0; zmin=(dom->z1 - dom->dz/2.0)/10.0; zmax=(dom->z2 + dom->dz/2.0)/10.0; /* setup the function to be integrated */ /* (1) find the minimum - requires a function in cartesian coordinates -> setup the centers in cartesian - use cartesian vlj() */ { Cartesian pos; pp->xyzcenters=grid2_alloc(pp->ncenters,3); for(i=0;i<pp->ncenters;i++) { pos = cyl2cart(model[i+first].cpos); pp->xyzcenters[i][XX]=pos.x/10.0; pp->xyzcenters[i][YY]=pos.y/10.0; pp->xyzcenters[i][ZZ]=pos.z/10.0; } init_vljcyl(pp); mesg(VERBOSE,"Potential: %s with ffgmx OW-CH4 interaction parameters at T=%g K", "Lennard-Jones 12-6 V_LJ(x,y,z)", pp->Temp); pp->min=find_min(vljvec,Rmax,zmin,zmax,NULL); mesg(VERBOSE,"Minimum: %f\n",pp->min); } /* (2) calculate the volume - this is better done in cylindrical coordinates --> setup again (and use cylindrical LJ) */ /* These cylindrical coordinates are buried in structures; I rather have them as simple arrays: AND Length has to be in nm (not Angstrom) because this is the length unit in the Lennard-Jones parameters (currently CH4-OW hardcoded) */ pp->centers=grid2_alloc(pp->ncenters,3); for(i=0;i<pp->ncenters;i++) { pp->centers[i][RAD]=model[i+first].cpos.rho/10.0; pp->centers[i][PHI]=model[i+first].cpos.phi; pp->centers[i][ZZZ]=model[i+first].cpos.z/10.0; } init_vljcyl(pp); /* now with the minimum found and with the LJ-centers in cylindrical coordinates! */ mesg(VERBOSE,"Potential: Shifted Lennard-Jones 12-6 V_LJ(r,phi,z) - %g kT " "with ffgmx OW-CH4 interaction parameters at T=%g K", pp->min, pp->Temp); init_gaussleg(pp->ngaussleg); mesg(VERBOSE,"Using %d-point Gauss-Legendre quadrature for the volume integrals.", pp->ngaussleg); if (prf->bPlot) plot_potential(vljcyl,Rmax,zmin,zmax,prf->nzplot); /* mesg(VERBOSE,"Potential: %s with ffgmx OW-CH4 interaction parameters", (prf->pot == vRljcyl) ? "WCA repulsive V_R,LJ(r)" : "Lennard-Jones 12-6 V_LJ(r)"); */ #ifdef TESTCASE { real vexact; /* test case: this should give the exact volume */ mesg(SUB1,"-------> Internal test of volume integration <-------"); vexact=PI*Rmax*Rmax*(zmax-zmin); mesg(SUB1,"VOLUME_TEST: R[nm] <%f> R_c[nm] <%f> L[nm] <%f> V=¶·R_c²·L[nm³] <%f>", dom->r1/10.0, Rmax, zmax-zmin, vexact); vol=cylint(cylconst, 0,Rmax, 0, 2*PI, zmin,zmax); mesg(SUB1,"VOLUME_TEST: f=1: Volume <%f> V_exact <%f>", vol,vexact); vol=cylint(cylcos, 0,Rmax, 0, 2*PI, zmin,zmax); vexact=0; mesg(SUB1,"VOLUME_TEST: f=cos(phi): Volume <%f> V_exact <%f>", vol,vexact); vol=cylint(cyl3, 0,Rmax, 0, 2*PI, 0,zmax-zmin); vexact=(1-exp(-Rmax))*PI*pow(zmax-zmin,3)/3.0; mesg(SUB1,"VOLUME_TEST: f=1/r exp(-r)*cos(phi)*cos(phi)*z: Volume <%f> V_exact <%f>", vol,vexact); vexact=1.0; /* PI*Rmax*Rmax*(zmax-zmin); */ vol = tdavg(Qvol,Zero, Rmax,zmin,zmax); mesg(SUB1,"VOLUME_TEST: <Qvol>, V(r)=0: Volume <%f> V_exact <%f>", vol,vexact); /* this analytical soln is alraedy specialised for FHG=6 */ vexact=(1.0-4.0*exp(-3.0))/(1-exp(-6.0*Rmax)*(1.0+6.0*Rmax)); vol = tdavg(Qvol,LinCheck, Rmax,zmin,zmax); mesg(SUB1,"VOLUME_TEST: <Qvol>, V(r)=6r: Volume <%f> V_exact <%f>", vol,vexact); /* correct one, f = 6, gives the same as above */ #define FHG 6.0 vexact= -(exp(FHG*(-0.5 + Rmax))* (-2.0 + 2.0*exp(FHG/2.) - FHG))/ (2.*(1.0 - exp(FHG*Rmax) + FHG*Rmax)); vol = tdavg(Qvol,LinCheck, Rmax,zmin,zmax); mesg(SUB1,"VOLUME_TEST: <Qvol>, V(r)=f/beta r nm^-1: Volume <%f> V_exact <%f>", vol,vexact); /* g(E) * exp(-bE) * f() f(r) = K1/2 r^2 (integral from Mathematica) */ vexact=2.0*PI*(zmax-zmin)* (K1*pow(Rmax,2) - (3.0*sqrt(2.0/PI)*sqrt(K1*pow(Rmax,2)))/ exp((K1*pow(Rmax,2))/2.) + (3.0 - K1*pow(Rmax,2))* erf(sqrt(K1*pow(Rmax,2))/sqrt(2)))/(2.*K1); vol = xV(harmonic,Rmax,zmin,zmax); mesg(SUB1,"VOLUME_TEST: xV: V(r)= k/2b r² nm^-1: Volume <%f> V_exact <%f>", vol,vexact); mesg(SUB1,"------> End of testcases <-------\n"); } #endif /* TESTCASE */ /* total volume */ /* simple & inefficient (two integrations): V = <Q> = Tr Qexp(-beta H) / Tr exp(-beta H) */ mesg(INPUT,"VOLUME_INPUT: R[nm] <%f> R_c[nm] <%f> L[nm] <%f> V=¶·R_c²·L[nm³] <%f>", dom->r1/10.0, Rmax, zmax-zmin, PI*Rmax*Rmax*(zmax-zmin)); mesg(INPUT,"VOLUME_PARAMETERS: Rmax[nm] <%f> z1 <%f> z2 <%f>",Rmax,zmin, zmax); /* accessible volume, Labbook II, p84 */ vol = xV(vljshiftcyl,Rmax,zmin,zmax); mesg(INPUT,"VOLUME_DATA: xV Volume[nm³] <%f> R*[nm] <%f>\n", vol,sqrt(vol/(PI*(zmax-zmin)))); /* normalised configurational volume, Labbok II, p79 (rubbish!) */ vol = Zsum(vljshiftcyl,Rmax,zmin,zmax); mesg(INPUT,"VOLUME_DATA: v1/Z Volume[nm³] <%f> R*[nm] <%f>\n", vol,sqrt(vol/(PI*(zmax-zmin)))); /* Thermodynamic average at fixed particle energy, Labbook II, p78 */ /* vol = tdavg(Qvol,prf->pp->u1, Rmax,zmin,zmax); */ /* mesg(INPUT,"VOLUME_DATA: <Qvol> Volume[nm³] <%f> R*[nm] <%f>\n", */ /* vol,sqrt(vol/(PI*(zmax-zmin)))); */ /* Pure configurational volume (unnormalised) */ /* vol = cylint(Z_V, 0,Rmax, 0,2*PI, zmin,zmax); */ /* mesg(INPUT,"VOLUME_DATA: v1 Volume[nm³] <%f> R*[nm] <%f>\n", */ /* vol,sqrt(vol/(PI*(zmax-zmin)))); */ if (prf->bSet) calc_profile(prf); free_gaussleg(); free(pp->centers); free(pp->xyzcenters); return vol; }