void StokesContinuityResid<EvalT, Traits>:: evaluateFields(typename Traits::EvalData workset) { typedef Intrepid::FunctionSpaceTools FST; for (std::size_t cell=0; cell < workset.numCells; ++cell) { for (std::size_t qp=0; qp < numQPs; ++qp) { divergence(cell,qp) = 0.0; for (std::size_t i=0; i < numDims; ++i) { divergence(cell,qp) += VGrad(cell,qp,i,i); } } } FST::integrate<ScalarT>(CResidual, divergence, wBF, Intrepid::COMP_CPP, false); // "false" overwrites contractDataFieldScalar<ScalarT>(CResidual, divergence, wBF,false); // "false" overwrites if (havePSPG) { for (std::size_t cell=0; cell < workset.numCells; ++cell) { for (std::size_t node=0; node < numNodes; ++node) { for (std::size_t qp=0; qp < numQPs; ++qp) { for (std::size_t j=0; j < numDims; ++j) { CResidual(cell,node) += TauM(cell,qp)*Rm(cell,qp,j)*wGradBF(cell,node,qp,j); } } } } } }
void lpaggreg::DQualities::computeQualities() { if (values==0){ return; } unsigned hsize=metaData.getHsize(); unsigned osize=values->getOsize(); unsigned vsize=values->getVsize(); qualities=dqualities(new vector<shared_ptr<UpperTriangularMatrix<shared_ptr<lpaggreg::Quality> > > >(hsize)); for (int h = 0; h < hsize; h++){ (*qualities)[h]=oqualities(new UpperTriangularMatrix<shared_ptr<lpaggreg::Quality> >(osize)); } for (int k=0; k < vsize; k++){ int i=0; int h; vector<UpperTriangularMatrix<lp_quality_type> > sum; vector<UpperTriangularMatrix<lp_quality_type> > info; for (h=0; h<hsize; h++){ sum.push_back(UpperTriangularMatrix<lp_quality_type>(osize)); info.push_back(UpperTriangularMatrix<lp_quality_type>(osize)); } for (h = (metaData.getPath())[i]; i < metaData.getLeaveSize(); h = (metaData.getPath())[++i]){ for (int i = osize-1; i >=0; i--) { (sum[h])(i,i,(*values)[h][k][i]); (info[h])(i,i,entropyReduction((*values)[h][k][i], 0)); (sum[(metaData.getParents())[h]])(i,i,(sum[(metaData.getParents())[h]])(i,i)+(sum[h])(i,i)); (info[(metaData.getParents())[h]])(i,i,(info[(metaData.getParents())[h]])(i,i)+(info[h])(i,i)); for (int j = i+1; j < osize; j++) { (sum[h])(i,j,(sum[h])(i+1,j)+(sum[h])(i,i)); (info[h])(i,j,(info[h])(i+1,j)+(info[h])(i,i)); (*(*qualities)[h])(i,j)->addToGain(entropyReduction((sum[h])(i,j), (info[h])(i,j))); (*(*qualities)[h])(i,j)->addToLoss(divergence(j-i+1, (sum[h])(i,j), (info[h])(i,j))); (sum[(metaData.getParents())[h]])(i,j,(sum[(metaData.getParents())[h]])(i,j)+(sum[h])(i,j)); (info[(metaData.getParents())[h]])(i,j,(info[(metaData.getParents())[h]])(i,j)+(info[h])(i,j)); } } } for (h = (metaData.getPath())[i]; i < hsize-1; h = (metaData.getPath())[++i]){ for (int i = osize-1; i >=0; i--) { for (int j = i; j < osize; j++) { (*(*qualities)[h])(i,j)->addToGain(entropyReduction((sum[h])(i,j), (info[h])(i,j))); (*(*qualities)[h])(i,j)->addToLoss(divergence((j-i+1)*(metaData.getSize())[h], (sum[h])(i,j), (info[h])(i,j))); (sum[(metaData.getParents())[h]])(i,j,(sum[(metaData.getParents())[h]])(i,j)+(sum[h])(i,j)); (info[(metaData.getParents())[h]])(i,j,(info[(metaData.getParents())[h]])(i,j)+(info[h])(i,j)); } } } for (int i = osize-1; i >=0; i--) { for (int j = i; j < osize; j++) { (*(*qualities)[h])(i,j)->addToGain(entropyReduction((sum[h])(i,j), (info[h])(i,j))); (*(*qualities)[h])(i,j)->addToLoss(divergence((j-i+1)*(metaData.getSize())[h], (sum[h])(i,j), (info[h])(i,j))); } } } }
void FluidSystem::project(VelocityField &velocity) const { Grid pressure(fullDim); Grid divergence(fullDim); div(divergence, velocity, dim); divergence = -1 * divergence; setContinuityBoundaries(divergence, dim); setContinuityBoundaries(pressure, dim); linearSolve(pressure, divergence, 1, 6, dim, std::bind(&setContinuityBoundaries, std::placeholders::_1, dim)); VelocityField gradient(fullStaggeredDim); gradient.clear(); grad(gradient, pressure, dim); velocity -= gradient; if (horizontalNeumann) { setHorizontalNeumannBoundaries(velocity[0], dim); } else { setContinuityBoundaries(velocity[0], dim); } if (verticalNeumann) { setVerticalNeumannBoundaries(velocity[1], dim); } else { setContinuityBoundaries(velocity[1], dim); } setDepthNeumannBoundaries(velocity[2], dim); }
/* Function for setting up and running the fluid simulation kernels */ void solveFluid(struct Configuration* config) { // Jacobi settings float alpha = -1.0f; // Should use alpha -1 here, but this gives nicer results //float alpha = -(1.0f/invhalfgridscale); float rbeta = 0.25; int iterations = 100; // grid scaling. this is currently not used if(rank == 0){ float gridscale = 1.0f; float invgridscale = 1.0f/gridscale; float invhalfgridscale = 0.5f/gridscale; // Timstep value float timestep = 0.05f; // Emitter settings float amount = 2.0f; float radius = 0.5*config->N/10.0f; float emitterposx = config->N/2; float emitterposy = config->N/3; // buoyancy settings float bdiry = 1.0f; float bdirx = 0.0f; float bstrength = 0.1f; // advection settings float veldamp = 0.01f; // Velocity advection float *tmp = config->velx0; config->velx0 = config->velx; config->velx = tmp; float *tmp1 = config->vely0; config->vely0 = config->vely; config->vely = tmp1; advect(config->N, config->velx, config->velx0, config->velx0, config->vely0, timestep, veldamp, 1); advect(config->N, config->vely, config->vely0, config->velx0, config->vely0, timestep, veldamp, 2); // Density advection float *tmp2 = config->dens0; config->dens0 = config->dens; config->dens = tmp2; advect(config->N, config->dens, config->dens0, config->velx, config->vely, timestep, 0.0f, 0); // Add density and density buoyancy addDensity(config->N, config->dens, timestep, emitterposx, emitterposy, radius, amount); addDensityBuoyancy(config->N, config->velx, config->vely, config->dens, bdirx, bdiry, bstrength, timestep); // Divergence calculation divergence(config->N, config->velx, config->vely, config->div); // Pressure jacobi calculation. First set pres array to zero as initial guess setMem(config->N, config->pres); } jacobi(iterations); if(rank == 0){ // Calculate projection projection(config->N, config->velx, config->vely, config->pres); } }
int main(int argc, char **argv) { int NX,NY,NZ; MPI_Init (&argc, &argv); int nprocs, procid; MPI_Comm_rank(MPI_COMM_WORLD, &procid); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /* Parsing Inputs */ if(argc==1){ NX=256;NY=256;NZ=256; } else{ NX=atoi(argv[1]); NY=atoi(argv[2]); NZ=atoi(argv[3]); } int N[3]={NX,NY,NZ}; int nthreads=1; grad(N,nthreads); laplace(N,nthreads); divergence(N,nthreads); biharmonic(N,nthreads); MPI_Finalize(); return 0; } // end main
void divergence(EBCellFAB& a_divF, const EBFluxFAB& a_flux, const EBISBox& a_ebisBox, const Box& a_box, const RealVect& a_fluxVal, const Real& a_dx) { IntVectSet ivs(a_box); for (VoFIterator vofit(ivs, a_ebisBox.getEBGraph()); vofit.ok(); ++vofit) { Real divval = divergence(a_flux, a_fluxVal, a_ebisBox, vofit(), a_dx); a_divF(vofit(), 0) = divval; } }
// w component of velocity source term double eval_q_w(double x, double y, double z) { typedef DualNumber<Scalar, NumberArray<NDIM, Scalar> > FirstDerivType; typedef DualNumber<FirstDerivType, NumberArray<NDIM, FirstDerivType> > SecondDerivType; typedef DualNumber<SecondDerivType, NumberArray<NDIM, SecondDerivType> > ThirdDerivType; typedef ThirdDerivType ADScalar; // Treat velocity as a vector NumberArray<NDIM, ADScalar> U; ADScalar x = ADScalar(x1,NumberArrayUnitVector<NDIM, 0, Scalar>::value()); ADScalar y = ADScalar(y1,NumberArrayUnitVector<NDIM, 1, Scalar>::value()); ADScalar z = ADScalar(z1,NumberArrayUnitVector<NDIM, 2, Scalar>::value()); // Arbitrary manufactured solutions U[0] = a * helper_f(x) + helper_g(y).derivatives()[1] + helper_h(z).derivatives()[2]; U[1] = b * helper_f(x).derivatives()[0] + helper_g(y) + helper_h(z).derivatives()[2]; U[2] = c * helper_f(x).derivatives()[0] + helper_g(y).derivatives()[1] + helper_h(z); ADScalar P = d * helper_f(x) + helper_gt(y) + helper_h(z); // NS equation residuals NumberArray<NDIM, Scalar> Q_u = raw_value( // convective term divergence(U.outerproduct(U)) // pressure - P.derivatives() // dissipation + nu * divergence(gradient(U))); return Q_u[2]; }
void PCM::propagateCavityGradients(const ScalarField& A_shape, ScalarField& A_nCavity, ScalarFieldTilde& A_rhoExplicitTilde, bool electricOnly) const { if(fsp.pcmVariant == PCM_SGA13) { //Propagate gradient w.r.t expanded cavities to nCavity: ((PCM*)this)->A_nc = 0; const ScalarField* A_shapeEx[2] = { &A_shape, &Acavity_shapeVdw }; for(int i=0; i<2; i++) { //First compute derivative w.r.t expanded electron density: ScalarField A_nCavityEx; ShapeFunction::propagateGradient(nCavityEx[i], *(A_shapeEx[i]), A_nCavityEx, fsp.nc, fsp.sigma); ((PCM*)this)->A_nc += (-1./fsp.nc) * integral(A_nCavityEx*nCavityEx[i]); //then propagate to original electron density: ScalarField nCavityExUnused; //unused return value below ShapeFunction::expandDensity(wExpand[i], Rex[i], nCavity, nCavityExUnused, &A_nCavityEx, &A_nCavity); } } else if(fsp.pcmVariant == PCM_CANDLE) { ScalarField A_nCavityEx; ScalarFieldTilde A_phiExt; double A_pCavity=0.; ShapeFunction::propagateGradient(nCavityEx[0], coulomb(Sf[0]*rhoExplicitTilde), I(wExpand[0]*J(A_shape)) + Acavity_shapeVdw, A_nCavityEx, A_phiExt, A_pCavity, fsp.nc, fsp.sigma, fsp.pCavity); A_nCavity += fsp.Ztot * I(Sf[0] * J(A_nCavityEx)); if(!electricOnly) A_rhoExplicitTilde += coulomb(Sf[0]*A_phiExt); ((PCM*)this)->A_nc = (-1./fsp.nc) * integral(A_nCavityEx*nCavityEx[0]); ((PCM*)this)->A_eta_wDiel = integral(A_shape * I(wExpand[1]*J(shapeVdw))); ((PCM*)this)->A_pCavity = A_pCavity; } else if(isPCM_SCCS(fsp.pcmVariant)) { //Electrostatic and volumetric combinations via shape: ShapeFunctionSCCS::propagateGradient(nCavity, A_shape - fsp.cavityPressure, A_nCavity, fsp.rhoMin, fsp.rhoMax, epsBulk); //Add surface contributions: ScalarField shapePlus, shapeMinus; ShapeFunctionSCCS::compute(nCavity+(0.5*fsp.rhoDelta), shapePlus, fsp.rhoMin, fsp.rhoMax, epsBulk); ShapeFunctionSCCS::compute(nCavity-(0.5*fsp.rhoDelta), shapeMinus, fsp.rhoMin, fsp.rhoMax, epsBulk); VectorField Dn = gradient(nCavity); ScalarField DnLength = sqrt(lengthSquared(Dn)); ScalarField A_shapeMinus = (fsp.cavityTension/fsp.rhoDelta) * DnLength; ScalarField A_DnLength = (fsp.cavityTension/fsp.rhoDelta) * (shapeMinus - shapePlus); A_nCavity -= divergence(Dn * (inv(DnLength) * A_DnLength)); ShapeFunctionSCCS::propagateGradient(nCavity+(0.5*fsp.rhoDelta), -A_shapeMinus, A_nCavity, fsp.rhoMin, fsp.rhoMax, epsBulk); ShapeFunctionSCCS::propagateGradient(nCavity-(0.5*fsp.rhoDelta), A_shapeMinus, A_nCavity, fsp.rhoMin, fsp.rhoMax, epsBulk); } else //All gradients are w.r.t the same shape function - propagate them to nCavity (which is defined as a density product for SaLSA) { ShapeFunction::propagateGradient(nCavity, A_shape + Acavity_shape, A_nCavity, fsp.nc, fsp.sigma); ((PCM*)this)->A_nc = (-1./fsp.nc) * integral(A_nCavity*nCavity); } }
/* * This routine is in charge of the Temperature equation. Virtually all * of the terms can be enabled or disabled by parameters read in through the * configuration file. This equation has the form: * * dT/dt = div(uT) + w hat z + del^2 T */ void calcTemp() { complex PRECISION * forces = T->force1; if(tDiff) { laplacian(T->spectral, forces, 0, 1.0); } else { memset(forces, 0, spectralCount * sizeof(complex PRECISION)); } if(tempAdvection) { //advect the background profile (as long as it is enabled) if(tempBackground) { plusEq(forces, u->vec->z->spectral); } //advect the perturbations p_vector flux = temp1; multiply(u->vec->x->spatial, T->spatial, flux->x->spatial); multiply(u->vec->y->spatial, T->spatial, flux->y->spatial); multiply(u->vec->z->spatial, T->spatial, flux->z->spatial); fftForward(flux->x); fftForward(flux->y); fftForward(flux->z); p_field advect = temp2->x; divergence(flux, advect); minusEq(forces, advect->spectral); } //Apply hyper diffusion to the boundaries if(sanitize) { killBoundaries(T->spatial, forces, 1, 100); } }
void NS(void) { //surface_tension_geo(); //surface_tension(); // if(iteration%ioutput==0) // { // print_2D_array("GeoSurfx.dat",iteration,"GeoSurfx",surfx[0],l-1,m-1,dx); // print_2D_array("GeoSurfy.dat",iteration,"GeoSurfy",surfy[0],l-1,m-1,dx); // } /* surface_tension(); if(iteration%ioutput==0) { print_2D_array("FreeSurfx.dat",iteration,"FreeSurfx",surfx[0],l-1,m-1,dx); print_2D_array("FreeSurfy.dat",iteration,"FreeSurfy",surfy[0],l-1,m-1,dx); } */ momentum(); divergence(); // print_2D_array("surfx",iteration,"surfx",surfx[0],l-1,m-1,dx); // print_2D_array("surfy",iteration,"surfy",surfy[0],l-1,m-1,dx); // print_2D_array("sigma",iteration,"sigma",sigma[0],l+1,m+1,dx); }
int main (int argc, char** argv) { int i; int iterations = 100; // prepare grids // declare_grids --> float * u_0_0_out; float * u_0_0; float * ux_1_0; float * uy_2_0; float * uz_3_0; float * u_0_0_out_cpu; float * u_0_0_cpu; float * ux_1_0_cpu; float * uy_2_0_cpu; float * uz_3_0_cpu; if ((argc<4)) { printf("Wrong number of parameters. Syntax:\n%s <x_max> <y_max> <z_max> <# of iterations>\n", argv[0]); exit(-1); } int x_max = atoi(argv[1]); int y_max = atoi(argv[2]); int z_max = atoi(argv[3]); if(argc==5) iterations = atoi(argv[4]); // <-- // allocate_grids --> u_0_0=((float * )malloc((((x_max*y_max)*z_max)*sizeof (float)))); ux_1_0=((float * )malloc(((((x_max+2)*y_max)*z_max)*sizeof (float)))); uy_2_0=((float * )malloc((((x_max*(y_max+2))*z_max)*sizeof (float)))); uz_3_0=((float * )malloc((((x_max*y_max)*(z_max+2))*sizeof (float)))); u_0_0_cpu=((float * )malloc((((x_max*y_max)*z_max)*sizeof (float)))); ux_1_0_cpu=((float * )malloc(((((x_max+2)*y_max)*z_max)*sizeof (float)))); uy_2_0_cpu=((float * )malloc((((x_max*(y_max+2))*z_max)*sizeof (float)))); uz_3_0_cpu=((float * )malloc((((x_max*y_max)*(z_max+2))*sizeof (float)))); // <-- // initialize // initialize_grids --> initialize(u_0_0, ux_1_0, uy_2_0, uz_3_0, 0.1, 0.2, 0.30000000000000004, x_max, y_max, z_max); initialize(u_0_0_cpu, ux_1_0_cpu, uy_2_0_cpu, uz_3_0_cpu, 0.1, 0.2, 0.30000000000000004, x_max, y_max, z_max); // <-- long nFlopsPerStencil = 8; long nGridPointsCount = iterations * ((x_max*y_max)*z_max); long nBytesTransferred = iterations * (((((((x_max+2)*y_max)*z_max)*sizeof (float))+(((x_max*(y_max+2))*z_max)*sizeof (float)))+(((x_max*y_max)*(z_max+2))*sizeof (float)))+(((x_max*y_max)*z_max)*sizeof (float))); /* *************************** PGI GPU-acc benchmark ********************* */ // warm up { // compute_stencil --> divergence(( & u_0_0_out), u_0_0, ux_1_0, uy_2_0, uz_3_0, 0.4, 0.5, 0.6, x_max, y_max, z_max,iterations); // <-- } // run the benchmark tic (); { // compute_stencil --> divergence(( & u_0_0_out), u_0_0, ux_1_0, uy_2_0, uz_3_0, 0.7, 0.7999999999999999, 0.8999999999999999, x_max, y_max, z_max,iterations); // <-- } toc (nFlopsPerStencil, nGridPointsCount, nBytesTransferred); /* *************************** ******************** ********************* */ /* *************************** Naive CPU Comparison ********************* */ // warm up cpu comparison { // compute_stencil --> divergence(( & u_0_0_out_cpu), u_0_0_cpu, ux_1_0_cpu, uy_2_0_cpu, uz_3_0_cpu, 0.4, 0.5, 0.6, x_max, y_max, z_max,iterations); // <-- } // run the benchmark tic (); { // compute_stencil --> divergence_cpu(( & u_0_0_out_cpu), u_0_0_cpu, ux_1_0_cpu, uy_2_0_cpu, uz_3_0_cpu, 0.7, 0.7999999999999999, 0.8999999999999999, x_max, y_max, z_max,iterations); // <-- } toc (nFlopsPerStencil, nGridPointsCount, nBytesTransferred); // checking "correctness" (assuming cpu version is correct) int error_count=0; int halo = 0; int x,y,z; for(y=0;y<x_max;y++) { for(x=0;x<x_max;x++) { for(z=0;z<y_max;z++) { i = x + (x_max+halo)*y + (x_max+halo)*(y_max+halo)*z; if(fabs(u_0_0_out[i] - u_0_0_out_cpu[i])>0.001) { error_count++; printf("%dth error encountered at u[%d]: |%f-%f|=%5.16f\n",error_count,i,u_0_0_out[i],u_0_0_out_cpu[i],fabs(u_0_0_out[i] - u_0_0_out_cpu[i])); if(error_count>30) { printf("too many errors\n"); printf("print some solutions\n"); for(x=0;x<100;x++) { printf("u_pgi[%d]=%2.2f ?? u_cpu[%d]=%2.2f\n",x,u_0_0_out[x],x,u_0_0_out_cpu[x]); } exit(1); } } } } } if(error_count==0) { printf("Error Check Successful. No errors encountered.\n"); } // free memory // deallocate_grids --> free(u_0_0); free(ux_1_0); free(uy_2_0); free(uz_3_0); // <-- return EXIT_SUCCESS; }
//Source term depending on cell void sources(struct CSRMat *Mat, struct RHS *Rhs) { int icell, ivar, idir; double *CelldblPnt, *phi, *dep, Src[nvar]; double tau[ndir][ndir], div, CmuOm; int i, j, k; double beta, Sij[ndir][ndir], Omij[ndir][ndir], xiw, fb; double SAa, SAb, SAc; for (icell=0;icell<ncell;icell++) { phi = setvar(icell); dep = setdep(icell); CelldblPnt = setdblcell(icell); memset(Src, 0.0, nvar * sizeof(double)); // Momentum Sources ---------------------------------------------------- if (eos != ICOUPLED) { for (idir=0;idir<ndir;idir++) Src[Uvar+idir] = - dep[PGrd+idir]; } // Turbulence production -------------- if (Kvar!=-1) { for (idir=0;idir<ndir;idir++) Src[Uvar+idir]-= 2.0 / 3.0 * dep[Rdep] * dep[KGrd+idir]; //Src[Uvar+idir]-= 2.0 / 3.0 * dep[MTdep] * divergence( dep); stress( phi, dep, tau); Src[Kvar] = prodk( dep, tau); } // turbulence Sources -------------------------------------------------- switch (turb) { // Spalart Allmaras ---------------- case SA: // NASA ################################# /*SAa = cb1 * ( 1.0 - ft2( phi, dep)) * Shat( phi, dep) * phi[MTvar]; SAb = ( cw1 * fw( phi, dep) - cb1 / (kappa * kappa) * ft2( phi, dep)) * \ ( phi[MTvar] * phi[MTvar]) / ( dep[Ddep] * dep[Ddep]); SAc = cb2 / sigma * scalarp( ndir, &dep[MTGrd], &dep[MTGrd]);*/ // Deck ################################# SAa = cb1 * Shat( phi, dep) * phi[MTvar]; SAb = cw1 * fw( phi, dep) * \ ( phi[MTvar] * phi[MTvar]) / ( dep[Ddep] * dep[Ddep]); SAc = 0.0; //cb2 / sigma * scalarp( ndir, &dep[MTGrd], &dep[MTGrd]); Src[MTvar] = dep[Rdep] * (SAa - SAb + SAc); break; // Kw Wilcox 2006 ------------------ case KW06: strain( dep, Sij); rotation( dep, Omij); div = divergence( dep); for (i=0;i<ndir;i++) Sij[i][i] -= 0.5 * div; xiw = 0.0; for (i=0;i<ndir;i++) { for (j=0;j<ndir;j++) { for (k=0;k<ndir;k++) xiw += Omij[i][j] * Omij[j][k] * Sij[k][i]; }} CmuOm = Cmu * phi[OMvar]; xiw = fabs( xiw / (CmuOm * CmuOm * CmuOm)); fb = ( 1.0 + 85.0*xiw) / ( 1.0 + 100.0*xiw); beta = beta0 * fb; Src[Kvar] -= Cmu * dep[Rdep] * phi[Kvar] * phi[OMvar]; Src[OMvar] = alpha * phi[OMvar] / phi[Kvar] * prodk( dep, tau); Src[OMvar]-= beta * dep[Rdep] * phi[OMvar] * phi[OMvar]; if ( scalarp( ndir, &dep[KGrd], &dep[OMGrd]) > 0.0) Src[OMvar]+= 0.125 * dep[Rdep] / phi[OMvar] * \ scalarp( ndir, &dep[KGrd], &dep[OMGrd]); break; // Menter KwSST -------------------- case KWSST: strain( dep, Sij); rotation( dep, Omij); alpha = blend( F1(phi,dep), gamma1, gamma2); beta = blend( F1(phi,dep), beta1, beta2); Src[Kvar] -= Cmu * dep[Rdep] * phi[Kvar] * phi[OMvar]; Src[OMvar] = alpha * dep[Rdep] / dep[MTdep] * prodk( dep, tau); Src[OMvar]-= beta * dep[Rdep] * phi[OMvar] * phi[OMvar]; Src[OMvar]+= 2.0 * (1.0-F1(phi,dep)) * sigw2 * dep[Rdep] / phi[OMvar] * \ scalarp( ndir, &dep[KGrd], &dep[OMGrd]); break; } getrhs( Rhs, icell, CelldblPnt[CellVol], Src); } }
double FluidMixture::operator()(const ScalarFieldArray& indep, ScalarFieldArray& Phi_indep, Outputs outputs) const { static StopWatch watch("FluidMixture::operator()"); watch.start(); //logPrintf("indep.size: %d nIndep: %d\n",indep.size(),nIndep); myassert(indep.size()==get_nIndep()); //---------- Compute site densities from the independent variables --------- ScalarFieldTildeArray Ntilde(nDensities); //site densities (in reciprocal space) std::vector< vector3<> > P0(component.size()); //polarization densities G=0 for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; ScalarFieldArray N(c.molecule.sites.size()); c.idealGas->getDensities(&indep[c.offsetIndep], &N[0], P0[ic]); for(unsigned i=0; i<c.molecule.sites.size(); i++) { //Replace negative densities with 0: double Nmin, Nmax; callPref(eblas_capMinMax)(gInfo.nr, N[i]->dataPref(), Nmin, Nmax, 0.); //store site densities in fourier space Ntilde[c.offsetDensity+i] = J(N[i]); N[i] = 0; //Really skimp on memory! } } //----------- Handle density constraints ------------ std::vector<double> Nscale(component.size(), 1.0); //density scale factor that satisfies the constraint std::vector<double> Ntot_c; //vector of total number of molecules for each component std::vector<double> Nscale_Qfixed(component.size(), 0.); //derivative of Nscale w.r.t the fixed charge std::vector<std::vector<double> > Nscale_N0(component.size(), std::vector<double>(component.size(),0.0)); //jacobian of Nscale w.r.t the uncorrected molecule counts std::vector<string> names; //list of molecule names //Find fixed N and charged species: double Qfixed = 0.0; if(rhoExternal) Qfixed += integral(rhoExternal); std::vector<std::pair<double,double> > N0Q; for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; double Qmolecule = c.molecule.getCharge(); if(c.Nnorm>0 || Qmolecule) { double N0 = integral(Ntilde[c.offsetDensity])/c.molecule.sites[0]->positions.size(); if(c.Nnorm>0) { Nscale[ic] = c.Nnorm/N0; Nscale_N0[ic][ic] = -c.Nnorm/pow(N0,2); Qfixed += Qmolecule*c.Nnorm; } else { N0Q.push_back(std::make_pair(N0, Qmolecule)); names.push_back(c.molecule.name); } } } //Find the betaV (see Qtot()) that makes the unit cell neutral if(N0Q.size()==0) { if(fabs(Qfixed)>fabs(Qtol)) die("Unit cell has a fixed net charge %le," "and there are no free charged species to neutralize it.\n", Qfixed); } else { double Qprime, Qcell, betaV=0.0; if(Qfixed+Qtot(-HUGE_VAL,Qprime,N0Q)<0) die("Unit cell will always have a net negative charge (no free positive charges).\n") if(Qfixed+Qtot(+HUGE_VAL,Qprime,N0Q)>0) die("Unit cell will always have a net positive charge (no free negative charges).\n") for(int iter=0; iter<10; iter++) //while(1) { Qcell = Qfixed+Qtot(betaV,Qprime,N0Q,&names,&gInfo,verboseLog); if(verboseLog) logPrintf("betaV = %le, Qcell = %le, Qprime = %le\n", betaV, Qcell, Qprime); if(fabs(Qcell)<fabs(Qtol)) break; if(std::isnan(Qcell)) { betaV=0.0; break;} betaV -= Qcell/Qprime; //Newton-Raphson update } for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& ci = *component[ic]; double Qi = ci.molecule.getCharge(); if(Qi && ci.Nnorm<=0) { Nscale[ic] = exp(-Qi*betaV); Nscale_Qfixed[ic] = exp(-Qi*betaV) * Qi / Qprime; for(unsigned jc=0; jc<component.size(); jc++) { const FluidComponent& cj = *component[jc]; double Qj = cj.molecule.getCharge(); if(Qj && cj.Nnorm<=0) Nscale_N0[ic][jc] += Qi*Qj*exp(-(Qi+Qj)*betaV)/Qprime; } } } } std::vector<double> Phi_Nscale(component.size(), 0.0); //accumulate explicit derivatives w.r.t Nscale here //Apply the scale factors to the site densities for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; for(unsigned i=0; i<c.molecule.sites.size(); i++) Ntilde[c.offsetDensity+i] *= Nscale[ic]; P0[ic] *= Nscale[ic]; Ntot_c.push_back(integral(Ntilde[c.offsetDensity])); } EnergyComponents Phi; //the grand free energy (with component information) ScalarFieldTildeArray Phi_Ntilde(nDensities); //gradients (functional derivative) w.r.t reciprocal space site densities nullToZero(Phi_Ntilde,gInfo); std::vector< vector3<> > Phi_P0(component.size()); //functional derivative w.r.t polarization density G=0 VectorFieldTilde Phi_epsMF; //functional derivative w.r.t mean field electric field //G=0 fix for mismatch in fluid-fluid vs. fluid-electron charge kernels //We do this AFTER we have applied the appropriate scale factors if( N0Q.size() && (!useMFKernel)) //if we have charged species in our fluid, and are using mismatched charge kernels { for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; for(unsigned i=0; i<c.molecule.sites.size(); i++) { const Molecule::Site& s = *(c.molecule.sites[i]); Phi["Gzero"] += Qfixed*(Ntot_c[ic]/gInfo.detR-c.idealGas->Nbulk)*s.positions.size()*s.deltaS; Phi_Ntilde[c.offsetDensity+i]->data()[0] += (1.0/gInfo.dV) * (Qfixed*s.deltaS); } } } //--------- Compute the (scaled) mean field coulomb interaction -------- { ScalarFieldTilde rho; //total charge density ScalarFieldTilde rhoMF; //effective charge density for mean-field term bool needRho = rhoExternal || outputs.Phi_rhoExternal; VectorFieldTilde epsMF = polarizable ? J(VectorField(&indep[nIndepIdgas])) : 0; //mean field electric field vector3<> P0tot; for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; for(unsigned i=0; i<c.molecule.sites.size(); i++) { const Molecule::Site& s = *(c.molecule.sites[i]); if(s.chargeKernel) { if(needRho) rho += s.chargeKernel * Ntilde[c.offsetDensity+i]; rhoMF += s.chargeKernel(0) * (c.molecule.mfKernel * Ntilde[c.offsetDensity+i]); } //Polarization contributions: if(polarizable && s.polKernel) { #define Polarization_Compute_Pi_Ni \ VectorField Pi = (Cpol*s.alpha) * I(c.molecule.mfKernel*epsMF - (rhoExternal ? gradient(s.polKernel*coulomb(rhoExternal)) : 0)); \ ScalarField Ni = I(Ntilde[c.offsetDensity+i]); Polarization_Compute_Pi_Ni ScalarField Phi_Ni = (0.5/(Cpol*s.alpha))*lengthSquared(Pi); Phi["Apol"] += gInfo.dV * dot(Ni, Phi_Ni); //Derivative contribution to site densities: Phi_Ntilde[c.offsetDensity+i] += Idag(Phi_Ni); Phi_Ni=0; //Update contributions to bound charge: VectorFieldTilde NPtilde = J(Ni * Pi); Pi=0; Ni=0; ScalarFieldTilde divNPbar; if(needRho) rho -= s.polKernel*divergence(NPtilde); VectorFieldTilde NPbarMF = c.molecule.mfKernel*NPtilde; NPtilde=0; rhoMF -= divergence(NPbarMF); Phi_epsMF += gInfo.nr * NPbarMF; P0tot += getGzero(NPbarMF); } } P0tot += P0[ic]; } if(rhoMF) { //External charge interaction: ScalarFieldTilde Phi_rho; ScalarFieldTilde Phi_rhoMF; if(needRho) { if(rhoExternal) { ScalarFieldTilde OdExternal = O(coulomb(rhoExternal)); if (!useMFKernel) { Phi["ExtCoulomb"] += dot(rho, OdExternal); Phi_rho += OdExternal; } if (useMFKernel) { Phi["ExtCoulomb"] += dot(rhoMF, OdExternal); Phi_rhoMF += OdExternal; } } if(outputs.Phi_rhoExternal) { if (!useMFKernel) *outputs.Phi_rhoExternal = coulomb(rho); if (useMFKernel) *outputs.Phi_rhoExternal = coulomb(rhoMF); } } //Mean field contributions: { ScalarFieldTilde OdMF = O(coulomb(rhoMF)); //mean-field electrostatic potential Phi["Coulomb"] += 0.5*dot(rhoMF, OdMF); Phi_rhoMF += OdMF; } //Polarization density interactions: if(outputs.electricP) *outputs.electricP = P0tot * gInfo.detR; //--- corrections for net dipole in cell: vector3<> Phi_P0tot = (4*M_PI*gInfo.detR) * P0tot; Phi["PsqCell"] += 0.5 * dot(Phi_P0tot, P0tot); //--- external electric field interactions: Phi["ExtCoulomb"] -= gInfo.detR * dot(Eexternal, P0tot); Phi_P0tot -= gInfo.detR * Eexternal; //Propagate gradients: for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; for(unsigned i=0; i<c.molecule.sites.size(); i++) { const Molecule::Site& s = *(c.molecule.sites[i]); if(s.chargeKernel) { if(Phi_rho) Phi_Ntilde[c.offsetDensity+i] += (1./gInfo.dV) * (s.chargeKernel * Phi_rho); Phi_Ntilde[c.offsetDensity+i] += (s.chargeKernel(0)/gInfo.dV) * (c.molecule.mfKernel * Phi_rhoMF); } //Polarization contributions: if(polarizable && s.polKernel) { VectorFieldTilde Phi_NPtilde = gradient(c.molecule.mfKernel*Phi_rhoMF + (needRho ? s.polKernel*Phi_rho : 0)); setGzero(Phi_NPtilde, getGzero(Phi_NPtilde) + Phi_P0tot); VectorField Phi_NP = Jdag(Phi_NPtilde); Phi_NPtilde=0; //propagate gradients from NP to N, epsMF and rhoExternal: Polarization_Compute_Pi_Ni #undef Polarization_Compute_Pi_Ni // --> via Ni ScalarField Phi_Ni; for(int k=0; k<3; k++) Phi_Ni += Phi_NP[k]*Pi[k]; Phi_Ntilde[c.offsetDensity+i] += (1./gInfo.dV) * Idag(Phi_Ni); Phi_Ni=0; // --> via Pi VectorFieldTilde Phi_PiTilde = Idag(Phi_NP * Ni); Phi_NP=0; Phi_epsMF += (Cpol*s.alpha/gInfo.dV)*(c.molecule.mfKernel*Phi_PiTilde); } } Phi_P0[ic] += (1./gInfo.detR) * Phi_P0tot; //convert to functional derivative } } } //--------- Hard sphere mixture and bonding ------------- { //Compute the FMT weighted densities: ScalarFieldTilde n0tilde, n1tilde, n2tilde, n3tilde, n1vTilde, n2mTilde; std::vector<ScalarField> n0mol(component.size(), 0); //partial n0 for molecules that need bonding corrections std::vector<int> n0mult(component.size(), 0); //number of sites which contribute to n0 for each molecule std::vector<std::map<double,int> > bond(component.size()); //sets of bonds for each molecule bool bondsPresent = false; //whether bonds are present for any molecule for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; bond[ic] = c.molecule.getBonds(); ScalarFieldTilde n0molTilde; for(unsigned i=0; i<c.molecule.sites.size(); i++) { const Molecule::Site& s = *(c.molecule.sites[i]); if(s.Rhs) { const ScalarFieldTilde& Nsite = Ntilde[c.offsetDensity+i]; n0mult[ic] += s.positions.size(); n0molTilde += s.w0 * Nsite; n1tilde += s.w1 * Nsite; n2tilde += s.w2 * Nsite; n3tilde += s.w3 * Nsite; n1vTilde += s.w1v * Nsite; n2mTilde += s.w2m * Nsite; } } if(n0molTilde) n0tilde += n0molTilde; if(bond[ic].size()) { n0mol[ic] = I(n0molTilde); bondsPresent = true; } } if(n0tilde) //at least one sphere in the mixture { ScalarField n0 = I(n0tilde); n0tilde=0; ScalarField n1 = I(n1tilde); n1tilde=0; ScalarField n2 = I(n2tilde); n2tilde=0; ScalarField Phi_n0, Phi_n1, Phi_n2; ScalarFieldTilde Phi_n3tilde, Phi_n1vTilde, Phi_n2mTilde; //Compute the sphere mixture free energy: Phi["MixedFMT"] += T * PhiFMT(n0, n1, n2, n3tilde, n1vTilde, n2mTilde, Phi_n0, Phi_n1, Phi_n2, Phi_n3tilde, Phi_n1vTilde, Phi_n2mTilde); //Bonding corrections if required if(bondsPresent) { for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; ScalarField Phi_n0mol; for(const auto& b: bond[ic]) Phi["Bonding"] += T * PhiBond(b.first, b.second*1./n0mult[ic], n0mol[ic], n2, n3tilde, Phi_n0mol, Phi_n2, Phi_n3tilde); if(Phi_n0mol) { //Propagate gradient w.r.t n0mol[ic] to the site densities: ScalarFieldTilde Phi_n0molTilde = Idag(Phi_n0mol); for(unsigned i=0; i<c.molecule.sites.size(); i++) { const Molecule::Site& s = *(c.molecule.sites[i]); if(s.Rhs) Phi_Ntilde[c.offsetDensity+i] += T * (s.w0 * Phi_n0molTilde); } } } } //Accumulate gradients w.r.t weighted densities to site densities: ScalarFieldTilde Phi_n0tilde = Idag(Phi_n0); Phi_n0=0; ScalarFieldTilde Phi_n1tilde = Idag(Phi_n1); Phi_n1=0; ScalarFieldTilde Phi_n2tilde = Idag(Phi_n2); Phi_n2=0; for(const FluidComponent* c: component) { for(unsigned i=0; i<c->molecule.sites.size(); i++) { const Molecule::Site& s = *(c->molecule.sites[i]); if(s.Rhs) { ScalarFieldTilde& Phi_Nsite = Phi_Ntilde[c->offsetDensity+i]; Phi_Nsite += T * (s.w0 * Phi_n0tilde); Phi_Nsite += T * (s.w1 * Phi_n1tilde); Phi_Nsite += T * (s.w2 * Phi_n2tilde); Phi_Nsite += T * (s.w3 * Phi_n3tilde); Phi_Nsite += T * (s.w1v * Phi_n1vTilde); Phi_Nsite += T * (s.w2m * Phi_n2mTilde); } } } } } //---------- Excess functionals -------------- for(const FluidComponent* c: component) if(c->fex) Phi["Fex("+c->molecule.name+")"] += c->fex->compute(Ñ[c->offsetDensity], &Phi_Ntilde[c->offsetDensity]); //--------- Mixing functionals -------------- for(const Fmix* fmix: fmixArr) Phi["Fmix("+fmix->getName()+")"] += fmix->compute(Ntilde, Phi_Ntilde); //--------- PhiNI --------- nullToZero(Phi_Ntilde, gInfo); if(outputs.N) outputs.N->resize(nDensities); //Put the site densities and gradients back in real space ScalarFieldArray N(nDensities); ScalarFieldArray Phi_N(nDensities); for(unsigned i=0; i<nDensities; i++) { N[i] = I(Ntilde[i]); Ntilde[i]=0; Phi_N[i] = Jdag(Phi_Ntilde[i]); Phi_Ntilde[i] = 0; if(outputs.N) (*outputs.N)[i] = N[i]; //Link site-density to return pointer if necessary } //Estimate psiEff based on gradients, if requested if(outputs.psiEff) { outputs.psiEff->resize(nDensities); for(const FluidComponent* c: component) for(unsigned i=0; i<c->molecule.sites.size(); i++) { ScalarField& psiCur = outputs.psiEff->at(c->offsetDensity+i); psiCur = Phi_N[c->offsetDensity+i] + c->idealGas->V[i]; if(i==0) psiCur -= c->idealGas->mu / c->molecule.sites[0]->positions.size(); psiCur *= (-1./T); } } for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; Phi["PhiNI("+c.molecule.name+")"] += c.idealGas->compute(&indep[c.offsetIndep], &N[c.offsetDensity], &Phi_N[c.offsetDensity], Nscale[ic], Phi_Nscale[ic]); //Fixed N correction to entropy: if(Nscale[ic]!=1.0) { double deltaTs = T*log(Nscale[ic]) / c.molecule.sites[0]->positions.size(); Phi_N[c.offsetDensity] += deltaTs; Phi["PhiNI("+c.molecule.name+")"] += integral(N[c.offsetDensity])*deltaTs; } } //Add in the implicit contributions to Phi_Nscale for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& ci = *component[ic]; bool anyNonzero=false; for(unsigned jc=0; jc<component.size(); jc++) if(Nscale_N0[ic][jc]) anyNonzero=true; if(anyNonzero) { Phi_Nscale[ic] += gInfo.detR*dot(P0[ic], Phi_P0[ic])/ Nscale[ic]; for(unsigned i=0; i<ci.molecule.sites.size(); i++) Phi_Nscale[ic] += gInfo.dV*dot(N[ci.offsetDensity+i], Phi_N[ci.offsetDensity+i])/ Nscale[ic]; } } //Propagate gradients from Nscale to N: for(unsigned jc=0; jc<component.size(); jc++) { const FluidComponent& cj = *component[jc]; double Phi_Ncontrib = 0.0; for(unsigned ic=0; ic<component.size(); ic++) if(Nscale_N0[ic][jc]) Phi_Ncontrib += Phi_Nscale[ic] * Nscale_N0[ic][jc]; if(Phi_Ncontrib) Phi_N[cj.offsetDensity] += Phi_Ncontrib / (Nscale[jc] * cj.molecule.sites[0]->positions.size()); } //Propagate gradients from Phi_N and Phi_P to Phi_indep Phi_indep.resize(get_nIndep()); for(unsigned ic=0; ic<component.size(); ic++) { const FluidComponent& c = *component[ic]; c.idealGas->convertGradients(&indep[c.offsetIndep], &N[c.offsetDensity], &Phi_N[c.offsetDensity], Phi_P0[ic], &Phi_indep[c.offsetIndep], Nscale[ic]); } for(unsigned k=nIndepIdgas; k<get_nIndep(); k++) Phi_indep[k] = Jdag(Phi_epsMF[k-nIndepIdgas]); //Propagate gradients from Nscale to Qfixed / rhoExternal (Natural G=0 solution) if(outputs.Phi_rhoExternal) { double Phi_Qfixed = 0.; for(unsigned ic=0; ic<component.size(); ic++) { Phi_Qfixed += Phi_Nscale[ic] * Nscale_Qfixed[ic]; if (N0Q.size() && (!useMFKernel)) { const FluidComponent& c = *component[ic]; for(unsigned i=0; i<c.molecule.sites.size(); i++) { //Correction to lambda from charge kernel mismatch const Molecule::Site& s = *(c.molecule.sites[i]); double lambda_s = (Ntot_c[ic]/gInfo.detR-c.idealGas->Nbulk)*s.deltaS*s.positions.size(); if(verboseLog) logPrintf("Charge kernel mismatch correction for site %s of molecule %s: %lg\n", s.name.c_str(),c.molecule.name.c_str(),lambda_s); Phi_Qfixed += lambda_s; } if(verboseLog) logPrintf("Total number of molecules of type %s: %lg\n",c.molecule.name.c_str(),Ntot_c[ic]); } } nullToZero(*outputs.Phi_rhoExternal, gInfo); (*outputs.Phi_rhoExternal)->setGzero(Phi_Qfixed); } Phi["+pV"] += p * gInfo.detR; //background correction if(verboseLog) Phi.print(globalLog, true, "\t\t\t\t%15s = %25.16lf\n"); if(outputs.Phi) *(outputs.Phi) = Phi; Phi_indep *= gInfo.dV; //convert functional derivative to partial derivative watch.stop(); return Phi; }
int checkCorrection(const Box& a_domain) { int eekflag = 0; const EBIndexSpace* const ebisPtr = Chombo_EBIS::instance(); CH_assert(ebisPtr->isDefined()); //create a dbl of split up into 2^D boxes Vector<Box> vbox; Vector<int> proc; domainSplit(a_domain, vbox, a_domain.size(0)/2); LoadBalance(proc, vbox); DisjointBoxLayout dbl(vbox, proc); LayoutData<bool> map1d(dbl); int ibox = 0; //make every other map 1d for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { map1d[dit()] = (ibox%2 == 0); ibox++; } LevelData< BaseFab<int> > intmap(dbl, 1 , IntVect::Unit); Correct1D2D::makeIntMap(intmap, map1d, dbl); //this defines an ebisl with 2 ghost cells EBLevelGrid eblg(dbl, ProblemDomain(a_domain), 2, Chombo_EBIS::instance()) ; RealVect fluxVal = RealVect::Unit; Real dx = 1.0/a_domain.size(0); EBCellFactory fact(eblg.getEBISL()); LevelData<EBCellFAB> divU(dbl, 1, IntVect::Zero, fact); Correct1D2D correctinator(eblg, map1d, 1); correctinator.setToZero(); //this is important for (DataIterator dit = dbl.dataIterator(); dit.ok(); ++dit) { //make a flux that is borked on the 1d side of box boundaries EBFluxFAB fluxFunc( eblg.getEBISL()[dit()], dbl[dit()], 1); setBorkedFlux(fluxFunc, eblg.getEBISL()[dit()], dbl[dit()], fluxVal, intmap[dit()]); //increment 1d buffers in corrector for (int idir = 0; idir < SpaceDim; idir++) { correctinator.increment1D(fluxFunc[idir], 1./dx, dit()); correctinator.increment2D(fluxFunc[idir], 1./dx, dit()); } //now take the divergence of the flux. it should be zero except //at box boundaries on the 1d side divergence(divU[dit()], fluxFunc, eblg.getEBISL()[dit()], dbl[dit()], fluxVal, dx); } //find max value of divergence before corrections Real max, min; EBLevelDataOps::getMaxMin(max, min, divU, 0); pout() << "before correction max divU = " << max << ", min divU = " << min << endl; //correct solution due to mismatch at 1d-2d boundaries correctinator.correctSolution(divU); //recalc max min EBLevelDataOps::getMaxMin(max, min, divU, 0); pout() << "after correction max divU = " << max << ", min divU = " << min << endl; if (Abs(max-min) > 1.0e-3) { pout() << "corrector did not seem to correct" << endl; return -7; } return eekflag; }
/** * * Function to compute the optical flow in one scale * **/ void Dual_TVL1_optic_flow( float *I0, // source image float *I1, // target image float *u1, // x component of the optical flow float *u2, // y component of the optical flow const int nx, // image width const int ny, // image height const float tau, // time step const float lambda, // weight parameter for the data term const float theta, // weight parameter for (u - v)² const int warps, // number of warpings per scale const float epsilon, // tolerance for numerical convergence const bool verbose // enable/disable the verbose mode ) { const int size = nx * ny; const float l_t = lambda * theta; size_t sf = sizeof(float); float *I1x = malloc(size*sf); float *I1y = xmalloc(size*sf); float *I1w = xmalloc(size*sf); float *I1wx = xmalloc(size*sf); float *I1wy = xmalloc(size*sf); float *rho_c = xmalloc(size*sf); float *v1 = xmalloc(size*sf); float *v2 = xmalloc(size*sf); float *p11 = xmalloc(size*sf); float *p12 = xmalloc(size*sf); float *p21 = xmalloc(size*sf); float *p22 = xmalloc(size*sf); float *div = xmalloc(size*sf); float *grad = xmalloc(size*sf); float *div_p1 = xmalloc(size*sf); float *div_p2 = xmalloc(size*sf); float *u1x = xmalloc(size*sf); float *u1y = xmalloc(size*sf); float *u2x = xmalloc(size*sf); float *u2y = xmalloc(size*sf); centered_gradient(I1, I1x, I1y, nx, ny); // initialization of p for (int i = 0; i < size; i++) { p11[i] = p12[i] = 0.0; p21[i] = p22[i] = 0.0; } for (int warpings = 0; warpings < warps; warpings++) { // compute the warping of the target image and its derivatives bicubic_interpolation_warp(I1, u1, u2, I1w, nx, ny, true); bicubic_interpolation_warp(I1x, u1, u2, I1wx, nx, ny, true); bicubic_interpolation_warp(I1y, u1, u2, I1wy, nx, ny, true); #pragma omp parallel for for (int i = 0; i < size; i++) { const float Ix2 = I1wx[i] * I1wx[i]; const float Iy2 = I1wy[i] * I1wy[i]; // store the |Grad(I1)|^2 grad[i] = (Ix2 + Iy2); // compute the constant part of the rho function rho_c[i] = (I1w[i] - I1wx[i] * u1[i] - I1wy[i] * u2[i] - I0[i]); } int n = 0; float error = INFINITY; while (error > epsilon * epsilon && n < MAX_ITERATIONS) { n++; // estimate the values of the variable (v1, v2) // (thresholding opterator TH) #pragma omp parallel for for (int i = 0; i < size; i++) { const float rho = rho_c[i] + (I1wx[i] * u1[i] + I1wy[i] * u2[i]); float d1, d2; if (rho < - l_t * grad[i]) { d1 = l_t * I1wx[i]; d2 = l_t * I1wy[i]; } else { if (rho > l_t * grad[i]) { d1 = -l_t * I1wx[i]; d2 = -l_t * I1wy[i]; } else { if (grad[i] < GRAD_IS_ZERO) d1 = d2 = 0; else { float fi = -rho/grad[i]; d1 = fi * I1wx[i]; d2 = fi * I1wy[i]; } } } v1[i] = u1[i] + d1; v2[i] = u2[i] + d2; } // compute the divergence of the dual variable (p1, p2) divergence(p11, p12, div_p1, nx ,ny); divergence(p21, p22, div_p2, nx ,ny); // estimate the values of the optical flow (u1, u2) error = 0.0; #pragma omp parallel for reduction(+:error) for (int i = 0; i < size; i++) { const float u1k = u1[i]; const float u2k = u2[i]; u1[i] = v1[i] + theta * div_p1[i]; u2[i] = v2[i] + theta * div_p2[i]; error += (u1[i] - u1k) * (u1[i] - u1k) + (u2[i] - u2k) * (u2[i] - u2k); } error /= size; // compute the gradient of the optical flow (Du1, Du2) forward_gradient(u1, u1x, u1y, nx ,ny); forward_gradient(u2, u2x, u2y, nx ,ny); // estimate the values of the dual variable (p1, p2) #pragma omp parallel for for (int i = 0; i < size; i++) { const float taut = tau / theta; const float g1 = hypot(u1x[i], u1y[i]); const float g2 = hypot(u2x[i], u2y[i]); const float ng1 = 1.0 + taut * g1; const float ng2 = 1.0 + taut * g2; p11[i] = (p11[i] + taut * u1x[i]) / ng1; p12[i] = (p12[i] + taut * u1y[i]) / ng1; p21[i] = (p21[i] + taut * u2x[i]) / ng2; p22[i] = (p22[i] + taut * u2y[i]) / ng2; } } if (verbose) fprintf(stderr, "Warping: %d, " "Iterations: %d, " "Error: %f\n", warpings, n, error); } // delete allocated memory free(I1x); free(I1y); free(I1w); free(I1wx); free(I1wy); free(rho_c); free(v1); free(v2); free(p11); free(p12); free(p21); free(p22); free(div); free(grad); free(div_p1); free(div_p2); free(u1x); free(u1y); free(u2x); free(u2y); }
void StableFluid3D::projectVelocity(double dt) { setBoundary(); Vector divergence(vel.Length()); // fill in velocities double dx = width / (double)resX; double dy = height / (double)resY; double dz = depth / (double)resZ; for (int i = 0; i < resX; ++i) { for (int j = 0; j < resY; ++j) { for (int k = 0; k < resZ; ++k) { int index = makeIndex(i, j, k); double div = (tempVelocities[0][i + 1][j][k] - tempVelocities[0][i][j][k]) / dx + (tempVelocities[1][i][j + 1][k] - tempVelocities[1][i][j][k]) / dy + (tempVelocities[2][i][j][k + 1] - tempVelocities[2][i][j][k]) / dz; vel[index] = div; divergence[index] = div; } } } // vel *= density / dt; bool useOldPCG = false; if (useOldPCG) { int k = 0; Vector laplacianTimesPressure(pressure.Length()); laplacian.Multiply(pressure, laplacianTimesPressure); r[0] = vel - laplacianTimesPressure; double error = r[0].Magnitude2(); while ((std::sqrt(error) > PCG_EPS) && (k < PCG_MAXITER)) { //cerr << "PCG iteration " << k << ", error: " << std::sqrt(error) << endl; ConjugateGradient(preconditioner, z[k % 2], r[k % 2], 0.0001, 500.0); ++k; int i1 = (k - 1) % 2; int i2 = k % 2; if (k == 1) { p = z[0]; } else { double beta = (InnerProduct(r[i1], z[i1])) / (InnerProduct(r[i2], z[i2])); p *= beta; p += z[i1]; } Vector laplacianTimesP(p.Length()); laplacian.Multiply(p, laplacianTimesP); double alpha = (InnerProduct(r[i1], z[i1])) / (InnerProduct(p, laplacianTimesP)); pressure += alpha * p; r[i2] = r[i1] - alpha * (laplacianTimesP); error = r[i2].Magnitude2(); } if (std::sqrt(error) > PCG_EPS) { std::cout << "end preconditioned conj grad " << "error: " << error << std::endl; } } else { p = Vector(vel.Length()); r[0] = divergence; //ApplyPreconditioner(r[0], z[0]); double sigma = InnerProduct(r[0], z[0]); int k = 0; double error = r[0].Magnitude2(); while (k < PCG_MAXITER) { ++k; Vector s(vel.Length()); s = z[0]; int k = 0; laplacian.Multiply(s, z[0]); double rho = 1.0; double alpha = rho / InnerProduct(s, z[0]); p += alpha * s; r[0] -= alpha * z[0]; error = r[0].Magnitude2(); if (error < PCG_EPS * PCG_EPS) { pressure = p; break; } //ApplyPreconditioner(r[0], z[0]); double sigmaNew = InnerProduct(r[0], z[0]); double beta = sigmaNew / rho; s = z[0] + beta * s; sigma = sigmaNew; } Vector laplacianTimesPressure(pressure.Length()); laplacian.Multiply(pressure, laplacianTimesPressure); r[0] = vel - laplacianTimesPressure; error = r[0].Magnitude2(); while ((std::sqrt(error) > PCG_EPS) && (k < PCG_MAXITER)) { //cerr << "PCG iteration " << k << ", error: " << std::sqrt(error) << endl; ConjugateGradient(preconditioner, z[k % 2], r[k % 2], 0.0001, 500.0); ++k; int i1 = (k - 1) % 2; int i2 = k % 2; if (k == 1) { p = z[0]; } else { double beta = (InnerProduct(r[i1], z[i1])) / (InnerProduct(r[i2], z[i2])); p *= beta; p += z[i1]; } Vector laplacianTimesP(p.Length()); laplacian.Multiply(p, laplacianTimesP); double alpha = (InnerProduct(r[i1], z[i1])) / (InnerProduct(p, laplacianTimesP)); pressure += alpha * p; r[i2] = r[i1] - alpha * (laplacianTimesP); error = r[i2].Magnitude2(); } if (std::sqrt(error) > PCG_EPS) { std::cout << "end preconditioned conj grad " << "error: " << error << std::endl; } } /* mathlib::Vector PCGr, PCGd, PCGq, PCGs; PCGr.Resize(resX * resY * resZ); PCGd.Resize(resX * resY * resZ); PCGq.Resize(resX * resY * resZ); PCGs.Resize(resX * resY * resZ); int iter = 0; PCGr = vel - laplacian * pressure; mathlib::ConjugateGradient(preconditioner, PCGd, PCGr); double deltaNew = mathlib::InnerProduct(PCGr, PCGd); double errBound = PCG_EPS * PCG_EPS * deltaNew; while ((iter < PCG_MAXITER) && (deltaNew > errBound)) { if (!(iter % 3)) cerr << "iteration " << iter << ", error: " << deltaNew << endl; PCGq = laplacian * PCGd; double alpha = deltaNew / (mathlib::InnerProduct(PCGd, PCGq)); pressure += alpha * PCGd; if ((iter % 10) == 0) PCGr = vel - laplacian * pressure; else PCGr -= alpha * PCGq; mathlib::ConjugateGradient(preconditioner, PCGs, PCGr); double deltaOld = deltaNew; deltaNew = mathlib::InnerProduct(PCGr, PCGs); double beta = deltaNew / deltaOld; PCGd *= beta; PCGd += PCGs; ++iter; } cout << "end preconditioned conj grad "<< "error: " << deltaNew << endl; */ std::cout << "dt:" << dt << "\t density:" << density << std::endl; // dt = 1.0; for (int i = 0; i < resX; ++i) { for (int j = 0; j < resY; ++j) { for (int k = 0; k < resZ; ++k) { int i1 = makeIndex(i, j, k); int i2; double deltaPressure; i2 = (i == 0 ? i1 : i1 - 1); velocities[0][i][j][k] = tempVelocities[0][i][j][k] - dt* 0.5 * (pressure[i1] - pressure[i2]) / dx; deltaPressure = pressure[i1] - pressure[i2]; i2 = (j == 0 ? i1 : i1 - resX); velocities[1][i][j][k] = tempVelocities[1][i][j][k] - dt * 0.5 * (pressure[i1] - pressure[i2]) / dy; deltaPressure = pressure[i1] - pressure[i2]; i2 = (k == 0 ? i1 : i1 - resY * resX); velocities[2][i][j][k] = tempVelocities[2][i][j][k] - dt * 0.5 * (pressure[i1] - pressure[i2]) / dz; deltaPressure = pressure[i1] - pressure[i2]; } } } }
void PCM::updateCavity() { //Cavities from expanded densities for SGA13 variant: if(fsp.pcmVariant == PCM_SGA13) { ScalarField* shapeEx[2] = { &shape, &shapeVdw }; for(int i=0; i<2; i++) { ShapeFunction::expandDensity(wExpand[i], Rex[i], nCavity, nCavityEx[i]); ShapeFunction::compute(nCavityEx[i], *(shapeEx[i]), fsp.nc, fsp.sigma); } } else if(fsp.pcmVariant == PCM_CANDLE) { nCavityEx[0] = fsp.Ztot * I(Sf[0] * J(nCavity)); ShapeFunction::compute(nCavityEx[0], coulomb(Sf[0]*rhoExplicitTilde), shapeVdw, fsp.nc, fsp.sigma, fsp.pCavity); //vdW cavity shape = I(wExpand[0] * J(shapeVdw)); //dielectric cavity } else if(isPCM_SCCS(fsp.pcmVariant)) ShapeFunctionSCCS::compute(nCavity, shape, fsp.rhoMin, fsp.rhoMax, epsBulk); else //Compute directly from nCavity (which is a density product for SaLSA): ShapeFunction::compute(nCavity, shape, fsp.nc, fsp.sigma); //Compute and cache cavitation energy and gradients: const auto& solvent = fsp.solvents[0]; switch(fsp.pcmVariant) { case PCM_SaLSA: case PCM_CANDLE: case PCM_SGA13: { //Select relevant shape function: const ScalarFieldTilde sTilde = J(fsp.pcmVariant==PCM_SaLSA ? shape : shapeVdw); ScalarFieldTilde A_sTilde; //Cavitation: const double nlT = solvent->Nbulk * fsp.T; const double Gamma = log(nlT/solvent->Pvap) - 1.; const double Cp = 15. * (solvent->sigmaBulk/(2*solvent->Rvdw * nlT) - (1+Gamma)/6); const double coeff2 = 1. + Cp - 2.*Gamma; const double coeff3 = Gamma - 1. -2.*Cp; ScalarField sbar = I(wCavity*sTilde); Adiel["Cavitation"] = nlT * integral(sbar*(Gamma + sbar*(coeff2 + sbar*(coeff3 + sbar*Cp)))); A_sTilde += wCavity*Idag(nlT * (Gamma + sbar*(2.*coeff2 + sbar*(3.*coeff3 + sbar*(4.*Cp))))); //Dispersion: ScalarFieldTildeArray Ntilde(Sf.size()), A_Ntilde(Sf.size()); //effective nuclear densities in spherical-averaged ansatz for(unsigned i=0; i<Sf.size(); i++) Ntilde[i] = solvent->Nbulk * (Sf[i] * sTilde); const double vdwScaleEff = (fsp.pcmVariant==PCM_CANDLE) ? fsp.sqrtC6eff : fsp.vdwScale; Adiel["Dispersion"] = e.vanDerWaals->energyAndGrad(atpos, Ntilde, atomicNumbers, vdwScaleEff, &A_Ntilde); A_vdwScale = Adiel["Dispersion"]/vdwScaleEff; for(unsigned i=0; i<Sf.size(); i++) if(A_Ntilde[i]) A_sTilde += solvent->Nbulk * (Sf[i] * A_Ntilde[i]); //Propagate gradients to appropriate shape function: (fsp.pcmVariant==PCM_SaLSA ? Acavity_shape : Acavity_shapeVdw) = Jdag(A_sTilde); break; } case PCM_GLSSA13: { VectorField Dshape = gradient(shape); ScalarField surfaceDensity = sqrt(lengthSquared(Dshape)); ScalarField invSurfaceDensity = inv(surfaceDensity); A_tension = integral(surfaceDensity); Adiel["CavityTension"] = A_tension * fsp.cavityTension; Acavity_shape = (-fsp.cavityTension)*divergence(Dshape*invSurfaceDensity); break; } case PCM_LA12: case PCM_PRA05: break; //no contribution case_PCM_SCCS_any: { //Volume contribution: Adiel["CavityPressure"] = fsp.cavityPressure * (gInfo.detR - integral(shape)); //Surface contribution: ScalarField shapePlus, shapeMinus; ShapeFunctionSCCS::compute(nCavity+(0.5*fsp.rhoDelta), shapePlus, fsp.rhoMin, fsp.rhoMax, epsBulk); ShapeFunctionSCCS::compute(nCavity-(0.5*fsp.rhoDelta), shapeMinus, fsp.rhoMin, fsp.rhoMax, epsBulk); ScalarField DnLength = sqrt(lengthSquared(gradient(nCavity))); Adiel["CavityTension"] = (fsp.cavityTension/fsp.rhoDelta) * integral(DnLength * (shapeMinus - shapePlus)); break; } } }