void RemovalState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const { if (!info.getUnloadLock()) { info.UpdateTimeTracker(diff); if (info.getTimeTracker().Passed() && !map.UnloadGrid(grid, false)) { TC_LOG_DEBUG("maps", "Grid[%u, %u] for map %u differed unloading due to players or active objects nearby", grid.getX(), grid.getY(), map.GetId()); map.ResetGridExpiry(grid); } } }
void RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 t_diff) const { if (!info.getUnloadLock()) { info.UpdateTimeTracker(t_diff); if (info.getTimeTracker().Passed()) { if (!m.UnloadGrid(grid, false)) { sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] for map %u differed unloading due to players or active objects nearby", grid.getX(), grid.getY(), m.GetId()); m.ResetGridExpiry(grid); } } } }
void RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { if(!info.getUnloadLock()) { info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { if( !m.UnloadGrid(x, y, false) ) { DEBUG_LOG("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); m.ResetGridExpiry(grid); } } } }
void ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle info.UpdateTimeTracker(t_diff); if (info.getTimeTracker().Passed()) { if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) { ObjectGridStoper stoper(grid); stoper.StopN(); grid.SetGridState(GRID_STATE_IDLE); sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] on map %u moved to IDLE state", x, y, m.GetId()); } else { m.ResetGridExpiry(grid, 0.1f); } } }
void ActiveState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const { // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle info.UpdateTimeTracker(diff); if (info.getTimeTracker().Passed()) { if (!grid.GetWorldObjectCountInNGrid<Player>() && !map.ActiveObjectsNearGrid(grid)) { ObjectGridStoper worker; TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer> visitor(worker); grid.VisitAllGrids(visitor); grid.SetGridState(GRID_STATE_IDLE); TC_LOG_DEBUG("maps", "Grid[%u, %u] on map %u moved to IDLE state", grid.getX(), grid.getY(), map.GetId()); } else map.ResetGridExpiry(grid, 0.1f); } }
void ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) { ObjectGridStoper stoper(grid); stoper.StopN(); grid.SetGridState(GRID_STATE_IDLE); } else { m.ResetGridExpiry(grid, 0.1f); } } }
void Basis::setup(const GridInfo& gInfo, const IonInfo& iInfo, double Ecut, const vector3<> k) { //Find the indices within Ecut: vector3<int> iGbox; for(int i=0; i<3; i++) iGbox[i] = 1 + int(sqrt(2*Ecut) * gInfo.R.column(i).length() / (2*M_PI)); std::vector< vector3<int> > iGvec; std::vector<int> indexVec; vector3<int> iG; for(iG[0]=-iGbox[0]; iG[0]<=iGbox[0]; iG[0]++) for(iG[1]=-iGbox[1]; iG[1]<=iGbox[1]; iG[1]++) for(iG[2]=-iGbox[2]; iG[2]<=iGbox[2]; iG[2]++) if(0.5*dot(iG+k, gInfo.GGT*(iG+k)) <= Ecut) { iGvec.push_back(iG); indexVec.push_back(gInfo.fullGindex(iG)); } setup(gInfo, iInfo, indexVec, iGvec); logPrintf("nbasis = %lu for k = ", nbasis); k.print(globalLog, " %6.3f "); }
//################ Droplet on attractive wall #################### int main(int argc, char** argv) { initSystem(argc, argv); GridInfo gInfo; gInfo.S = vector3<int>(64, 64, 64); double hGrid=1.0; //gInfo.S = vector3<int>(128, 128, 128); double hGrid=0.5; gInfo.R = Diag(gInfo.S * hGrid); gInfo.initialize(); double T = 298*Kelvin; FluidComponent component(FluidComponent::H2O, T, FluidComponent::ScalarEOS); component.s2quadType = QuadOctahedron; component.Nnorm = 270; PreconditionedFluidMixture fluidMixture(gInfo, T, 1.0); component.addToFluidMixture(&fluidMixture); double p = 1.01325*Bar; logPrintf("pV = %le\n", p*gInfo.detR); fluidMixture.initialize(p); #define geomName "AttractiveWall-3bohr-3.0kT/drop_plane" bool loadState=false; const char stateFilename[] = "TestFixedN/" geomName "_state.bin"; //Initialize potential: planar wall with attractive well: nullToZero(component.idealGas->V, gInfo); double xWall = 0.5*gInfo.R(0,0)-21.0; double dxWall = 2.0; applyFunc_r(gInfo, initAttractiveWall, xWall, dxWall, 100*T, 3.*T, component.idealGas->V[0]->data()); if(loadState) fluidMixture.loadState(stateFilename); else { //Initialize state biased towards center of cell const double muSet=-5.0; const double Rdroplet = 22.0; //guess droplet size: nullToZero(fluidMixture.state, gInfo, fluidMixture.get_nIndep()); applyFunc_r(gInfo, initSphere, gInfo.R*vector3<>(0.5,0.5,0.5), Rdroplet, 0.0, muSet, fluidMixture.state[0]->data()); RealKernel gauss(gInfo); initGaussianKernel(gauss, 2.0); fluidMixture.state[0] = I(gauss*J(fluidMixture.state[0])); ScalarField wallMask(ScalarFieldData::alloc(gInfo)); applyFunc_r(gInfo, initAttractiveWall, xWall, 2*dxWall, 0.0, 1.0, wallMask->data()); fluidMixture.state[0] *= (wallMask+1.0); } MinimizeParams mp; mp.fpLog = globalLog; mp.nDim = 2*gInfo.nr; mp.nIterations=10; mp.knormThreshold=1e-11; mp.dirUpdateScheme = MinimizeParams::FletcherReeves; //mp.dirUpdateScheme = MinimizeParams::SteepestDescent; //mp.updateTestStepSize = false; mp.fdTest = !loadState; int sysRet=system("mkdir -p TestFixedN/" geomName "_img"); if(sysRet) { logPrintf("Error making image directory\n"); mpiUtil->exit(sysRet); } for(int loopCount=0; loopCount<100; loopCount++) { ScalarFieldArray N; TIME("getOmega calculation (with gradient)", globalLog, double omega = fluidMixture.getFreeEnergy(FluidMixture::Outputs(&N)); if(std::isnan(omega)) break; //Don't save state after it has become nan ); logPrintf("Ntot = %lf\n", gInfo.dV*sum(N[0])); logPrintf("Saving state:\n"); fluidMixture.saveState(stateFilename); saveDX(N[0], "TestFixedN/" geomName "_nO"); saveDX(N[1], "TestFixedN/" geomName "_nH"); saveSphericalized(&N[0], 2, "TestFixedN/" geomName "_n.spherical", 0.25); //Invoke octave to create an image: FILE* pp = popen("octave -q", "w"); fprintf(pp, "imwrite( waterSlice(\"TestFixedN/" geomName "_n%%s.bin\", [%d %d %d], 1, %d, 1e-2),", gInfo.S[0], gInfo.S[1], gInfo.S[2], gInfo.S[2]/2); fprintf(pp, " \"TestFixedN/" geomName "_img/img%04d.png\"); exit;\n", loopCount); fflush(pp); pclose(pp); logPrintf("Starting CG:\n"); TIME("minimize", globalLog, fluidMixture.minimize(mp); );
void read(std::vector<ColumnBundle>& Y, const char *fname, const ElecInfo& eInfo, const ColumnBundleReadConversion* conversion) { if(conversion && conversion->realSpace) { if(eInfo.qStop==eInfo.qStart) return; //no k-point on this process const GridInfo* gInfoWfns = Y[eInfo.qStart].basis->gInfo; //Create a custom gInfo if necessary: GridInfo gInfoCustom; gInfoCustom.R = gInfoWfns->R; gInfoCustom.S = conversion->S_old; for(int k=0; k<3; k++) if(!gInfoCustom.S[k]) gInfoCustom.S[k] = gInfoWfns->S[k]; bool needCustom = !(gInfoCustom.S == gInfoWfns->S); if(needCustom) { logSuspend(); gInfoCustom.initialize(); logResume(); } const GridInfo& gInfo = needCustom ? gInfoCustom : *gInfoWfns; //Read one column at a time: complexScalarField Icol; nullToZero(Icol, gInfo); for(int q=eInfo.qStart; q<eInfo.qStop; q++) { int nCols = Y[q].nCols(); int nSpinor = Y[q].spinorLength(); if(conversion->nBandsOld) nCols = std::min(nCols, conversion->nBandsOld); for(int b=0; b<nCols; b++) for(int s=0; s<nSpinor; s++) { char fname_qb[1024]; sprintf(fname_qb, fname, q, b*nSpinor+s); loadRawBinary(Icol, fname_qb); if(needCustom) Y[q].setColumn(b,s, changeGrid(J(Icol), *gInfoWfns)); else Y[q].setColumn(b,s, J(Icol)); } } } else { //Check if a conversion is actually needed: std::vector<ColumnBundle> Ytmp(eInfo.qStop); std::vector<Basis> basisTmp(eInfo.qStop); std::vector<long> nBytes(mpiUtil->nProcesses(), 0); //total bytes to be read on each process for(int q=eInfo.qStart; q<eInfo.qStop; q++) { bool needTmp = false, customBasis = false; int nCols = Y[q].nCols(); if(conversion) { if(conversion->nBandsOld && conversion->nBandsOld!=nCols) { nCols = conversion->nBandsOld; needTmp = true; } double EcutOld = conversion->EcutOld ? conversion->EcutOld : conversion->Ecut; customBasis = (EcutOld!=conversion->Ecut); if(customBasis) { needTmp = true; logSuspend(); basisTmp[q].setup(*(Y[q].basis->gInfo), *(Y[q].basis->iInfo), EcutOld, Y[q].qnum->k); logResume(); } } const Basis* basis = customBasis ? &basisTmp[q] : Y[q].basis; int nSpinor = Y[q].spinorLength(); if(needTmp) Ytmp[q].init(nCols, basis->nbasis*nSpinor, basis, Y[q].qnum); nBytes[mpiUtil->iProcess()] += nCols * basis->nbasis*nSpinor * sizeof(complex); } //Sync nBytes: if(mpiUtil->nProcesses()>1) for(int iSrc=0; iSrc<mpiUtil->nProcesses(); iSrc++) mpiUtil->bcast(nBytes[iSrc], iSrc); //Compute offset of current process, and expected file length: long offset=0, fsize=0; for(int iSrc=0; iSrc<mpiUtil->nProcesses(); iSrc++) { if(iSrc<mpiUtil->iProcess()) offset += nBytes[iSrc]; fsize += nBytes[iSrc]; } //Read data into Ytmp or Y as appropriate, and convert if necessary: MPIUtil::File fp; mpiUtil->fopenRead(fp, fname, fsize, "Hint: Did you specify the correct nBandsOld, EcutOld and kdepOld?\n"); mpiUtil->fseek(fp, offset, SEEK_SET); for(int q=eInfo.qStart; q<eInfo.qStop; q++) { ColumnBundle& Ycur = Ytmp[q] ? Ytmp[q] : Y[q]; mpiUtil->fread(Ycur.data(), sizeof(complex), Ycur.nData(), fp); if(Ytmp[q]) //apply conversions: { if(Ytmp[q].basis!=Y[q].basis) { int nSpinor = Y[q].spinorLength(); for(int b=0; b<std::min(Y[q].nCols(), Ytmp[q].nCols()); b++) for(int s=0; s<nSpinor; s++) Y[q].setColumn(b,s, Ytmp[q].getColumn(b,s)); //convert using the full G-space as an intermediate } else { if(Ytmp[q].nCols()<Y[q].nCols()) Y[q].setSub(0, Ytmp[q]); else Y[q] = Ytmp[q].getSub(0, Y[q].nCols()); } Ytmp[q].free(); } } mpiUtil->fclose(fp); } }
int main(int argc, char** argv) { initSystem(argc, argv); //Parse command-line S2quadType quadType = QuadEuler; int nBeta = 12; if(argc > 1) { if(!S2quadTypeMap.getEnum(argv[1], quadType)) die("<quad> must be one of %s\n", S2quadTypeMap.optionList().c_str()); if(quadType==QuadEuler) { if(argc < 3) die("<nBeta> must be specified for Euler quadratures.\n") nBeta = atoi(argv[2]); if(nBeta <= 0) die("<nBeta> must be non-negative.") } } //Setup simulation grid: GridInfo gInfo; gInfo.S = vector3<int>(1, 1, 4096); const double hGrid = 0.0625; gInfo.R = Diag(hGrid * gInfo.S); gInfo.initialize(); double T = 298*Kelvin; FluidComponent component(FluidComponent::H2O, T, FluidComponent::ScalarEOS); component.s2quadType = quadType; component.quad_nBeta = nBeta; component.representation = FluidComponent::Pomega; FluidMixture fluidMixture(gInfo, T); component.addToFluidMixture(&fluidMixture); double p = 1.01325*Bar; logPrintf("pV = %le\n", p*gInfo.detR); fluidMixture.initialize(p); //Initialize external potential (repel O from a cube) double Dfield = 1.0 * eV/Angstrom; const double zWall = 8.0 - 1e-3; const double& gridLength = gInfo.R(2,2); ScalarField phiApplied(ScalarFieldData::alloc(gInfo)), phiWall(ScalarFieldData::alloc(gInfo)); applyFunc_r(gInfo, setPhi, phiApplied->data(), phiWall->data(), gridLength, Dfield, zWall); const double ZO = component.molecule.sites[0]->chargeKernel(0); component.idealGas->V[0] = ZO * phiApplied + phiWall; component.idealGas->V[1] = -0.5*ZO * phiApplied + phiWall; //----- Initialize state ----- fluidMixture.initState(0.01); //----- FDtest and CG ----- MinimizeParams mp; mp.fpLog = globalLog; mp.nDim = gInfo.nr * fluidMixture.get_nIndep(); mp.energyLabel = "Phi"; mp.nIterations=1500; mp.energyDiffThreshold=1e-16; fluidMixture.minimize(mp); //------ Outputs --------- ostringstream quadName; quadName << S2quadTypeMap.getString(quadType); if(quadType == QuadEuler) quadName << nBeta; ScalarFieldArray N; fluidMixture.getFreeEnergy(FluidMixture::Outputs(&N)); FILE* fp = fopen((quadName.str()+".Nplanar").c_str(), "w"); double* NOdata = N[0]->data(); double* NHdata = N[1]->data(); double nlInv = 1./component.idealGas->get_Nbulk(); for(int i=0; i<gInfo.S[2]/2; i++) fprintf(fp, "%le\t%le\t%le\n", i*hGrid, nlInv*NOdata[i], 0.5*nlInv*NHdata[i]); fclose(fp); finalizeSystem(); return 0; }