Page MenuHomec4science

No OneTemporary

File Metadata

Created
Thu, Feb 20, 12:50
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/allvars.h b/src/allvars.h
index 603dc87..ba13529 100644
--- a/src/allvars.h
+++ b/src/allvars.h
@@ -1,2581 +1,2586 @@
/*! \file allvars.h
* \brief declares global variables.
*
* This file declares all global variables. Further variables should be added here, and declared as
* 'extern'. The actual existence of these variables is provided by the file 'allvars.c'. To produce
* 'allvars.c' from 'allvars.h', do the following:
*
* - Erase all #define's, typedef's, and enum's
* - add #include "allvars.h", delete the #ifndef ALLVARS_H conditional
* - delete all keywords 'extern'
* - delete all struct definitions enclosed in {...}, e.g.
* "extern struct global_data_all_processes {....} All;"
* becomes "struct global_data_all_processes All;"
*/
#ifndef ALLVARS_H
#define ALLVARS_H
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_integration.h>
#include "tags.h"
#define GADGETVERSION "2.0" /*!< code version string */
#define TIMEBASE (1<<28) /*!< The simulated timespan is mapped onto the integer interval [0,TIMESPAN],
* where TIMESPAN needs to be a power of 2. Note that (1<<28) corresponds to 2^29
*/
#define MAXTOPNODES 200000 /*!< Maximum number of nodes in the top-level tree used for domain decomposition */
typedef long long peanokey; /*!< defines the variable type used for Peano-Hilbert keys */
#define BITS_PER_DIMENSION 18 /*!< Bits per dimension available for Peano-Hilbert order.
Note: If peanokey is defined as type int, the allowed maximum is 10.
If 64-bit integers are used, the maximum is 21 */
#define PEANOCELLS (((peanokey)1)<<(3*BITS_PER_DIMENSION)) /*!< The number of different Peano-Hilbert cells */
#define RNDTABLE 3000 /*!< gives the length of a table with random numbers, refreshed at every timestep.
This is used to allow application of random numbers to a specific particle
in a way that is independent of the number of processors used. */
#define MAX_REAL_NUMBER 1e37
#define MIN_REAL_NUMBER 1e-37
#define MAXLEN_FILENAME 100 /*!< Maximum number of characters for filenames (including the full path) */
#ifdef ISOTHERM_EQS
#define GAMMA (1.0) /*!< index for isothermal gas */
#else
#define GAMMA (5.0/3) /*!< adiabatic index of simulated gas */
#endif
#define GAMMA_MINUS1 (GAMMA-1)
#define HYDROGEN_MASSFRAC 0.76 /*!< mass fraction of hydrogen, relevant only for radiative cooling */
/* Some physical constants in cgs units */
#define GRAVITY 6.672e-8 /*!< Gravitational constant (in cgs units) */
#define SOLAR_MASS 1.989e33
#define SOLAR_LUM 3.826e33
#define RAD_CONST 7.565e-15
#define AVOGADRO 6.0222e23
#define BOLTZMANN 1.3806e-16
#define GAS_CONST 8.31425e7
#define C 2.9979e10
#define PLANCK 6.6262e-27
#define CM_PER_MPC 3.085678e24
#define PROTONMASS 1.6726e-24
#define ELECTRONMASS 9.10953e-28
#define THOMPSON 6.65245e-25
#define ELECTRONCHARGE 4.8032e-10
#define HUBBLE 3.2407789e-18 /* in h/sec */
#define YEAR_IN_SECOND 31536000.0 /* year in sec */
#define FEH_SOLAR 0.00181 /* used only if cooling with metal is on and chimie is off */
#define KPC_IN_CM 3.085678e+21
#define PI 3.1415926535897931
#define TWOPI 6.2831853071795862
/* Some conversion factors */
#define SEC_PER_MEGAYEAR 3.155e13
#define SEC_PER_YEAR 3.155e7
#ifndef ASMTH
#define ASMTH 1.25 /*!< ASMTH gives the scale of the short-range/long-range force split in units of FFT-mesh cells */
#endif
#ifndef RCUT
#define RCUT 4.5 /*!< RCUT gives the maximum distance (in units of the scale used for the force split) out to
which short-range forces are evaluated in the short-range tree walk. */
#endif
#define MAX_NGB 20000 /*!< defines maximum length of neighbour list */
#define MAXLEN_OUTPUTLIST 10000 /*!< maxmimum number of entries in list of snapshot output times */
#define DRIFT_TABLE_LENGTH 1000 /*!< length of the lookup table used to hold the drift and kick factors */
#ifdef COSMICTIME
#define COSMICTIME_TABLE_LENGTH 1000 /*!< length of the lookup table used for the cosmic time computation */
#endif
#define MAXITER 1000 /*!< maxmimum number of steps for SPH neighbour iteration */
#ifdef DOUBLEPRECISION /*!< If defined, the variable type FLOAT is set to "double", otherwise to FLOAT */
#define FLOAT double
#else
#define FLOAT float
#endif
#ifndef TWODIMS
#define NUMDIMS 3 /*!< For 3D-normalized kernel */
#define KERNEL_COEFF_1 2.546479089470 /*!< Coefficients for SPH spline kernel and its derivative */
#define KERNEL_COEFF_2 15.278874536822
#define KERNEL_COEFF_3 45.836623610466
#define KERNEL_COEFF_4 30.557749073644
#define KERNEL_COEFF_5 5.092958178941
#define KERNEL_COEFF_6 (-15.278874536822)
#define NORM_COEFF 4.188790204786 /*!< Coefficient for kernel normalization. Note: 4.0/3 * PI = 4.188790204786 */
#else
#define NUMDIMS 2 /*!< For 2D-normalized kernel */
#define KERNEL_COEFF_1 (5.0/7*2.546479089470) /*!< Coefficients for SPH spline kernel and its derivative */
#define KERNEL_COEFF_2 (5.0/7*15.278874536822)
#define KERNEL_COEFF_3 (5.0/7*45.836623610466)
#define KERNEL_COEFF_4 (5.0/7*30.557749073644)
#define KERNEL_COEFF_5 (5.0/7*5.092958178941)
#define KERNEL_COEFF_6 (5.0/7*(-15.278874536822))
#define NORM_COEFF M_PI /*!< Coefficient for kernel normalization. */
#endif
#ifdef MULTIPHASE
#define GAS_SPH 0
#define GAS_STICKY 1
#define GAS_DARK 2
#endif
#if defined(SFR) || defined(STELLAR_PROP)
#define ST 1
#endif
#ifdef CHIMIE
#define NELEMENTS 10
#define MAXNELEMENTS 64
#endif
#ifdef COOLING
#define COOLING_NMETALICITIES 9
#define COOLING_NTEMPERATURES 171
#endif
#ifdef COMPUTE_VELOCITY_DISPERSION
#define VELOCITY_DISPERSION_SIZE 3
#endif
#ifdef TRACE_ACC
#define NUMTRACEAVG 64
#endif
#ifdef CHIMIE
extern int FE;
extern int METALS;
#endif
extern int SetMinTimeStepForActives;
extern int ThisTask; /*!< the rank of the local processor */
extern int NTask; /*!< number of processors */
extern int PTask; /*!< smallest integer such that NTask <= 2^PTask */
extern int NumPart; /*!< number of particles on the LOCAL processor */
extern int N_gas; /*!< number of gas particles on the LOCAL processor */
#if defined(SFR) || defined(STELLAR_PROP)
extern int N_stars; /*!< number of stars particle on the LOCAL processor */
#endif
#ifdef MULTIPHASE
extern int N_sph;
extern int N_sticky;
extern int N_stickyflaged;
extern int N_dark;
extern int NumColPotLocal; /*!< local number of potentially collisional particles */
extern int NumColPot; /*!< total number of potentially collisional particles */
extern int NumColLocal; /*!< local number of collisions */
extern int NumCol; /*!< total number of collisions */
extern int NumNoColLocal;
extern int NumNoCol;
#endif
#ifdef GAS_ACCRETION
extern int NumPart_acc;
extern int N_gas_acc;
#ifdef STELLAR_PROP
extern int N_stars_acc;
#endif
#endif
#ifdef HOT_HALO
extern int NumPart_HaloAcc;
#endif
extern long long Ntype[6]; /*!< total number of particles of each type */
extern int NtypeLocal[6]; /*!< local number of particles of each type */
extern int NumForceUpdate; /*!< number of active particles on local processor in current timestep */
extern int NumSphUpdate; /*!< number of active SPH particles on local processor in current timestep */
#ifdef CHIMIE
extern int NumStUpdate;
#endif
#ifdef TESSEL
extern int NumPTUpdate;
#endif
extern double CPUThisRun; /*!< Sums the CPU time for the process (current submission only) */
#ifdef SPLIT_DOMAIN_USING_TIME
extern double CPU_Gravity;
#endif
extern int RestartFlag; /*!< taken from command line used to start code. 0 is normal start-up from
initial conditions, 1 is resuming a run from a set of restart files, while 2
marks a restart from a snapshot file. */
extern char *Exportflag; /*!< Buffer used for flagging whether a particle needs to be exported to another process */
extern int *Ngblist; /*!< Buffer to hold indices of neighbours retrieved by the neighbour search routines */
extern int TreeReconstructFlag; /*!< Signals that a new tree needs to be constructed */
#ifdef SFR
extern int RearrangeParticlesFlag;/*!< Signals that particles must be rearanged */
#endif
extern int Flag_FullStep; /*!< This flag signals that the current step involves all particles */
extern gsl_rng *random_generator; /*!< the employed random number generator of the GSL library */
extern double RndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#ifdef SFR
extern double StarFormationRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef FEEDBACK_WIND
extern double FeedbackWindRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef CHIMIE
extern double ChimieRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef CHIMIE_KINETIC_FEEDBACK
extern double ChimieKineticFeedbackRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef GAS_ACCRETION
extern double gasAccretionRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef HOT_HALO
extern double HaloRndTable[RNDTABLE]; /*!< Hold a table with random numbers, refreshed every timestep */
#endif
#ifdef AB_TURB
//Ornstein-Uhlenbeck variables
extern double StOUVar;
extern double* StOUPhases;
extern gsl_rng* StRng;
//forcing field in fourie space
extern double* StAmpl;
extern double* StAka; //phases (real part)
extern double* StAkb; //phases (imag part)
extern double* StMode;
extern int StNModes;
//integertime StTPrev; (yr : ask ?)
extern int StTPrev;
extern double StSolWeightNorm;
#endif
#ifdef PY_INTERFACE
extern int NumPartQ;
extern int N_gasQ;
extern long long NtypeQ[6]; /*!< total number of particles of each type */
extern int NtypeLocalQ[6]; /*!< local number of particles of each type */
extern double DomainCornerQ[3]; /*!< gives the lower left corner of simulation volume */
extern double DomainCenterQ[3]; /*!< gives the center of simulation volume */
extern double DomainLenQ; /*!< gives the (maximum) side-length of simulation volume */
extern double DomainFacQ; /*!< factor used for converting particle coordinates to a Peano-Hilbert mesh covering the simulation volume */
extern int DomainMyStartQ; /*!< first domain mesh cell that resides on the local processor */
extern int DomainMyLastQ; /*!< last domain mesh cell that resides on the local processor */
extern int *DomainStartListQ; /*!< a table that lists the first domain mesh cell for all processors */
extern int *DomainEndListQ; /*!< a table that lists the last domain mesh cell for all processors */
extern double *DomainWorkQ; /*!< a table that gives the total "work" due to the particles stored by each processor */
extern int *DomainCountQ; /*!< a table that gives the total number of particles held by each processor */
extern int *DomainCountSphQ; /*!< a table that gives the total number of SPH particles held by each processor */
extern int *DomainTaskQ; /*!< this table gives for each leaf of the top-level tree the processor it was assigned to */
extern peanokey *DomainKeyBufQ; /*!< this points to a buffer used during the exchange of particle data */
extern int NTopnodesQ; /*!< total number of nodes in top-level tree */
extern int NTopleavesQ; /*!< number of leaves in top-level tree. Each leaf can be assigned to a different processor */
extern void *CommBufferQ; /*!< points to communication buffer, which is used in the domain decomposition, the
parallel tree-force computation, the SPH routines, etc. */
#endif
extern double DomainCorner[3]; /*!< gives the lower left corner of simulation volume */
extern double DomainCenter[3]; /*!< gives the center of simulation volume */
extern double DomainLen; /*!< gives the (maximum) side-length of simulation volume */
extern double DomainFac; /*!< factor used for converting particle coordinates to a Peano-Hilbert mesh covering the simulation volume */
extern int DomainMyStart; /*!< first domain mesh cell that resides on the local processor */
extern int DomainMyLast; /*!< last domain mesh cell that resides on the local processor */
extern int *DomainStartList; /*!< a table that lists the first domain mesh cell for all processors */
extern int *DomainEndList; /*!< a table that lists the last domain mesh cell for all processors */
extern double *DomainWork; /*!< a table that gives the total "work" due to the particles stored by each processor */
extern int *DomainCount; /*!< a table that gives the total number of particles held by each processor */
extern int *DomainCountSph; /*!< a table that gives the total number of SPH particles held by each processor */
extern int *DomainTask; /*!< this table gives for each leaf of the top-level tree the processor it was assigned to */
extern int *DomainNodeIndex; /*!< this table gives for each leaf of the top-level tree the corresponding node of the gravitational tree */
extern FLOAT *DomainTreeNodeLen; /*!< this table gives for each leaf of the top-level tree the side-length of the corresponding node of the gravitational tree */
extern FLOAT *DomainHmax; /*!< this table gives for each leaf of the top-level tree the maximum SPH smoothing length among the particles of the corresponding node of the gravitational tree */
extern struct DomainNODE
{
FLOAT s[3]; /*!< center-of-mass coordinates */
FLOAT vs[3]; /*!< center-of-mass velocities */
FLOAT mass; /*!< mass of node */
#ifdef STELLAR_FLUX
FLOAT starlum; /*!< star luminosity of node */
#endif
#ifdef UNEQUALSOFTENINGS
#ifndef ADAPTIVE_GRAVSOFT_FORGAS
int bitflags; /*!< this bit-field encodes the particle type with the largest softening among the particles of the nodes, and whether there are particles with different softening in the node */
#else
FLOAT maxsoft; /*!< hold the maximum gravitational softening of particles in the
node if the ADAPTIVE_GRAVSOFT_FORGAS option is selected */
#endif
#endif
}
*DomainMoment; /*!< this table stores for each node of the top-level tree corresponding node data from the gravitational tree */
extern peanokey *DomainKeyBuf; /*!< this points to a buffer used during the exchange of particle data */
extern peanokey *Key; /*!< a table used for storing Peano-Hilbert keys for particles */
extern peanokey *KeySorted; /*!< holds a sorted table of Peano-Hilbert keys for all particles, used to construct top-level tree */
extern int NTopnodes; /*!< total number of nodes in top-level tree */
extern int NTopleaves; /*!< number of leaves in top-level tree. Each leaf can be assigned to a different processor */
extern struct topnode_data
{
int Daughter; /*!< index of first daughter cell (out of 8) of top-level node */
int Pstart; /*!< for the present top-level node, this gives the index of the first node in the concatenated list of topnodes collected from all processors */
int Blocks; /*!< for the present top-level node, this gives the number of corresponding nodes in the concatenated list of topnodes collected from all processors */
int Leaf; /*!< if the node is a leaf, this gives its number when all leaves are traversed in Peano-Hilbert order */
peanokey Size; /*!< number of Peano-Hilbert mesh-cells represented by top-level node */
peanokey StartKey; /*!< first Peano-Hilbert key in top-level node */
long long Count; /*!< counts the number of particles in this top-level node */
}
#ifdef PY_INTERFACE
*TopNodesQ,
#endif
*TopNodes; /*!< points to the root node of the top-level tree */
extern double TimeOfLastTreeConstruction; /*!< holds what it says, only used in connection with FORCETEST */
/* variables for input/output, usually only used on process 0 */
extern char ParameterFile[MAXLEN_FILENAME]; /*!< file name of parameterfile used for starting the simulation */
extern FILE *FdInfo; /*!< file handle for info.txt log-file. */
extern FILE *FdLog; /*!< file handle for log.txt log-file. */
extern FILE *FdEnergy; /*!< file handle for energy.txt log-file. */
#ifdef SYSTEMSTATISTICS
extern FILE *FdSystem;
#endif
extern FILE *FdTimings; /*!< file handle for timings.txt log-file. */
extern FILE *FdCPU; /*!< file handle for cpu.txt log-file. */
#ifdef FORCETEST
extern FILE *FdForceTest; /*!< file handle for forcetest.txt log-file. */
#endif
#ifdef SFR
extern FILE *FdSfr; /*!< file handle for sfr.txt log-file. */
#endif
#ifdef CHIMIE
extern FILE *FdChimie; /*!< file handle for chimie log-file. */
#ifdef CHIMIE_STATS
extern FILE *FdChimieStatsSNs; /*!< file handle for chimie stats-file. */
extern FILE *FdChimieStatsGas; /*!< file handle for chimie stats-file. */
#endif
#endif
#ifdef MULTIPHASE
extern FILE *FdPhase; /*!< file handle for pase.txt log-file. */
extern FILE *FdSticky; /*!< file handle for sticky.txt log-file. */
#endif
#ifdef AGN_ACCRETION
extern FILE *FdAccretion; /*!< file handle for accretion.txt log-file. */
#endif
#ifdef BONDI_ACCRETION
extern FILE *FdBondi; /*!< file handle for bondi.txt log-file. */
#endif
#ifdef BUBBLES
extern FILE *FdBubble; /*!< file handle for bubble.txt log-file. */
#endif
#ifdef GAS_ACCRETION
extern FILE *FdGasAccretion; /*!< file handle for gas_accretion.txt log-file. */
#endif
#ifdef PERIODICOUTER
extern FILE *FdTrace; /*!< file handle for trace.txt log-file. */
#endif
extern double DriftTable[DRIFT_TABLE_LENGTH]; /*!< table for the cosmological drift factors */
extern double GravKickTable[DRIFT_TABLE_LENGTH]; /*!< table for the cosmological kick factor for gravitational forces */
extern double HydroKickTable[DRIFT_TABLE_LENGTH]; /*!< table for the cosmological kick factor for hydrodynmical forces */
#ifdef COSMICTIME
extern double CosmicTimeTable[COSMICTIME_TABLE_LENGTH]; /*!< table for the computation of cosmic time */
extern double FullCosmicTimeTable[COSMICTIME_TABLE_LENGTH]; /*!< table for the computation of cosmic time */
extern double FullCosmicTimeTableInv[COSMICTIME_TABLE_LENGTH]; /*!< table for the computation of cosmic time */
#endif
extern void *CommBuffer; /*!< points to communication buffer, which is used in the domain decomposition, the
parallel tree-force computation, the SPH routines, etc. */
/*! This structure contains data which is the SAME for all tasks (mostly code parameters read from the
* parameter file). Holding this data in a structure is convenient for writing/reading the restart file, and
* it allows the introduction of new global variables in a simple way. The only thing to do is to introduce
* them into this structure.
*/
extern struct global_data_all_processes
{
long long TotNumPart; /*!< total particle numbers (global value) */
long long TotN_gas; /*!< total gas particle number (global value) */
#ifdef GAS_ACCRETION
long long TotNumPart_acc;
long long TotN_gas_acc;
#endif
#ifdef HOT_HALO
long long TotNumPart_HaloAcc;
#endif
#ifdef PY_INTERFACE
long long TotNumPartQ; /*!< total particle numbers (global value) */
long long TotN_gasQ; /*!< total gas particle number (global value) */
int MaxPartQ; /*!< This gives the maxmimum number of particles that can be stored on one processor. */
int MaxPartSphQ; /*!< This gives the maxmimum number of SPH particles that can be stored on one processor. */
int BunchSizeSph;
int BunchSizeDensitySph;
double ForceSofteningQ;
#endif
#if defined(SFR) || defined(STELLAR_PROP)
long long TotN_stars; /*!< total stars particle number (global value) */
#endif
#ifdef MULTIPHASE
long long TotN_sph; /*!< total sph particle number (global value) */
long long TotN_sticky; /*!< total sticky particle number (global value) */
long long TotN_stickyflaged; /*!< total sticky flaged particle number (global value) */
long long TotN_stickyactive; /*!< total sticky active particle number (global value) */
long long TotN_dark; /*!< total dark particle number (global value) */
#endif
int MaxPart; /*!< This gives the maxmimum number of particles that can be stored on one processor. */
int MaxPartSph; /*!< This gives the maxmimum number of SPH particles that can be stored on one processor. */
#ifdef TESSEL
int MaxgPart;
#endif
#ifdef STELLAR_PROP
int MaxPartStars; /*!< This gives the maxmimum number of Star particles that can be stored on one processor. */
#endif
double BoxSize; /*!< Boxsize in case periodic boundary conditions are used */
int ICFormat; /*!< selects different versions of IC file-format */
int SnapFormat; /*!< selects different versions of snapshot file-formats */
int NumFilesPerSnapshot; /*!< number of files in multi-file snapshot dumps */
int NumFilesWrittenInParallel;/*!< maximum number of files that may be written simultaneously when
writing/reading restart-files, or when writing snapshot files */
int BufferSize; /*!< size of communication buffer in MB */
int BunchSizeForce; /*!< number of particles fitting into the buffer in the parallel tree-force algorithm */
int BunchSizeDensity; /*!< number of particles fitting into the communication buffer in the density computation */
int BunchSizeHydro; /*!< number of particles fitting into the communication buffer in the SPH hydrodynamical force computation */
int BunchSizeDomain; /*!< number of particles fitting into the communication buffer in the domain decomposition */
#ifdef MULTIPHASE
int BunchSizeSticky; /*!< number of particles fitting into the communication buffer in the Chimie computation */
#endif
#ifdef CHIMIE
int BunchSizeChimie; /*!< number of particles fitting into the communication buffer in the Chimie computation */
int BunchSizeStarsDensity; /*!< number of particles fitting into the communication buffer in the star density computation */
#endif
#ifdef SYNCHRONIZE_NGB_TIMESTEP
int BunchSizeSynchronizeNgBTimestep;
#endif
#ifdef DISSIPATION_FORCES
int BunchSizeDissipationForces;
#endif
#ifdef FOF
int BunchSizeFOF;
#endif
#ifdef TESSEL
int BunchSizeGhost;
#endif
double PartAllocFactor; /*!< in order to maintain work-load balance, the particle load will usually
NOT be balanced. Each processor allocates memory for PartAllocFactor times
the average number of particles to allow for that */
double TreeAllocFactor; /*!< Each processor allocates a number of nodes which is TreeAllocFactor times
the maximum(!) number of particles. Note: A typical local tree for N
particles needs usually about ~0.65*N nodes. */
#ifdef SFR
double StarsAllocFactor; /*!< Estimated fraction of gas particles that will form stars during the simulation
This allow to reduce the memory stored for stellar particles */
#endif
/* some SPH parameters */
double DesNumNgb; /*!< Desired number of SPH neighbours */
double MaxNumNgbDeviation; /*!< Maximum allowed deviation neighbour number */
double ArtBulkViscConst; /*!< Sets the parameter \f$\alpha\f$ of the artificial viscosity */
#ifdef ART_CONDUCTIVITY
double ArtCondConst; /*!< Sets the parameter \f$\alpha\f$ of the artificial conductivity */
double ArtCondThreshold;
#endif
double InitGasTemp; /*!< may be used to set the temperature in the IC's */
double MinGasTemp; /*!< may be used to set a floor for the gas temperature */
double MinEgySpec; /*!< the minimum allowed temperature expressed as energy per unit mass */
/* Usefull constants */
double Boltzmann;
double ProtonMass;
double mumh;
#ifdef COOLING
/* Cooling parameters */
double *logT;
double *logL;
gsl_interp_accel *acc_cooling_spline;
gsl_spline *cooling_spline;
double CoolingType;
#ifdef PYCOOL
char * CoolingFile;
#else
char CoolingFile[MAXLEN_FILENAME]; /*!< cooling file */
#endif
double CutofCoolingTemperature;
/*
new metal dependent cooling
*/
double CoolingParameters_zmin;
double CoolingParameters_zmax;
double CoolingParameters_slz;
double CoolingParameters_tmin;
double CoolingParameters_tmax;
double CoolingParameters_slt;
double CoolingParameters_FeHSolar;
double CoolingParameters_ZHSolar;
double CoolingParameters_cooling_data_max;
double CoolingParameters_cooling_data[COOLING_NMETALICITIES][COOLING_NTEMPERATURES];
int CoolingParameters_p;
int CoolingParameters_q;
#ifdef COOLING_WIERSMA
char CoolingDirectory[MAXLEN_FILENAME]; /*!< cooling directory */
#endif
#ifdef COOLING_GRACKLE
char GrackleCloudyTable[MAXLEN_FILENAME]; /*!< cooling cloudy table */
int GrackleUVbackground;
double GrackleRedshift;
#ifdef COOLING_GRACKLE_H_SSHIELDING
double GrackleHSShieldingDensityThreshold; /*!< Hydrogen self-shielding density threshold */
#endif
#endif
#ifdef COOLING_FCT_FROM_HDF5
// cooling tables loaded from HDF5 files
// (dimensions depend on the presence of nHe)
float*** COOLING_TABLES_METAL_FREE;
float** COOLING_TABLES_TOTAL_METAL;
float*** ELECTRON_DENSITY_OVER_N_H_TABLES;
float** ELECTRON_DENSITY_OVER_N_H_TABLES_SOLAR;
float* HYDROGEN_TABLES;
float* TEMPERATURE_TABLES;
float* HELIUM_ABOUNDANCE_TABLES;
//corresponding sizes
int SIZE_HYDROGEN_TABLES;
int SIZE_TEMPERATURE_TABLES;
int SIZE_HELIUM_ABOUNDANCE_TABLES;
// current redshift value determining the cooling file
// from which the data is interpolated
float CURRENT_TABLE_REDSHIFT;
#endif
#endif
#ifdef CHIMIE
int ChimieNumberOfParameterFiles;
#ifdef PYCHEM
char * ChimieParameterFile;
#else
char ChimieParameterFile[MAXLEN_FILENAME]; /*!< chimie parameter file */
#endif
double ChimieSupernovaEnergy;
double ChimieKineticFeedbackFraction;
double ChimieWindSpeed;
double ChimieWindTime;
double ChimieSNIaThermalTime;
double ChimieSNIIThermalTime;
double ChimieMaxSizeTimestep;
#ifdef CHIMIE_TIMEBET
double ChimieTimeBetChimie; /*!< simulation time interval between computations of Chimie */
double ChimieTimeLastChimie; /*!< simulation time when the Chimie was computed the last time */
double ChimieTi_begstep; /*!< start of chimie step */
#endif
#ifdef CHIMIE_ONE_SN_ONLY /*!< explode only one sn>*/
int ChimieOneSN;
double ChimieOneSNMass;
#endif
#if CHIMIE_EJECTA_RADIUS == 1
double ChimieEjectaRadius;
#endif
#endif
#if defined (CHIMIE) || defined (COOLING)
double InitGasMetallicity; /*!< initial gas metallicity>*/
double GasMetal; /*!< gas metal fraction, used when CHIMIE is disabled >*/
#endif
#if !defined (HEATING_PE)
double HeatingPeElectronFraction;
#endif
#if !defined (HEATING_PE) || defined (STELLAR_FLUX) || defined (EXTERNAL_FLUX)
double HeatingPeSolarEnergyDensity;
#endif
#if !defined (HEATING_PE) || defined (STELLAR_FLUX)
double HeatingPeLMRatioGas;
double HeatingPeLMRatioHalo;
double HeatingPeLMRatioDisk;
double HeatingPeLMRatioBulge;
double HeatingPeLMRatioStars;
double HeatingPeLMRatioBndry;
double HeatingPeLMRatio[6];
#endif
#ifdef EXTERNAL_FLUX
double HeatingExternalFLuxEnergyDensity;
#endif
#ifdef MULTIPHASE
double CriticalTemperature;
double CriticalEgySpec;
double CriticalNonCollisionalTemperature;
double CriticalNonCollisionalEgySpec;
#ifdef COLDGAS_CYCLE
double ColdGasCycleTransitionTime;
double ColdGasCycleTransitionParameter;
#endif
#endif
#ifdef MULTIPHASE
/* some STICKY parameters */
int StickyUseGridForCollisions;
double StickyTime; /*!< Cooling time of sticky particle collision */
double StickyCollisionTime;
double StickyLastCollisionTime;
double StickyIdleTime;
double StickyMinVelocity;
double StickyMaxVelocity;
int StickyGridNx;
int StickyGridNy;
int StickyGridNz;
double StickyGridXmin;
double StickyGridXmax;
double StickyGridYmin;
double StickyGridYmax;
double StickyGridZmin;
double StickyGridZmax;
double StickyLambda;
double StickyDensity;
double StickyDensityPower;
double StickyBetaR;
double StickyBetaT;
double StickyRsphFact; /*!< Fraction of the sph radius used in sticky particle */
#endif
#ifdef JEANS_PRESSURE_FLOOR
double JeansMassFactor;
#endif
#ifdef OUTERPOTENTIAL
#ifdef NFW
double HaloConcentration;
double HaloMass;
double GasMassFraction;
double NFWPotentialCte;
double Rs;
#endif
#ifdef PLUMMER
double PlummerMass;
double PlummerSoftenning;
double PlummerPotentialCte;
#endif
#ifdef HOMOSPHERE
double HomosphereMass;
double HomosphereMaxRadius;
double HomospherePotentialCte;
#endif
#ifdef MIYAMOTONAGAI
double MiyamotoNagaiMass;
double MiyamotoNagaiHr;
double MiyamotoNagaiHz;
double MiyamotoNagaiPotentialCte;
#endif
#ifdef PISOTHERM
double Rho0;
double Rc;
double PisothermPotentialCte;
double GasMassFraction;
double PotentialInf;
gsl_function PotentialF;
gsl_integration_workspace *Potentialw;
#endif
#ifdef CORIOLIS
double CoriolisOmegaX;
double CoriolisOmegaY;
double CoriolisOmegaZ;
double CoriolisOmegaX0;
double CoriolisOmegaY0;
double CoriolisOmegaZ0;
#endif
#endif
#ifdef SFR
int StarFormationNStarsFromGas;
double StarFormationStarMass;
double StarFormationMgMsFraction;
int StarFormationType;
double StarFormationCstar;
double StarFormationTime;
double StarFormationDensity;
double StarFormationTemperature;
double ThresholdDensity;
#ifndef LONGIDS
unsigned int MaxID; /* max value of ID, this is used to set id of new stars */
#else
unsigned long long MaxID; /* max value of ID, this is used to set id of new stars */
#endif
#ifdef SFR_USE_JEANS
double StarformationSofteningMaxPhys;
double StarformationSoftening;
double StarformationJeansMassFactor;
#endif
#endif /* SFR */
#ifdef FOF
double FoF_ThresholdDensity; /* threshold density : particles with density below FoF_ThresholdDensity are excluded from the FoF */
double FoF_MinHeadDensity; /* keep only heads with density higher than this value */
double FoF_Density;
double FoF_ThresholdDensityFactor;
double FoF_MinHeadDensityFactor;
int FoF_MinGroupMembers; /* minimum members required to form stars */
double FoF_MinGroupMass; /* minimum mass required to form stars (in solar mass) */
double FoF_VirialFractionThreshold; /* virial fraction value, below which a group is assumed to be bound */
double FoF_HsmlSearchRadiusFactor; /* friends are search in a radius given by hsml time this factor */
double FoF_HsmlMaxDistFactor; /* a particle may be linked to a head only if ``r < Hsml*FoF_HsmlMaxDistFactor``*/
int FoF_StarFormationType; /*!< allow to tune the sfr in FOF */
double FoF_TimeBetFoF; /*!< simulation time interval between computations of FoF */
double FoF_TimeLastFoF; /*!< simulation time when the FoF was computed the last time */
int FoF_SnapshotFileCount; /*!< number of snapshot that is written next */
char FoF_SnapshotFileBase[MAXLEN_FILENAME]; /*!< basename to construct the names of snapshotf files */
#endif
#ifdef FEEDBACK
double SupernovaTime;
#endif
#ifdef FEEDBACK_WIND
double SupernovaWindEgySpecPerMassUnit;
double SupernovaWindFractionInEgyKin;
double SupernovaWindParameter;
double SupernovaWindSpeed;
double SupernovaWindIntAccuracy;
#endif
#ifdef AGN_ACCRETION
double TimeBetAccretion;
double AccretionRadius;
double AGNFactor;
double MinMTotInRa;
double TimeLastAccretion;
double LastMTotInRa;
double MTotInRa;
double dMTotInRa;
#endif
#ifdef BUBBLES
char BubblesInitFile[MAXLEN_FILENAME]; /*!< bubble file */
double *BubblesTime;
double *BubblesD;
double *BubblesR;
double *BubblesE;
double *BubblesA;
double *BubblesB;
int BubblesIndex;
double BubblesAlpha;
double BubblesBeta;
double BubblesDelta;
double BubblesRadiusFactor;
double EnergyBubbles;
#endif
#ifdef AGN_HEATING
double AGNHeatingPower;
double AGNHeatingRmax;
#endif
#ifdef BONDI_ACCRETION
double BondiEfficiency;
double BondiBlackHoleMass;
double BondiHsmlFactor;
double BondiPower;
double BondiTimeBet;
double BondiTimeLast;
#endif
#if defined (AGN_ACCRETION) || defined (BONDI_ACCRETION)
double LightSpeed;
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO) || defined(ART_VISCO_CD)
double ArtBulkViscConstMin;
double ArtBulkViscConstMax;
double ArtBulkViscConstL;
#endif
#ifdef METAL_DIFFUSION
double MetalDiffusionConst;
#endif
#ifdef AB_TURB
double StDecay;
double StEnergy;
double StDtFreq;
double StKmin;
double StKmax;
double StSolWeight;
double StAmplFac;
int StSpectForm;
int StSeed;
#endif
#ifdef GAS_ACCRETION
double AccretionParticleMass[6];
#endif
#ifdef SYNCHRONIZE_NGB_TIMESTEP
int NgbFactorTimestep;
#endif
/* some force counters */
long long TotNumOfForces; /*!< counts total number of force computations */
long long NumForcesSinceLastDomainDecomp; /*!< count particle updates since last domain decomposition */
/* system of units */
double G; /*!< Gravity-constant in internal units */
double UnitTime_in_s; /*!< factor to convert internal time unit to seconds/h */
double UnitMass_in_g; /*!< factor to convert internal mass unit to grams/h */
double UnitVelocity_in_cm_per_s; /*!< factor to convert intqernal velocity unit to cm/sec */
double UnitLength_in_cm; /*!< factor to convert internal length unit to cm/h */
double UnitPressure_in_cgs; /*!< factor to convert internal pressure unit to cgs units (little 'h' still around!) */
double UnitDensity_in_cgs; /*!< factor to convert internal length unit to g/cm^3*h^2 */
double UnitCoolingRate_in_cgs; /*!< factor to convert internal cooling rate to cgs units */
double UnitEnergy_in_cgs; /*!< factor to convert internal energy to cgs units */
double UnitTime_in_Megayears; /*!< factor to convert internal time to megayears/h */
double GravityConstantInternal; /*!< If set to zero in the parameterfile, the internal value of the
gravitational constant is set to the Newtonian value based on the system of
units specified. Otherwise the value provided is taken as internal gravity constant G. */
/* Cosmological parameters */
double Hubble; /*!< Hubble-constant in internal units */
double Omega0; /*!< matter density in units of the critical density (at z=0)*/
double OmegaLambda; /*!< vaccum energy density relative to crictical density (at z=0) */
double OmegaBaryon; /*!< baryon density in units of the critical density (at z=0)*/
double HubbleParam; /*!< little `h', i.e. Hubble constant in units of 100 km/s/Mpc. Only needed to get absolute physical values for cooling physics */
#ifdef HUBBLE_PARAM_WHEN_NOT_IN_UNITS
double HubbleParamNIU; /*!< little `h', i.e. Hubble constant in units of 100 km/s/Mpc. Only needed to get redshift when physical units are used */
#endif
/* Code options */
int ComovingIntegrationOn; /*!< flags that comoving integration is enabled */
int PeriodicBoundariesOn; /*!< flags that periodic boundaries are enabled */
int ResubmitOn; /*!< flags that automatic resubmission of job to queue system is enabled */
int TypeOfOpeningCriterion; /*!< determines tree cell-opening criterion: 0 for Barnes-Hut, 1 for relative criterion */
int TypeOfTimestepCriterion; /*!< gives type of timestep criterion (only 0 supported right now - unlike gadget-1.1) */
int OutputListOn; /*!< flags that output times are listed in a specified file */
/* Parameters determining output frequency */
int SnapshotFileCount; /*!< number of snapshot that is written next */
double TimeBetSnapshot; /*!< simulation time interval between snapshot files */
double TimeOfFirstSnapshot; /*!< simulation time of first snapshot files */
double CpuTimeBetRestartFile; /*!< cpu-time between regularly generated restart files */
double TimeLastRestartFile; /*!< cpu-time when last restart-file was written */
double TimeBetStatistics; /*!< simulation time interval between computations of energy statistics */
double TimeLastStatistics; /*!< simulation time when the energy statistics was computed the last time */
int NumCurrentTiStep; /*!< counts the number of system steps taken up to this point */
/* Current time of the simulation, global step, and end of simulation */
double Time; /*!< current time of the simulation */
double TimeBegin; /*!< time of initial conditions of the simulation */
double TimeStep; /*!< difference between current times of previous and current timestep */
double TimeMax; /*!< marks the point of time until the simulation is to be evolved */
/* variables for organizing discrete timeline */
double Timebase_interval; /*!< factor to convert from floating point time interval to integer timeline */
int Ti_Current; /*!< current time on integer timeline */
int Ti_nextoutput; /*!< next output time on integer timeline */
#ifdef FLEXSTEPS
int PresentMinStep; /*!< If FLEXSTEPS is used, particle timesteps are chosen as multiples of the present minimum timestep. */
int PresentMaxStep; /*!< If FLEXSTEPS is used, this is the maximum timestep in timeline units, rounded down to the next power 2 division */
#endif
#ifdef PMGRID
int PM_Ti_endstep; /*!< begin of present long-range timestep */
int PM_Ti_begstep; /*!< end of present long-range timestep */
#endif
/* Placement of PM grids */
#ifdef PMGRID
double Asmth[2]; /*!< Gives the scale of the long-range/short-range split (in mesh-cells), both for the coarse and the high-res mesh */
double Rcut[2]; /*!< Gives the maximum radius for which the short-range force is evaluated with the tree (in mesh-cells), both for the coarse and the high-res mesh */
double Corner[2][3]; /*!< lower left corner of coarse and high-res PM-mesh */
double UpperCorner[2][3]; /*!< upper right corner of coarse and high-res PM-mesh */
double Xmintot[2][3]; /*!< minimum particle coordinates both for coarse and high-res PM-mesh */
double Xmaxtot[2][3]; /*!< maximum particle coordinates both for coarse and high-res PM-mesh */
double TotalMeshSize[2]; /*!< total extension of coarse and high-res PM-mesh */
#endif
/* Variables that keep track of cumulative CPU consumption */
double TimeLimitCPU; /*!< CPU time limit as defined in parameterfile */
double CPU_TreeConstruction; /*!< time spent for constructing the gravitational tree */
double CPU_TreeWalk; /*!< actual time spent for pure tree-walks */
double CPU_Gravity; /*!< cumulative time used for gravity computation (tree-algorithm only) */
double CPU_Potential; /*!< time used for computing gravitational potentials */
double CPU_Domain; /*!< cumulative time spent for domain decomposition */
double CPU_Snapshot; /*!< time used for writing snapshot files */
double CPU_Total; /*!< cumulative time spent for domain decomposition */
double CPU_CommSum; /*!< accumulated time used for communication, and for collecting partial results, in tree-gravity */
double CPU_Imbalance; /*!< cumulative time lost accross all processors as work-load imbalance in gravitational tree */
double CPU_HydCompWalk; /*!< time used for actual SPH computations, including neighbour search */
double CPU_HydCommSumm; /*!< cumulative time used for communication in SPH, and for collecting partial results */
double CPU_HydImbalance; /*!< cumulative time lost due to work-load imbalance in SPH */
double CPU_Hydro; /*!< cumulative time spent for SPH related computations */
#ifdef SFR
double CPU_StarFormation; /*!< cumulative time spent for star formation computations */
#endif
#ifdef CHIMIE
double CPU_Chimie; /*!< cumulative time spent for chimie computations */
double CPU_ChimieDensCompWalk;
double CPU_ChimieDensCommSumm;
double CPU_ChimieDensImbalance;
double CPU_ChimieDensEnsureNgb;
double CPU_ChimieCompWalk;
double CPU_ChimieCommSumm;
double CPU_ChimieImbalance;
#endif
#ifdef MULTIPHASE
double CPU_Sticky; /*!< cumulative time spent for sticky computations */
#endif
double CPU_EnsureNgb; /*!< time needed to iterate on correct neighbour numbers */
double CPU_Predict; /*!< cumulative time to drift the system forward in time, including dynamic tree updates */
double CPU_TimeLine; /*!< time used for determining new timesteps, and for organizing the timestepping, including kicks of active particles */
double CPU_PM; /*!< time used for long-range gravitational force */
double CPU_Peano; /*!< time required to establish Peano-Hilbert order */
#ifdef DETAILED_CPU_DOMAIN
double CPU_Domain_findExtend;
double CPU_Domain_determineTopTree;
double CPU_Domain_sumCost;
double CPU_Domain_findSplit;
double CPU_Domain_shiftSplit;
double CPU_Domain_countToGo;
double CPU_Domain_exchange;
#endif
#ifdef DETAILED_CPU_GRAVITY
double CPU_Gravity_TreeWalk1;
double CPU_Gravity_TreeWalk2;
double CPU_Gravity_CommSum1;
double CPU_Gravity_CommSum2;
double CPU_Gravity_Imbalance1;
double CPU_Gravity_Imbalance2;
#endif
#ifdef COOLING
double CPU_Cooling;
#endif
#ifdef DETAILED_CPU
double CPU_Leapfrog;
double CPU_Physics;
double CPU_Residual;
double CPU_Accel;
double CPU_Begrun;
#endif
/* tree code opening criterion */
double ErrTolTheta; /*!< BH tree opening angle */
double ErrTolForceAcc; /*!< parameter for relative opening criterion in tree walk */
/* adjusts accuracy of time-integration */
double ErrTolIntAccuracy; /*!< accuracy tolerance parameter \f$ \eta \f$ for timestep criterion. The
timestep is \f$ \Delta t = \sqrt{\frac{2 \eta eps}{a}} \f$ */
double MinSizeTimestep; /*!< minimum allowed timestep. Normally, the simulation terminates if the
timestep determined by the timestep criteria falls below this limit. */
double MaxSizeTimestep; /*!< maximum allowed timestep */
double MaxRMSDisplacementFac; /*!< this determines a global timestep criterion for cosmological simulations
in comoving coordinates. To this end, the code computes the rms velocity
of all particles, and limits the timestep such that the rms displacement
is a fraction of the mean particle separation (determined from the
particle mass and the cosmological parameters). This parameter specifies
this fraction. */
double CourantFac; /*!< SPH-Courant factor */
/* frequency of tree reconstruction/domain decomposition */
double TreeDomainUpdateFrequency; /*!< controls frequency of domain decompositions */
/* Gravitational and hydrodynamical softening lengths (given in terms of an `equivalent' Plummer softening length).
* Five groups of particles are supported 0="gas", 1="halo", 2="disk", 3="bulge", 4="stars", 5="bndry"
*/
double MinGasHsmlFractional; /*!< minimum allowed SPH smoothing length in units of SPH gravitational softening length */
double MinGasHsml; /*!< minimum allowed SPH smoothing length */
double SofteningGas; /*!< comoving gravitational softening lengths for type 0 */
double SofteningHalo; /*!< comoving gravitational softening lengths for type 1 */
double SofteningDisk; /*!< comoving gravitational softening lengths for type 2 */
double SofteningBulge; /*!< comoving gravitational softening lengths for type 3 */
double SofteningStars; /*!< comoving gravitational softening lengths for type 4 */
double SofteningBndry; /*!< comoving gravitational softening lengths for type 5 */
double SofteningGasMaxPhys; /*!< maximum physical softening length for type 0 */
double SofteningHaloMaxPhys; /*!< maximum physical softening length for type 1 */
double SofteningDiskMaxPhys; /*!< maximum physical softening length for type 2 */
double SofteningBulgeMaxPhys; /*!< maximum physical softening length for type 3 */
double SofteningStarsMaxPhys; /*!< maximum physical softening length for type 4 */
double SofteningBndryMaxPhys; /*!< maximum physical softening length for type 5 */
double SofteningTable[6]; /*!< current (comoving) gravitational softening lengths for each particle type */
double ForceSoftening[6]; /*!< the same, but multiplied by a factor 2.8 - at that scale the force is Newtonian */
double MassTable[6]; /*!< Table with particle masses for particle types with equal mass.
If particle masses are all equal for one type, the corresponding entry in MassTable
is set to this value, allowing the size of the snapshot files to be reduced. */
/* some filenames */
char InitCondFile[MAXLEN_FILENAME]; /*!< filename of initial conditions */
char OutputDir[MAXLEN_FILENAME]; /*!< output directory of the code */
char SnapshotFileBase[MAXLEN_FILENAME]; /*!< basename to construct the names of snapshotf files */
char EnergyFile[MAXLEN_FILENAME]; /*!< name of file with energy statistics */
#ifdef SYSTEMSTATISTICS
char SystemFile[MAXLEN_FILENAME];
#endif
char CpuFile[MAXLEN_FILENAME]; /*!< name of file with cpu-time statistics */
char InfoFile[MAXLEN_FILENAME]; /*!< name of log-file with a list of the timesteps taken */
char LogFile[MAXLEN_FILENAME]; /*!< name of log-file with varied info */
#ifdef SFR
char SfrFile[MAXLEN_FILENAME]; /*!< name of file with sfr records */
#endif
#ifdef CHIMIE
char ChimieFile[MAXLEN_FILENAME]; /*!< name of file with chimie records */
#endif
#ifdef MULTIPHASE
char PhaseFile[MAXLEN_FILENAME]; /*!< name of file with phase records */
char StickyFile[MAXLEN_FILENAME]; /*!< name of file with sticky records */
#endif
#ifdef AGN_ACCRETION
char AccretionFile[MAXLEN_FILENAME]; /*!< name of file with accretion records */
#endif
#ifdef BONDI_ACCRETION
char BondiFile[MAXLEN_FILENAME]; /*!< name of file with bondi records */
#endif
#ifdef BUBBLES
char BubbleFile[MAXLEN_FILENAME]; /*!< name of file with bubble records */
#endif
#ifdef GAS_ACCRETION
char GasAccretionFile[MAXLEN_FILENAME]; /*!< name of file with sfr records */
#endif
char TimingsFile[MAXLEN_FILENAME]; /*!< name of file with performance metrics of gravitational tree algorithm */
char RestartFile[MAXLEN_FILENAME]; /*!< basename of restart-files */
char ResubmitCommand[MAXLEN_FILENAME]; /*!< name of script-file that will be executed for automatic restart */
char OutputListFilename[MAXLEN_FILENAME]; /*!< name of file with list of desired output times */
double OutputListTimes[MAXLEN_OUTPUTLIST]; /*!< table with desired output times */
int OutputListLength; /*!< number of output times stored in the table of desired output times */
#ifdef RANDOMSEED_AS_PARAMETER
int RandomSeed; /*!< initial random seed >*/
#endif
#ifdef PERIODICOUTER
char TraceFile[MAXLEN_FILENAME];
double TracePos[3]; //trace particle position
double TraceVel[3]; //trace particle velocity
double TraceAcc[3]; //trace particle acceleration
double TracePeriodPos[3]; //trace particle position in periodic box
FLOAT TraceAngOld[3];
FLOAT TraceTheta;
FLOAT TracePotential;
double TraceAngular[4]; //trace particle Angular velocity
double TraceQuat[4]; //Trace quaternion
double TraceQuatConj[4]; //Easiest to store conjugate here to save repetitive calculation
FLOAT QuatOrig[4]; //Need an arbitrary direction of 0 theta, define it when velocity is -y
int InertialV;
#ifdef TRACE_ACC
#ifndef LONGIDS
unsigned int TraceMinPot[NUMTRACEAVG]; //Get minimum potential particle originally
#else
unsigned long long TraceMinPot[NUMTRACEAVG];
#endif
#endif
#endif
#ifdef HOT_HALO
double HaloT; //Halo Temperature
double HaloPartMass; //Halo particle mass
double HaloScaleFactor; //Halo scale factor (the value at 0)
FLOAT Halocs; //Halo soundspeed
FLOAT HaloLast;
double HaloAccYBound;
#endif
#ifdef MERGE_SPLIT
double Dwarf_Split_Merge_Distance; //Distance to count as hsml for dwarf particles
int SplitThreshold;
int MergeThreshold;
int nZones;
int split_method;
double MinMassForParticleSplit[6];
double MaxMassForParticleMerger[6];
#ifndef LONGIDS
unsigned int MergeID; /*!< particle identifier */
#else
unsigned long long MergeID; /*!< particle identifier */
#endif
#endif
#if defined(CHIMIE) || defined(FOF)
double CMUtoMsol; /*!< convertion factor from Code Mass Unit to Solar Mass >*/
double MsoltoCMU; /*!< convertion factor from Solar Mass to Code Mass Unit >*/
#endif
#ifdef COMPUTE_PHYSICAL_UNITS
double CDUtoAtomPerCC; /*!< convertion factor from Code Density Unit to Atom per CC >*/
#endif
}
All; /*!< a container variable for global variables that are equal on all processors */
/*! This structure holds all the information that is
* stored for each particle of the simulation.
*/
extern struct particle_data
{
FLOAT Pos[3]; /*!< particle position at its current time */
FLOAT Mass; /*!< particle mass */
FLOAT Vel[3]; /*!< particle velocity at its current time */
FLOAT GravAccel[3]; /*!< particle acceleration due to gravity */
#ifdef PMGRID
FLOAT GravPM[3]; /*!< particle acceleration due to long-range PM gravity force*/
#endif
#ifdef FORCETEST
FLOAT GravAccelDirect[3]; /*!< particle acceleration when computed with direct summation */
#endif
FLOAT Potential; /*!< gravitational potential */
FLOAT OldAcc; /*!< magnitude of old gravitational force. Used in relative opening criterion */
#ifndef LONGIDS
unsigned int ID; /*!< particle identifier */
#else
unsigned long long ID; /*!< particle identifier */
#endif
int Type; /*!< flags particle type. 0=gas, 1=halo, 2=disk, 3=bulge, 4=stars, 5=bndry */
int Ti_endstep; /*!< marks start of current timestep of particle on integer timeline */
int Ti_begstep; /*!< marks end of current timestep of particle on integer timeline */
#ifdef SYNCHRONIZE_NGB_TIMESTEP
int Old_Ti_endstep; /*!< marks start of old current timestep of particle on integer timeline */
int Old_Ti_begstep; /*!< marks end of old current timestep of particle on integer timeline */
#endif
#ifdef FLEXSTEPS
int FlexStepGrp; /*!< a random 'offset' on the timeline to create a smooth groouping of particles */
#endif
float GravCost; /*!< weight factor used for balancing the work-load */
#ifdef PSEUDOSYMMETRIC
float AphysOld; /*!< magnitude of acceleration in last timestep. Used to make a first order
prediction of the change of acceleration expected in the future, thereby
allowing to guess whether a decrease/increase of the timestep should occur
in the timestep that is started. */
#endif
#ifdef PARTICLE_FLAG
float Flag;
#endif
#ifdef STELLAR_PROP
unsigned int StPIdx; /*!< index to the corresponding StP particle */
#endif
#ifdef TESSEL
int iT; /*!< index of a triangle to which the point belong to */
int IsDone;
int IsAdded; /*!< if the point has already be added in the tesselation */
int ivPoint; /*!< index of first voronoi point */
int nvPoints; /*!< number of voronoi points */
int iMedian;
int nMedians;
double Volume;
double Density;
double Pressure;
double Entropy;
double rSearch; /*!< radius in which particles must search for ngbs */
int iPref; /*!< for a ghost point, index of the reference point */
FLOAT tesselAccel[3];
#endif
# ifdef SYNCHRONIZE_NGB_TIMESTEP
int Ti_step;
#endif
#ifdef VANISHING_PARTICLES
int VanishingFlag;
#endif
#ifdef FOF_SFR
//int FoFidx; /* no longer used */
#endif
}
*P, /*!< holds particle data on local processor */
#ifdef PY_INTERFACE
*Q,
*DomainPartBufQ, /*!< buffer for particle data used in domain decomposition */
#endif
*DomainPartBuf; /*!< buffer for particle data used in domain decomposition */
/* the following struture holds data that is stored for each SPH particle in addition to the collisionless
* variables.
*/
extern struct sph_particle_data
{
FLOAT Entropy; /*!< current value of entropy (actually entropic function) of particle */
FLOAT Density; /*!< current baryonic mass density of particle */
FLOAT Hsml; /*!< current smoothing length */
FLOAT Left; /*!< lower bound in iterative smoothing length search */
FLOAT Right; /*!< upper bound in iterative smoothing length search */
FLOAT NumNgb; /*!< weighted number of neighbours found */
#ifdef AVOIDNUMNGBPROBLEM
FLOAT OldNumNgb;
#endif
FLOAT Pressure; /*!< current pressure */
FLOAT DtEntropy; /*!< rate of change of entropy */
#ifdef COOLING
//FLOAT EntropyRad; /*!< current value of entropy resulting from the cooling */
FLOAT DtEntropyRad; /*!< rate of change of entropy due to cooling */
FLOAT DtEnergyRad;
#endif
#ifdef STELLAR_FLUX
FLOAT EnergyFlux; /*!< current value of local energy flux - Sph particles */
#endif
#ifdef AGN_HEATING
FLOAT EgySpecAGNHeat; /*!< current value of specific energy radiated of particle - Sph particles */
FLOAT DtEgySpecAGNHeat; /*!< rate of change of specific radiated energy - Sph particles */
FLOAT DtEntropyAGNHeat;
#endif
#ifdef MULTIPHASE
FLOAT StickyTime;
int StickyFlag;
#ifdef COUNT_COLLISIONS
float StickyCollisionNumber;
#endif
#endif
#ifdef FEEDBACK
FLOAT EgySpecFeedback;
FLOAT DtEgySpecFeedback;
FLOAT EnergySN;
FLOAT EnergySNrem;
FLOAT TimeSN;
FLOAT FeedbackVel[3]; /*!< kick due to feedback force */
#endif
#ifdef FEEDBACK_WIND
FLOAT FeedbackWindVel[3]; /*!< kick due to feedback force */
#endif
FLOAT HydroAccel[3]; /*!< acceleration due to hydrodynamical force */
FLOAT VelPred[3]; /*!< predicted SPH particle velocity at the current time */
FLOAT DivVel; /*!< local velocity divergence */
FLOAT CurlVel; /*!< local velocity curl */
FLOAT Rot[3]; /*!< local velocity curl */
FLOAT DhsmlDensityFactor; /*!< correction factor needed in the equation of motion of the conservative entropy formulation of SPH */
FLOAT MaxSignalVel; /*!< maximum "signal velocity" occuring for this particle */
#ifdef MULTIPHASE
int Phase;
int StickyIndex;
int StickyNgb;
int StickyMaxID;
float StickyMaxFs;
FLOAT StickyNewVel[3];
#endif
#ifdef OUTPUTOPTVAR1
FLOAT OptVar1; /*!< optional variable 1 */
#endif
#ifdef OUTPUTOPTVAR2
FLOAT OptVar2; /*!< optional variable 2 */
#endif
#ifdef COMPUTE_VELOCITY_DISPERSION
FLOAT VelocityDispersion[VELOCITY_DISPERSION_SIZE]; /*!< velocity dispersion */
#endif
#ifdef CHIMIE
FLOAT Metal[NELEMENTS];
#ifdef CHIMIE_SMOOTH_METALS
FLOAT MassMetal[NELEMENTS]; /*!< old metal estimation (ratio of masses) */
FLOAT RhoMetal[NELEMENTS]; /*!< metal density of the particle */
#endif
FLOAT dMass; /*!< mass variation due to mass transfere */
#ifdef CHIMIE_THERMAL_FEEDBACK
FLOAT DeltaEgySpec;
FLOAT SNIaThermalTime; /*!< flag particles that got energy from SNIa */
FLOAT SNIIThermalTime; /*!< flag particles that got energy from SNII */
double NumberOfSNIa;
double NumberOfSNII;
#endif
#ifdef CHIMIE_KINETIC_FEEDBACK
FLOAT WindTime; /*!< flag particles that belongs to the wind */
unsigned int WindFlag; /*!< flag particles that will be part of the wind */
#endif
#endif /*CHIMIE*/
#ifdef ENTROPYPRED
FLOAT EntropyPred; /*!< predicted entropy at the current time */
#endif
#ifdef ART_CONDUCTIVITY
FLOAT EnergyIntPred;
FLOAT GradEnergyInt[3];
#endif
#ifdef AB_TURB
FLOAT TurbAccel[3];
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO) || defined(ART_VISCO_CD)
double ArtBulkViscConst;
#ifdef ART_VISCO_CD
double DmatCD[3][3];
double TmatCD[3][3];
double DiVelAccurate;
double DiVelTemp;
double ArtBulkViscConstOld;
double R_CD;
FLOAT MaxSignalVelCD;
#endif
#endif
#ifdef GAS_ACCRETION
int ActiveFlag;
#endif
#ifdef DISSIPATION_FORCES
FLOAT EnergyDissipationForces;
FLOAT DtEnergyDissipationForces;
FLOAT DissipationForcesAccel[3];
#endif
#if PY_INTERFACE
FLOAT Observable;
FLOAT ObsMoment0;
FLOAT ObsMoment1;
FLOAT GradObservable[3];
#endif
# ifdef SYNCHRONIZE_NGB_TIMESTEP
int Ti_minNgbStep;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
FLOAT FeedbackUpdatedAccel[3]; /*!< acceleration after feedback injection */
FLOAT MaxSignalVelFeedbackUpdated;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
FLOAT EgyWtDensity; /*!< 'effective' rho to use in hydro equations */
FLOAT EntVarPred; /*!< predicted entropy variable */
FLOAT DhsmlEgyDensityFactor; /*!< correction factor for density-independent entropy formulation */
#endif
#ifdef FOF
int FOF_CPUHead; /*!< cpu ID of the first particle of the chain */
int FOF_CPUTail; /*!< cpu ID of the last particle of the chain */
int FOF_CPUNext; /*!< cpu ID of the next particle of the chain */
int FOF_CPUPrev; /*!< cpu ID of the previous particle of the chain */
int FOF_Head; /*!< first particle of the chain */
int FOF_Tail; /*!< last particle of the chain */
int FOF_Next; /*!< next particle in the chain */
int FOF_Prev; /*!< previous particle in the chain */
int FOF_gid; /*!< group id */
int FOF_Len; /*!< length of the chain */
int FOF_Done; /*!< the particle is done (used for pseudo heads) */
FLOAT FOF_DensMax;
FLOAT FOF_MassMax;
FLOAT FOF_MassMin;
FLOAT FOF_MassSSP;
FLOAT FOF_NStars;
#ifdef CHIMIE_OPTIMAL_SAMPLING
FLOAT OptIMF_k;
FLOAT OptIMF_CurrentMass;
#endif
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
FLOAT RmsSpeed;
+#endif
+
+#ifdef METAL_DIFFUSION
FLOAT MetalDiffusionCoeff;
FLOAT MetalDiffusionA;
FLOAT MetalDiffusionB[NELEMENTS];
#endif
+
+
}
*SphP, /*!< holds SPH particle data on local processor */
#ifdef PY_INTERFACE
*SphQ,
*DomainSphBufQ, /*!< buffer for SPH particle data in domain decomposition */
#endif
*DomainSphBuf; /*!< buffer for SPH particle data in domain decomposition */
#ifdef FOF
extern struct fof_particles_in
{
FLOAT Mass;
FLOAT MassNew;
FLOAT MassMax;
FLOAT MassMin;
FLOAT MassSSP;
FLOAT k;
FLOAT Pos[3];
int NStars;
int ID;
int Index;
int Task;
}
*FoF_P,*FoF_P_local;
extern struct fof_groups_data
{
int Index; /*!< group index (used when the group is send) */
int Head; /*!< head index */
int HeadID; /*!< head id, -1 if the head is not local */
int LocalHead; /*!< index to local head */
int Task; /*!< task hosting the true head */
int N; /*!< number of members */
int Nlocal; /*!< number of local members */
float Mass; /*!< total mass */
float MassCenter[3]; /*!< mass center */
float DensityMax; /*!< density max */
float DensityMin; /*!< density min */
float PotentialMax; /*!< potential max */
float VirialFraction; /*!< virial fraction 2(T+U)/W */
float MV[3];
float MV2[3];
float RadiusMax;
float K;
float W;
float U;
float T;
float Density;
float HeadPos[3];
float HeadPotential;
int SfrFlag;
}
*Groups,*GroupsGet,*GroupsRecv;
extern int *Tot_HeadID_list;
extern int Tot_Ngroups;
extern int Tot_Ntgroups;
extern int Tot_Npgroups;
extern int Tot_Ntsfrgroups;
extern int Ngroups; /* true and pseudo groups */
extern int Ntgroups; /* true groups */
extern int Npgroups; /* pseudo groups */
extern int Ntsfrgroups; /* true groups that forms stars */
extern int Nsfrgroups; /* local number of groups flagged for sfr */
extern int Tot_Nsfrgroups; /* total number of groups flagged for sfr */
#endif
#ifdef GAS_ACCRETION
extern struct acc_particle_data
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Mass;
FLOAT Time;
int Type;
int ID;
}
*Acc;
extern struct gas_acc_particle_data
{
FLOAT Entropy;
#ifdef CHIMIE
FLOAT Metal[NELEMENTS];
#endif
}
*SphAcc;
#endif
#ifdef HOT_HALO
extern struct haloacc_pos_data
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Mass;
FLOAT Time;
int Type;
int ID;
}
*HaloAcc;
#endif
#ifdef TRACE_ACC
extern struct pot_index
{
FLOAT Potential;
#ifndef LONGIDS
unsigned int ID;
#else
unsigned long long ID;
#endif
int index;
}
*PotInd;
#endif
#ifdef STELLAR_PROP
/* the following struture holds data that is stored for each SPH particle in addition to the collisionless
* variables.
*/
extern struct st_particle_data
{
#ifdef CHECK_ID_CORRESPONDENCE
unsigned int ID; /*!< particle identifier (must be the same as P[].ID) only used to check ID correspondance */
#endif
FLOAT FormationTime; /*!< star formation time of particle */
FLOAT InitialMass; /*!< initial stellar mass */
#ifndef LONGIDS
unsigned int IDProj; /*!< id of projenitor particle */
#else
unsigned long long IDProj; /*!< id of projenitor particle */
#endif
FLOAT Metal[NELEMENTS];
FLOAT Density; /*!< current baryonic mass density of particle */
FLOAT Y; /*!< elements weighting normalisation */
FLOAT Hsml; /*!< current smoothing length */
FLOAT Left; /*!< lower bound in iterative smoothing length search */
FLOAT Right; /*!< upper bound in iterative smoothing length search */
FLOAT NumNgb; /*!< weighted number of neighbours found */
unsigned int PIdx; /*!< index to the corresponding particle */
#ifdef AVOIDNUMNGBPROBLEM
FLOAT OldNumNgb;
#endif
FLOAT DhsmlDensityFactor; /*!< correction factor needed in the equation of motion of the conservative entropy formulation of SPH */
double TotalEjectedGasMass;
double TotalEjectedEltMass[NELEMENTS];
double TotalEjectedEgySpec;
double NumberOfSNIa;
double NumberOfSNII;
#ifdef CHIMIE_KINETIC_FEEDBACK
double NgbMass; /*!< mass of neighbours */
#endif
#ifdef CHIMIE
unsigned int Flag;
#endif
#ifdef CHIMIE_OPTIMAL_SAMPLING
float OptIMF_CurrentMass;
int OptIMF_N_WD;
float OptIMF_k; /*!< kroupa normalization */
float OptIMF_m_max; /*!< max mass of star in the "cluster">*/
#endif
#ifdef FOF_SFR
FLOAT MassMax; /*!< maximal stellar mass contained by the particle */
FLOAT MassMin; /*!< minimal stellar mass contained by the particle */
FLOAT MassSSP; /*!< mass of the total SSP */
int NStars; /*!< number of stars contained by the particle. If =-1, the particle represents a portion of the IMF */
#endif
#if CHIMIE_EJECTA_RADIUS == 2
FLOAT Pressure;
#endif
}
*StP, /*!< holds ST particle data on local processor */
*DomainStBuf; /*!< buffer for ST particle data in domain decomposition */
#endif
/* Variables for Tree
*/
extern int MaxNodes; /*!< maximum allowed number of internal nodes */
extern int Numnodestree; /*!< number of (internal) nodes in each tree */
extern struct NODE
{
FLOAT len; /*!< sidelength of treenode */
FLOAT center[3]; /*!< geometrical center of node */
#ifdef ADAPTIVE_GRAVSOFT_FORGAS
FLOAT maxsoft; /*!< hold the maximum gravitational softening of particles in the
node if the ADAPTIVE_GRAVSOFT_FORGAS option is selected */
#endif
#ifdef STELLAR_FLUX
FLOAT starlum ; /*!< star luminosity of node */
#endif
union
{
int suns[8]; /*!< temporary pointers to daughter nodes */
struct
{
FLOAT s[3]; /*!< center of mass of node */
FLOAT mass; /*!< mass of node */
int bitflags; /*!< a bit-field with various information on the node */
int sibling; /*!< this gives the next node in the walk in case the current node can be used */
int nextnode; /*!< this gives the next node in case the current node needs to be opened */
int father; /*!< this gives the parent node of each node (or -1 if we have the root node) */
}
d;
}
u;
}
*Nodes_base, /*!< points to the actual memory allocted for the nodes */
*Nodes; /*!< this is a pointer used to access the nodes which is shifted such that Nodes[All.MaxPart]
gives the first allocated node */
extern int *Nextnode; /*!< gives next node in tree walk */
extern int *Father; /*!< gives parent node in tree */
extern struct extNODE /*!< this structure holds additional tree-node information which is not needed in the actual gravity computation */
{
FLOAT hmax; /*!< maximum SPH smoothing length in node. Only used for gas particles */
FLOAT vs[3]; /*!< center-of-mass velocity */
}
*Extnodes_base, /*!< points to the actual memory allocted for the extended node information */
*Extnodes; /*!< provides shifted access to extended node information, parallel to Nodes/Nodes_base */
/*! Header for the standard file format.
*/
extern struct io_header
{
int npart[6]; /*!< number of particles of each type in this file */
double mass[6]; /*!< mass of particles of each type. If 0, then the masses are explicitly
stored in the mass-block of the snapshot file, otherwise they are omitted */
double time; /*!< time of snapshot file */
double redshift; /*!< redshift of snapshot file */
int flag_sfr; /*!< flags whether the simulation was including star formation */
int flag_feedback; /*!< flags whether feedback was included (obsolete) */
unsigned int npartTotal[6]; /*!< total number of particles of each type in this snapshot. This can be
different from npart if one is dealing with a multi-file snapshot. */
int flag_cooling; /*!< flags whether cooling was included */
int num_files; /*!< number of files in multi-file snapshot */
double BoxSize; /*!< box-size of simulation in case periodic boundaries were used */
double Omega0; /*!< matter density in units of critical density */
double OmegaLambda; /*!< cosmological constant parameter */
double HubbleParam; /*!< Hubble parameter in units of 100 km/sec/Mpc */
int flag_stellarage; /*!< flags whether the file contains formation times of star particles */
int flag_metals; /*!< flags whether the file contains metallicity values for gas and star particles */
unsigned int npartTotalHighWord[6]; /*!< High word of the total number of particles of each type */
int flag_entropy_instead_u; /*!< flags that IC-file contains entropy instead of u */
int flag_chimie_extraheader; /*!< flags that IC-file contains extra-header for chimie */
int flag_supernova_thermaltime; /*!< flags that IC-file contains supernova thermal time */
#ifdef MULTIPHASE
double critical_energy_spec;
#ifdef MESOMACHINE
char fill[34];
#else
char fill[44]; /* use 42 with regor... */
#endif
#else
char fill[52]; /*!< fills to 256 Bytes */
#endif
}
header; /*!< holds header for snapshot files */
#ifdef CHIMIE_EXTRAHEADER
/*! Header for the chimie part.
*/
extern struct io_chimie_extraheader
{
int nelts; /*!< number of chemical element followed */
float SolarMassAbundances[NELEMENTS];
char labels[256-4-4*(NELEMENTS)];
}
chimie_extraheader;
#endif
#define IO_NBLOCKS 26 /*!< total number of defined information blocks for snapshot files.
Must be equal to the number of entries in "enum iofields" */
enum iofields /*!< this enumeration lists the defined output blocks in snapshot files. Not all of them need to be present. */
{
IO_POS,
IO_VEL,
IO_ID,
IO_MASS,
IO_U,
IO_RHO,
IO_HSML,
IO_POT,
IO_ACCEL,
IO_DTENTR,
IO_TSTP,
IO_ERADSPH,
IO_ERADSTICKY,
IO_ERADFEEDBACK,
IO_ENERGYFLUX,
IO_METALS,
IO_SNII_THERMALTIME,
IO_SNIA_THERMALTIME,
IO_STAR_FORMATIONTIME,
IO_STAR_INITIAL_MASS,
IO_STAR_IDPROJ,
IO_STAR_RHO,
IO_STAR_HSML,
IO_STAR_METALS,
IO_OPTVAR1,
IO_OPTVAR2
};
extern char Tab_IO_Labels[IO_NBLOCKS][4]; /*<! This table holds four-byte character tags used for fileformat 2 */
/* global state of system, used for global statistics
*/
extern struct state_of_system
{
double Mass;
double EnergyKin;
double EnergyPot;
double EnergyInt;
#ifdef COOLING
double EnergyRadSph;
#endif
#ifdef AGN_HEATING
double EnergyAGNHeat;
#endif
#ifdef DISSIPATION_FORCES
double EnergyDissipationForces;
#endif
#ifdef MULTIPHASE
double EnergyRadSticky;
#endif
#ifdef FEEDBACK_WIND
double EnergyFeedbackWind;
#endif
#ifdef BUBBLES
double EnergyBubbles;
#endif
#ifdef CHIMIE_THERMAL_FEEDBACK
double EnergyThermalFeedback;
#endif
#ifdef CHIMIE_KINETIC_FEEDBACK
double EnergyKineticFeedback;
#endif
#ifdef INTEGRAL_CONSERVING_DISSIPATION
double EnergyICDissipation;
#endif
double EnergyTot;
double Momentum[4];
double AngMomentum[4];
double CenterOfMass[4];
double MassComp[6];
double EnergyKinComp[6];
double EnergyPotComp[6];
double EnergyIntComp[6];
#ifdef COOLING
double EnergyRadSphComp[6];
#endif
#ifdef AGN_HEATING
double EnergyAGNHeatComp[6];
#endif
#ifdef MULTIPHASE
double EnergyRadStickyComp[6];
#endif
#ifdef FEEDBACK_WIND
double EnergyFeedbackWindComp[6];
#endif
#ifdef BUBBLES
double EnergyBubblesComp[6];
#endif
#ifdef CHIMIE_THERMAL_FEEDBACK
double EnergyThermalFeedbackComp[6];
#endif
#ifdef CHIMIE_KINETIC_FEEDBACK
double EnergyKineticFeedbackComp[6];
#endif
double EnergyTotComp[6];
double MomentumComp[6][4];
double AngMomentumComp[6][4];
double CenterOfMassComp[6][4];
#ifdef DISSIPATION_FORCES
double EnergyDissipationForcesComp[6];
#endif
#ifdef INTEGRAL_CONSERVING_DISSIPATION
double EnergyICDissipationComp[6];
#endif
}
SysState; /*<! Structure for storing some global statistics about the simulation. */
/*! This structure contains data related to the energy budget.
These values are different for each task. It need to be stored
in the restart flag.
*/
extern struct local_state_of_system
{
double EnergyTest;
double EnergyInt1;
double EnergyInt2;
double EnergyKin1;
double EnergyKin2;
#ifdef COOLING
double RadiatedEnergy;
#endif
#ifdef SFR
double StarEnergyInt;
#ifdef FEEDBACK
double StarEnergyFeedback;
#endif
#endif
#ifdef CHIMIE_THERMAL_FEEDBACK
double EnergyThermalFeedback;
#endif
#ifdef CHIMIE_KINETIC_FEEDBACK
double EnergyKineticFeedback;
#endif
#ifdef MULTIPHASE
double EnergyRadSticky;
#endif
#ifdef FEEDBACK_WIND
double EnergyFeedbackWind;
#endif
#ifdef INTEGRAL_CONSERVING_DISSIPATION
double EnergyICDissipation;
#endif
}
LocalSysState; /*<! Structure for storing some local statistics about the simulation. */
/* Various structures for communication
*/
extern struct gravdata_in
{
union
{
FLOAT Pos[3];
FLOAT Acc[3];
FLOAT Potential;
}
u;
#if defined(UNEQUALSOFTENINGS) || defined(STELLAR_FLUX)
int Type;
#ifdef ADAPTIVE_GRAVSOFT_FORGAS
FLOAT Soft;
#endif
#endif
#ifdef STELLAR_FLUX
FLOAT EnergyFlux;
#endif
union
{
FLOAT OldAcc;
int Ninteractions;
}
w;
}
*GravDataIn, /*!< holds particle data to be exported to other processors */
*GravDataGet, /*!< holds particle data imported from other processors */
*GravDataResult, /*!< holds the partial results computed for imported particles. Note: We use GravDataResult = GravDataGet, such that the result replaces the imported data */
*GravDataOut; /*!< holds partial results received from other processors. This will overwrite the GravDataIn array */
extern struct gravdata_index
{
int Task;
int Index;
int SortIndex;
}
*GravDataIndexTable; /*!< the particles to be exported are grouped by task-number. This table allows the results to be disentangled again and to be assigned to the correct particle */
extern struct densdata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Hsml;
#ifdef MULTIPHASE
int Phase;
#endif
int Index;
int Task;
#ifdef ART_CONDUCTIVITY
FLOAT EnergyIntPred;
#endif
#ifdef WITH_ID_IN_DENSITY
int ID;
#endif
}
*DensDataIn, /*!< holds particle data for SPH density computation to be exported to other processors */
*DensDataGet; /*!< holds imported particle data for SPH density computation */
extern struct densdata_out
{
FLOAT Rho;
FLOAT Div, Rot[3];
FLOAT DhsmlDensity;
FLOAT Ngb;
#ifdef ART_CONDUCTIVITY
FLOAT GradEnergyInt[3];
#endif
#ifdef DENSITY_INDEPENDENT_SPH
FLOAT EgyRho;
FLOAT DhsmlEgyDensity;
#endif
#ifdef CHIMIE_SMOOTH_METALS
FLOAT RhoMetal[NELEMENTS];
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
FLOAT RmsSpeed;
#endif
}
*DensDataResult, /*!< stores the locally computed SPH density results for imported particles */
*DensDataPartialResult; /*!< imported partial SPH density results from other processors */
extern struct hydrodata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Hsml;
#ifdef FEEDBACK
FLOAT EnergySN;
#endif
#ifdef MULTIPHASE
int Phase;
FLOAT Entropy;
int StickyFlag;
#endif
FLOAT Mass;
FLOAT Density;
FLOAT Pressure;
FLOAT F1;
FLOAT DhsmlDensityFactor;
int Timestep;
int Task;
int Index;
#ifdef WITH_ID_IN_HYDRA
int ID;
#endif
#ifdef ART_CONDUCTIVITY
FLOAT NormGradEnergyInt;
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO) || defined(ART_VISCO_CD)
double ArtBulkViscConst;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
FLOAT EgyRho;
FLOAT EntVarPred;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
FLOAT PressureFeedbackUpdated;
FLOAT F1FeedbackUpdated;
#endif
#ifdef METAL_DIFFUSION
FLOAT MetalDiffusionCoeff;
#endif
}
*HydroDataIn, /*!< holds particle data for SPH hydro-force computation to be exported to other processors */
*HydroDataGet; /*!< holds imported particle data for SPH hydro-force computation */
extern struct hydrodata_out
{
FLOAT Acc[3];
FLOAT DtEntropy;
#ifdef FEEDBACK
FLOAT DtEgySpecFeedback;
FLOAT FeedbackAccel[3]; /*!< acceleration due to feedback force */
#endif
FLOAT MaxSignalVel;
#ifdef COMPUTE_VELOCITY_DISPERSION
FLOAT VelocityDispersion[VELOCITY_DISPERSION_SIZE];
#endif
#ifdef MULTIPHASE
FLOAT StickyDVel[3]; /*!< differences in velocities induced by sticky collisions */
#endif
#ifdef OUTPUT_CONDUCTIVITY
FLOAT OptVar2;
#endif
#ifdef ART_VISCO_CD
double DmatCD[3][3];
double TmatCD[3][3];
double R_CD;
FLOAT MaxSignalVelCD;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
FLOAT AccFeedbackUpdated[3];
FLOAT maxSignalVelFeedbackUpdated;
#endif
#ifdef METAL_DIFFUSION
FLOAT MetalDiffusionA;
FLOAT MetalDiffusionB[NELEMENTS];
#endif
}
*HydroDataResult, /*!< stores the locally computed SPH hydro results for imported particles */
*HydroDataPartialResult; /*!< imported partial SPH hydro-force results from other processors */
#ifdef MULTIPHASE
extern struct stickydata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Mass;
FLOAT Hsml;
int ID;
int StickyMaxID;
int StickyNgb;
float StickyMaxFs;
int Task;
int Index;
}
*StickyDataIn, /*!< holds particle data for sticky computation to be exported to other processors */
*StickyDataGet; /*!< holds imported particle data for sticky computation */
extern struct stickydata_out
{
int StickyMaxID;
int StickyNgb;
float StickyMaxFs;
FLOAT StickyNewVel[3];
}
*StickyDataResult, /*!< stores the locally computed sticky results for imported particles */
*StickyDataPartialResult; /*!< imported partial sticky results from other processors */
extern struct Sticky_index
{
int Index;
int CellIndex;
int Flag;
}
*StickyIndex;
#endif
#ifdef CHIMIE
extern struct chimiedata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
#ifndef LONGIDS
unsigned int ID; /*!< particle identifier */
#else
unsigned long long ID; /*!< particle identifier */
#endif
FLOAT Hsml;
#ifdef FEEDBACK
FLOAT EnergySN;
#endif
#ifdef MULTIPHASE
int Phase;
FLOAT Entropy;
int StickyFlag;
#endif
FLOAT Density;
FLOAT Y;
FLOAT Pressure;
FLOAT F1;
FLOAT DhsmlDensityFactor;
int Timestep;
int Task;
int Index;
double TotalEjectedGasMass;
double TotalEjectedEltMass[NELEMENTS];
double TotalEjectedEgySpec;
double NumberOfSNIa;
double NumberOfSNII;
#ifdef CHIMIE_KINETIC_FEEDBACK
FLOAT NgbMass;
#endif
}
*ChimieDataIn, /*!< holds particle data for Chimie computation to be exported to other processors */
*ChimieDataGet; /*!< holds imported particle data for Chimie computation */
extern struct chimiedata_out
{
FLOAT Acc[3];
FLOAT DtEntropy;
#ifdef FEEDBACK
FLOAT DtEgySpecFeedback;
FLOAT FeedbackAccel[3]; /*!< acceleration due to feedback force */
#endif
FLOAT MaxSignalVel;
#ifdef COMPUTE_VELOCITY_DISPERSION
FLOAT VelocityDispersion[VELOCITY_DISPERSION_SIZE];
#endif
#ifdef MULTIPHASE
FLOAT StickyDVel[3]; /*!< differences in velocities induced by sticky collisions */
#endif
}
*ChimieDataResult, /*!< stores the locally computed Chimie results for imported particles */
*ChimieDataPartialResult; /*!< imported partial Chimie results from other processors */
extern struct starsdensdata_in
{
FLOAT Pos[3];
FLOAT Hsml;
int Index;
int Task;
}
*StarsDensDataIn, /*!< holds particle data for SPH density computation to be exported to other processors */
*StarsDensDataGet; /*!< holds imported particle data for SPH density computation */
extern struct starsdensdata_out
{
FLOAT Rho;
FLOAT Y;
FLOAT DhsmlDensity;
FLOAT Ngb;
#ifdef CHIMIE_KINETIC_FEEDBACK
FLOAT NgbMass;
#endif
#if CHIMIE_EJECTA_RADIUS == 2
FLOAT Pressure;
#endif
}
*StarsDensDataResult, /*!< stores the locally computed SPH density results for imported particles */
*StarsDensDataPartialResult; /*!< imported partial SPH density results from other processors */
#endif /*CHIMIE*/
#ifdef DISSIPATION_FORCES
extern struct dissipationforcesdata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Hsml;
FLOAT Mass;
FLOAT Density;
int Task;
int Index;
}
*DissipationForcesDataIn, /*!< holds particle data for SPH hydro-force computation to be exported to other processors */
*DissipationForcesDataGet; /*!< holds imported particle data for SPH hydro-force computation */
extern struct dissipationforcesdata_out
{
FLOAT Acc[3];
FLOAT DtEnergy;
}
*DissipationForcesDataResult, /*!< stores the locally computed SPH hydro results for imported particles */
*DissipationForcesDataPartialResult; /*!< imported partial SPH hydro-force results from other processors */
#endif /* DISSIPATION_FORCES */
#ifdef FOF
extern struct FOFdata_in
{
FLOAT Pos[3];
FLOAT Hsml;
FLOAT Density;
int ID;
int FOF_Head;
int FOF_Tail;
int FOF_Prev;
int FOF_Next;
int FOF_CPUHead; /*!< index of the particle in its local proc */
int FOF_CPUPrev; /*!< index of the particle in its local proc */
int FOF_idx;
FLOAT FOF_DensMax;
int Task;
int Index;
}
*FOFDataIn, /*!< holds particle data for SPH hydro-force computation to be exported to other processors */
*FOFDataGet; /*!< holds imported particle data for SPH hydro-force computation */
extern struct FOFdata_out
{
int FOF_Head;
int FOF_Prev;
FLOAT FOF_DensMax;
int FOF_CPUHead;
int FOF_CPUPrev;
int FOF_Done;
}
*FOFDataResult, /*!< stores the locally computed SPH hydro results for imported particles */
*FOFDataPartialResult; /*!< imported partial SPH hydro-force results from other processors */
#endif /* FOF */
#ifdef TESSEL
extern struct ghostdata_in
{
FLOAT Pos[3];
FLOAT rSearch;
int Index;
int Task;
}
*GhostDataIn, /*!< holds particle data for SPH density computation to be exported to other processors */
*GhostDataGet; /*!< holds imported particle data for SPH density computation */
extern struct ghostdata_out
{
FLOAT Value;
}
*GhostDataResult, /*!< stores the locally computed SPH density results for imported particles */
*GhostDataPartialResult; /*!< imported partial SPH density results from other processors */
/* ghost particles */
//extern struct ghost_particle_data
//{
// FLOAT Pos[3]; /*!< particle position at its current time */
// FLOAT Mass; /*!< particle mass */
//}
// *gP;
extern int NumgPart;
#endif /* TESSEL */
#ifdef SYNCHRONIZE_NGB_TIMESTEP
extern struct SynchroinzeNgbTimestepdata_in
{
FLOAT Pos[3];
FLOAT Hsml;
int Ti_step;
int Ti_endstep;
int Index;
int Task;
#ifdef MULTIPHASE
int Phase;
#endif
}
*SynchroinzeNgbTimestepDataIn,
*SynchroinzeNgbTimestepDataGet;
#endif
#ifdef PY_INTERFACE
extern struct denssphdata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Hsml;
FLOAT Density;
FLOAT DhsmlDensityFactor;
int Index;
int Task;
FLOAT Observable;
}
*DensSphDataIn, /*!< holds particle data for SPH density computation to be exported to other processors */
*DensSphDataGet; /*!< holds imported particle data for SPH density computation */
extern struct denssphdata_out
{
FLOAT Rho;
FLOAT Div, Rot[3];
FLOAT DhsmlDensity;
FLOAT Ngb;
FLOAT GradObservable[3];
}
*DensSphDataResult, /*!< stores the locally computed SPH density results for imported particles */
*DensSphDataPartialResult; /*!< imported partial SPH density results from other processors */
extern struct sphdata_in
{
FLOAT Pos[3];
FLOAT Vel[3];
FLOAT Hsml;
FLOAT Density;
FLOAT DhsmlDensityFactor;
FLOAT ObsMoment0;
FLOAT ObsMoment1;
FLOAT Observable;
int Task;
int Index;
}
*SphDataIn, /*!< holds particle data for SPH hydro-force computation to be exported to other processors */
*SphDataGet; /*!< holds imported particle data for SPH hydro-force computation */
extern struct sphdata_out
{
FLOAT ObsMoment0;
FLOAT ObsMoment1;
FLOAT GradObservable[3];
}
*SphDataResult, /*!< stores the locally computed SPH hydro results for imported particles */
*SphDataPartialResult; /*!< imported partial SPH hydro-force results from other processors */
#endif /*PY_INTERFACE*/
#endif
diff --git a/src/density.c b/src/density.c
index 9c9637f..38ee313 100644
--- a/src/density.c
+++ b/src/density.c
@@ -1,968 +1,971 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <mpi.h>
#include "allvars.h"
#include "proto.h"
/*! \file density.c
* \brief SPH density computation and smoothing length determination
*
* This file contains the "first SPH loop", where the SPH densities and
* some auxiliary quantities are computed. If the number of neighbours
* obtained falls outside the target range, the correct smoothing
* length is determined iteratively, if needed.
*/
#ifdef PERIODIC
static double boxSize, boxHalf;
#ifdef LONG_X
static double boxSize_X, boxHalf_X;
#else
#define boxSize_X boxSize
#define boxHalf_X boxHalf
#endif
#ifdef LONG_Y
static double boxSize_Y, boxHalf_Y;
#else
#define boxSize_Y boxSize
#define boxHalf_Y boxHalf
#endif
#ifdef LONG_Z
static double boxSize_Z, boxHalf_Z;
#else
#define boxSize_Z boxSize
#define boxHalf_Z boxHalf
#endif
#endif
/*! This function computes the local density for each active SPH particle,
* the number of neighbours in the current smoothing radius, and the
* divergence and curl of the velocity field. The pressure is updated as
* well. If a particle with its smoothing region is fully inside the
* local domain, it is not exported to the other processors. The function
* also detects particles that have a number of neighbours outside the
* allowed tolerance range. For these particles, the smoothing length is
* adjusted accordingly, and the density computation is executed again.
* Note that the smoothing length is not allowed to fall below the lower
* bound set by MinGasHsml.
*/
void density(int mode)
{
long long ntot, ntotleft;
int *noffset, *nbuffer, *nsend, *nsend_local, *numlist, *ndonelist;
int i, j, n, ndone, npleft, maxfill, source, iter = 0;
int level, ngrp, sendTask, recvTask, place, nexport;
double dt_entr, tstart, tend, tstart_ngb = 0, tend_ngb = 0;
double sumt, sumcomm, timengb, sumtimengb;
double timecomp = 0, timeimbalance = 0, timecommsumm = 0, sumimbalance;
MPI_Status status;
#ifdef DETAILED_CPU_OUTPUT_IN_DENSITY
double *timengblist;
double *timecomplist;
double *timecommsummlist;
double *timeimbalancelist;
#endif
#ifdef DETAILED_CPU
double t0=0,t1=0;
#endif
#ifdef PERIODIC
boxSize = All.BoxSize;
boxHalf = 0.5 * All.BoxSize;
#ifdef LONG_X
boxHalf_X = boxHalf * LONG_X;
boxSize_X = boxSize * LONG_X;
#endif
#ifdef LONG_Y
boxHalf_Y = boxHalf * LONG_Y;
boxSize_Y = boxSize * LONG_Y;
#endif
#ifdef LONG_Z
boxHalf_Z = boxHalf * LONG_Z;
boxSize_Z = boxSize * LONG_Z;
#endif
#endif
#ifdef DETAILED_CPU
if (mode==1)
t0 = second();
#endif
noffset = malloc(sizeof(int) * NTask); /* offsets of bunches in common list */
nbuffer = malloc(sizeof(int) * NTask);
nsend_local = malloc(sizeof(int) * NTask);
nsend = malloc(sizeof(int) * NTask * NTask);
ndonelist = malloc(sizeof(int) * NTask);
for(n = 0, NumSphUpdate = 0; n < N_gas; n++)
{
SphP[n].Left = SphP[n].Right = 0;
#ifdef AVOIDNUMNGBPROBLEM
SphP[n].OldNumNgb = -1;
#endif
#ifdef ART_CONDUCTIVITY // warning, this is no longer correct if JEANS_PRESSURE_FLOOR is used
SphP[n].EnergyIntPred = GAMMA_MINUS1*SphP[n].Pressure/SphP[n].Density ;
#endif
#ifdef SFR
if((P[n].Ti_endstep == All.Ti_Current) && (P[n].Type == 0))
#else
if(P[n].Ti_endstep == All.Ti_Current)
#endif
NumSphUpdate++;
}
numlist = malloc(NTask * sizeof(int) * NTask);
MPI_Allgather(&NumSphUpdate, 1, MPI_INT, numlist, 1, MPI_INT, MPI_COMM_WORLD);
for(i = 0, ntot = 0; i < NTask; i++)
ntot += numlist[i];
free(numlist);
/* we will repeat the whole thing for those particles where we didn't
* find enough neighbours
*/
do
{
i = 0; /* beginn with this index */
ntotleft = ntot; /* particles left for all tasks together */
while(ntotleft > 0)
{
for(j = 0; j < NTask; j++)
nsend_local[j] = 0;
/* do local particles and prepare export list */
tstart = second();
for(nexport = 0, ndone = 0; i < N_gas && nexport < All.BunchSizeDensity - NTask; i++)
#ifdef SFR
if((P[i].Ti_endstep == All.Ti_Current) && (P[i].Type == 0))
#else
if(P[i].Ti_endstep == All.Ti_Current)
#endif
{
ndone++;
for(j = 0; j < NTask; j++)
Exportflag[j] = 0;
density_evaluate(i, 0);
for(j = 0; j < NTask; j++)
{
if(Exportflag[j])
{
DensDataIn[nexport].Pos[0] = P[i].Pos[0];
DensDataIn[nexport].Pos[1] = P[i].Pos[1];
DensDataIn[nexport].Pos[2] = P[i].Pos[2];
DensDataIn[nexport].Vel[0] = SphP[i].VelPred[0];
DensDataIn[nexport].Vel[1] = SphP[i].VelPred[1];
DensDataIn[nexport].Vel[2] = SphP[i].VelPred[2];
DensDataIn[nexport].Hsml = SphP[i].Hsml;
#ifdef MULTIPHASE
DensDataIn[nexport].Phase = SphP[i].Phase;
#endif
DensDataIn[nexport].Index = i;
DensDataIn[nexport].Task = j;
#ifdef ART_CONDUCTIVITY
DensDataIn[nexport].EnergyIntPred = SphP[i].EnergyIntPred ;
#endif
#ifdef WITH_ID_IN_DENSITY
DensDataIn[nexport].ID = P[i].ID ;
#endif
nexport++;
nsend_local[j]++;
}
}
}
tend = second();
timecomp += timediff(tstart, tend);
qsort(DensDataIn, nexport, sizeof(struct densdata_in), dens_compare_key);
for(j = 1, noffset[0] = 0; j < NTask; j++)
noffset[j] = noffset[j - 1] + nsend_local[j - 1];
tstart = second();
MPI_Allgather(nsend_local, NTask, MPI_INT, nsend, NTask, MPI_INT, MPI_COMM_WORLD);
tend = second();
timeimbalance += timediff(tstart, tend);
/* now do the particles that need to be exported */
for(level = 1; level < (1 << PTask); level++)
{
tstart = second();
for(j = 0; j < NTask; j++)
nbuffer[j] = 0;
for(ngrp = level; ngrp < (1 << PTask); ngrp++)
{
maxfill = 0;
for(j = 0; j < NTask; j++)
{
if((j ^ ngrp) < NTask)
if(maxfill < nbuffer[j] + nsend[(j ^ ngrp) * NTask + j])
maxfill = nbuffer[j] + nsend[(j ^ ngrp) * NTask + j];
}
if(maxfill >= All.BunchSizeDensity)
break;
sendTask = ThisTask;
recvTask = ThisTask ^ ngrp;
if(recvTask < NTask)
{
if(nsend[ThisTask * NTask + recvTask] > 0 || nsend[recvTask * NTask + ThisTask] > 0)
{
/* get the particles */
MPI_Sendrecv(&DensDataIn[noffset[recvTask]],
nsend_local[recvTask] * sizeof(struct densdata_in), MPI_BYTE,
recvTask, TAG_DENS_A,
&DensDataGet[nbuffer[ThisTask]],
nsend[recvTask * NTask + ThisTask] * sizeof(struct densdata_in),
MPI_BYTE, recvTask, TAG_DENS_A, MPI_COMM_WORLD, &status);
}
}
for(j = 0; j < NTask; j++)
if((j ^ ngrp) < NTask)
nbuffer[j] += nsend[(j ^ ngrp) * NTask + j];
}
tend = second();
timecommsumm += timediff(tstart, tend);
tstart = second();
for(j = 0; j < nbuffer[ThisTask]; j++)
density_evaluate(j, 1);
tend = second();
timecomp += timediff(tstart, tend);
/* do a block to explicitly measure imbalance */
tstart = second();
MPI_Barrier(MPI_COMM_WORLD);
tend = second();
timeimbalance += timediff(tstart, tend);
/* get the result */
tstart = second();
for(j = 0; j < NTask; j++)
nbuffer[j] = 0;
for(ngrp = level; ngrp < (1 << PTask); ngrp++)
{
maxfill = 0;
for(j = 0; j < NTask; j++)
{
if((j ^ ngrp) < NTask)
if(maxfill < nbuffer[j] + nsend[(j ^ ngrp) * NTask + j])
maxfill = nbuffer[j] + nsend[(j ^ ngrp) * NTask + j];
}
if(maxfill >= All.BunchSizeDensity)
break;
sendTask = ThisTask;
recvTask = ThisTask ^ ngrp;
if(recvTask < NTask)
{
if(nsend[ThisTask * NTask + recvTask] > 0 || nsend[recvTask * NTask + ThisTask] > 0)
{
/* send the results */
MPI_Sendrecv(&DensDataResult[nbuffer[ThisTask]],
nsend[recvTask * NTask + ThisTask] * sizeof(struct densdata_out),
MPI_BYTE, recvTask, TAG_DENS_B,
&DensDataPartialResult[noffset[recvTask]],
nsend_local[recvTask] * sizeof(struct densdata_out),
MPI_BYTE, recvTask, TAG_DENS_B, MPI_COMM_WORLD, &status);
/* add the result to the particles */
for(j = 0; j < nsend_local[recvTask]; j++)
{
source = j + noffset[recvTask];
place = DensDataIn[source].Index;
SphP[place].NumNgb += DensDataPartialResult[source].Ngb;
SphP[place].Density += DensDataPartialResult[source].Rho;
SphP[place].DivVel += DensDataPartialResult[source].Div;
SphP[place].DhsmlDensityFactor += DensDataPartialResult[source].DhsmlDensity;
#ifdef DENSITY_INDEPENDENT_SPH
SphP[place].EgyWtDensity += DensDataPartialResult[source].EgyRho;
SphP[place].DhsmlEgyDensityFactor += DensDataPartialResult[source].DhsmlEgyDensity;
#endif
SphP[place].Rot[0] += DensDataPartialResult[source].Rot[0];
SphP[place].Rot[1] += DensDataPartialResult[source].Rot[1];
SphP[place].Rot[2] += DensDataPartialResult[source].Rot[2];
#ifdef ART_CONDUCTIVITY
SphP[place].GradEnergyInt[0] += DensDataPartialResult[source].GradEnergyInt[0];
SphP[place].GradEnergyInt[1] += DensDataPartialResult[source].GradEnergyInt[1];
SphP[place].GradEnergyInt[2] += DensDataPartialResult[source].GradEnergyInt[2];
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
SphP[place].RmsSpeed += DensDataPartialResult[source].RmsSpeed;
#endif
}
}
}
for(j = 0; j < NTask; j++)
if((j ^ ngrp) < NTask)
nbuffer[j] += nsend[(j ^ ngrp) * NTask + j];
}
tend = second();
timecommsumm += timediff(tstart, tend);
level = ngrp - 1;
}
MPI_Allgather(&ndone, 1, MPI_INT, ndonelist, 1, MPI_INT, MPI_COMM_WORLD);
for(j = 0; j < NTask; j++)
ntotleft -= ndonelist[j];
}
/* do final operations on results */
tstart = second();
for(i = 0, npleft = 0; i < N_gas; i++)
{
#ifdef SFR
if((P[i].Ti_endstep == All.Ti_Current) && (P[i].Type == 0))
#else
if(P[i].Ti_endstep == All.Ti_Current)
#endif
{
{
/* this two following lines where the old Gadget-2 version */
//SphP[i].DhsmlDensityFactor =
// 1 / (1 + SphP[i].Hsml * SphP[i].DhsmlDensityFactor / (NUMDIMS * SphP[i].Density));
/* they are replaced by the next ones, from Hopkins */
SphP[i].DhsmlDensityFactor *= SphP[i].Hsml / (NUMDIMS * SphP[i].Density);
if (SphP[i].DhsmlDensityFactor > -0.9)
{
SphP[i].DhsmlDensityFactor = 1 / (1 + SphP[i].DhsmlDensityFactor);
} else {
SphP[i].DhsmlDensityFactor = 1;
}
#ifdef DENSITY_INDEPENDENT_SPH
if((SphP[i].EntVarPred>0)&&(SphP[i].EgyWtDensity>0))
{
SphP[i].DhsmlEgyDensityFactor *= SphP[i].Hsml/ (NUMDIMS * SphP[i].EgyWtDensity);
SphP[i].DhsmlEgyDensityFactor *= -SphP[i].DhsmlDensityFactor;
SphP[i].EgyWtDensity /= SphP[i].EntVarPred;
} else {
SphP[i].DhsmlEgyDensityFactor=0; SphP[i].EntVarPred=0; SphP[i].EgyWtDensity=0;
}
#endif
#if CHIMIE_SMOOTH_METALS
int k;
for (k=0;k<NELEMENTS;k++)
SphP[i].Metal[k] = SphP[i].RhoMetal[k] / SphP[i].Density;
#endif
SphP[i].CurlVel = sqrt(SphP[i].Rot[0] * SphP[i].Rot[0] +
SphP[i].Rot[1] * SphP[i].Rot[1] +
SphP[i].Rot[2] * SphP[i].Rot[2]) / SphP[i].Density;
SphP[i].DivVel /= SphP[i].Density;
dt_entr = (All.Ti_Current - (P[i].Ti_begstep + P[i].Ti_endstep) / 2) * All.Timebase_interval;
#ifdef DENSITY_INDEPENDENT_SPH
SphP[i].Pressure = pow(SphP[i].EntVarPred*SphP[i].EgyWtDensity,GAMMA);
#else
SphP[i].Pressure =
(SphP[i].Entropy + SphP[i].DtEntropy * dt_entr) * pow(SphP[i].Density, GAMMA);
#endif
#ifdef JEANS_PRESSURE_FLOOR
SphP[i].Pressure = dmax(SphP[i].Pressure,JeansPressureFloor(i));
#endif
#ifdef ART_CONDUCTIVITY
SphP[i].GradEnergyInt[0] /= SphP[i].Density;
SphP[i].GradEnergyInt[1] /= SphP[i].Density;
SphP[i].GradEnergyInt[2] /= SphP[i].Density;
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
SphP[i].RmsSpeed /= SphP[i].Density;
+#endif
+
+#ifdef METAL_DIFFUSION
if(SphP[i].RmsSpeed>0)
SphP[i].MetalDiffusionCoeff = All.MetalDiffusionConst*2*SphP[i].Density * sqrt( SphP[i].RmsSpeed ) * SphP[i].Hsml ;
else
SphP[i].MetalDiffusionCoeff = 0;
//if(SphP[i].MetalDiffusionCoeff<2e-7)
// SphP[i].MetalDiffusionCoeff=0;
#endif
}
/* now check whether we had enough neighbours */
if(SphP[i].NumNgb < (All.DesNumNgb - All.MaxNumNgbDeviation) ||
(SphP[i].NumNgb > (All.DesNumNgb + All.MaxNumNgbDeviation)
&& SphP[i].Hsml > (1.01 * All.MinGasHsml)))
{
#ifdef AVOIDNUMNGBPROBLEM
// if((SphP[i].NumNgb>SphP[i].OldNumNgb-All.MaxNumNgbDeviation/10000.)
// &&(SphP[i].NumNgb<SphP[i].OldNumNgb+All.MaxNumNgbDeviation/10000.))
if(SphP[i].NumNgb==SphP[i].OldNumNgb)
{
P[i].Ti_endstep = -P[i].Ti_endstep - 1;
printf("ID=%d NumNgb=%g OldNumNgb=%g\n",P[i].ID,SphP[i].NumNgb,SphP[i].OldNumNgb);
continue;
}
SphP[i].OldNumNgb = SphP[i].NumNgb;
#endif
/* need to redo this particle */
npleft++;
if(SphP[i].Left > 0 && SphP[i].Right > 0)
if((SphP[i].Right - SphP[i].Left) < 1.0e-3 * SphP[i].Left)
{
/* this one should be ok */
npleft--;
P[i].Ti_endstep = -P[i].Ti_endstep - 1; /* Mark as inactive */
continue;
}
if(SphP[i].NumNgb < (All.DesNumNgb - All.MaxNumNgbDeviation))
SphP[i].Left = dmax(SphP[i].Hsml, SphP[i].Left);
else
{
if(SphP[i].Right != 0)
{
if(SphP[i].Hsml < SphP[i].Right)
SphP[i].Right = SphP[i].Hsml;
}
else
SphP[i].Right = SphP[i].Hsml;
}
if(iter >= MAXITER - 10)
{
printf
("i=%d task=%d ID=%d Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n pos=(%g|%g|%g)\n",
i, ThisTask, (int) P[i].ID, SphP[i].Hsml, SphP[i].Left, SphP[i].Right,
(float) SphP[i].NumNgb, SphP[i].Right - SphP[i].Left, P[i].Pos[0], P[i].Pos[1],
P[i].Pos[2]);
fflush(stdout);
}
if(SphP[i].Right > 0 && SphP[i].Left > 0)
SphP[i].Hsml = pow(0.5 * (pow(SphP[i].Left, 3) + pow(SphP[i].Right, 3)), 1.0 / 3);
else
{
if(SphP[i].Right == 0 && SphP[i].Left == 0)
{
printf
("i=%d task=%d ID=%d Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n pos=(%g|%g|%g)\n",
i, ThisTask, (int) P[i].ID, SphP[i].Hsml, SphP[i].Left, SphP[i].Right,
(float) SphP[i].NumNgb, SphP[i].Right - SphP[i].Left, P[i].Pos[0], P[i].Pos[1],
P[i].Pos[2]);
fflush(stdout);
endrun(8188); /* can't occur */
}
if(SphP[i].Right == 0 && SphP[i].Left > 0)
{
if(P[i].Type == 0 && fabs(SphP[i].NumNgb - All.DesNumNgb) < 0.5 * All.DesNumNgb)
{
SphP[i].Hsml *=
1 - (SphP[i].NumNgb -
All.DesNumNgb) / (NUMDIMS * SphP[i].NumNgb) * SphP[i].DhsmlDensityFactor;
}
else
SphP[i].Hsml *= 1.26;
}
if(SphP[i].Right > 0 && SphP[i].Left == 0)
{
if(P[i].Type == 0 && fabs(SphP[i].NumNgb - All.DesNumNgb) < 0.5 * All.DesNumNgb)
{
SphP[i].Hsml *=
1 - (SphP[i].NumNgb -
All.DesNumNgb) / (NUMDIMS * SphP[i].NumNgb) * SphP[i].DhsmlDensityFactor;
}
else
SphP[i].Hsml /= 1.26;
}
}
if(SphP[i].Hsml < All.MinGasHsml)
SphP[i].Hsml = All.MinGasHsml;
}
else
P[i].Ti_endstep = -P[i].Ti_endstep - 1; /* Mark as inactive */
}
}
tend = second();
timecomp += timediff(tstart, tend);
numlist = malloc(NTask * sizeof(int) * NTask);
MPI_Allgather(&npleft, 1, MPI_INT, numlist, 1, MPI_INT, MPI_COMM_WORLD);
for(i = 0, ntot = 0; i < NTask; i++)
ntot += numlist[i];
free(numlist);
if(ntot > 0)
{
if(iter == 0)
tstart_ngb = second();
iter++;
if(iter > 0 && ThisTask == 0)
{
printf("ngb iteration %d: need to repeat for %d%09d particles.\n", iter,
(int) (ntot / 1000000000), (int) (ntot % 1000000000));
fflush(stdout);
}
if(iter > MAXITER)
{
printf("failed to converge in neighbour iteration in density()\n");
fflush(stdout);
endrun(1155);
}
}
else
tend_ngb = second();
}
while(ntot > 0);
/* mark as active again */
for(i = 0; i < NumPart; i++)
if(P[i].Ti_endstep < 0)
P[i].Ti_endstep = -P[i].Ti_endstep - 1;
free(ndonelist);
free(nsend);
free(nsend_local);
free(nbuffer);
free(noffset);
/* collect some timing information */
if(iter > 0)
timengb = timediff(tstart_ngb, tend_ngb);
else
timengb = 0;
MPI_Reduce(&timengb, &sumtimengb, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&timecomp, &sumt, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&timecommsumm, &sumcomm, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&timeimbalance, &sumimbalance, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
#ifdef DETAILED_CPU_OUTPUT_IN_DENSITY
numlist = malloc(sizeof(int) * NTask);
timengblist = malloc(sizeof(double) * NTask);
timecomplist = malloc(sizeof(double) * NTask);
timecommsummlist = malloc(sizeof(double) * NTask);
timeimbalancelist = malloc(sizeof(double) * NTask);
MPI_Gather(&NumSphUpdate, 1, MPI_INT, numlist, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gather(&timengb, 1, MPI_DOUBLE, timengblist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&timecomp, 1, MPI_DOUBLE, timecomplist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&timecommsumm, 1, MPI_DOUBLE, timecommsummlist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&timeimbalance, 1, MPI_DOUBLE, timeimbalancelist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if(ThisTask == 0)
{
fprintf(FdTimings, "\n density (mode=%d)\n\n",mode);
fprintf(FdTimings, "Nupdate ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12d ",numlist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timengb ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timengblist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timecomp ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timecomplist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timecommsumm ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timecommsummlist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timeimbalance ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timeimbalancelist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "\n");
}
free(timeimbalancelist);
free(timecommsummlist);
free(timecomplist);
free(numlist);
#endif
#ifdef DETAILED_CPU
if (mode==1)
{
t1 = second();
#ifdef SFR
All.CPU_StarFormation += timediff(t0, t1);
#endif
}
else
if(ThisTask == 0)
{
All.CPU_HydCompWalk += sumt / NTask;
All.CPU_HydCommSumm += sumcomm / NTask;
All.CPU_HydImbalance += sumimbalance / NTask;
All.CPU_EnsureNgb += sumtimengb / NTask;
}
#else
if(ThisTask == 0)
{
All.CPU_HydCompWalk += sumt / NTask;
All.CPU_HydCommSumm += sumcomm / NTask;
All.CPU_HydImbalance += sumimbalance / NTask;
All.CPU_EnsureNgb += sumtimengb / NTask;
}
#endif
#ifdef GAS_ACCRETION
update_entropy_for_accreated_particles();
#endif
}
/*! This function represents the core of the SPH density computation. The
* target particle may either be local, or reside in the communication
* buffer.
*/
void density_evaluate(int target, int mode)
{
int j, n, startnode, numngb, numngb_inbox;
double h, h2, fac, hinv, hinv3, hinv4;
double rho, divv, wk, dwk;
double dx, dy, dz, r, r2, u, mass_j;
double dvx, dvy, dvz, rotv[3];
double weighted_numngb, dhsmlrho;
FLOAT *pos, *vel;
int phase=0;
#ifdef WITH_ID_IN_DENSITY
int id;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
double egyrho, dhsmlegyrho;
#endif
#ifdef ART_CONDUCTIVITY
double gradux, graduy, graduz;
double energyintpred;
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
double RmsSpeed=0;
#endif
#ifdef CHIMIE_SMOOTH_METALS
FLOAT rhometal[NELEMENTS];
int k;
for (k=0;k<NELEMENTS;k++)
rhometal[k] = 0;
#endif
if(mode == 0)
{
pos = P[target].Pos;
vel = SphP[target].VelPred;
h = SphP[target].Hsml;
#ifdef WITH_ID_IN_DENSITY
id = P[target].ID;
#endif
#ifdef MULTIPHASE
phase = SphP[target].Phase;
#endif
#ifdef ART_CONDUCTIVITY
energyintpred = SphP[target].EnergyIntPred;
#endif
}
else
{
pos = DensDataGet[target].Pos;
vel = DensDataGet[target].Vel;
h = DensDataGet[target].Hsml;
#ifdef WITH_ID_IN_DENSITY
id = DensDataGet[target].ID;
#endif
#ifdef MULTIPHASE
phase = DensDataGet[target].Phase;
#endif
#ifdef ART_CONDUCTIVITY
energyintpred = DensDataGet[target].EnergyIntPred;
#endif
}
h2 = h * h;
hinv = 1.0 / h;
#ifndef TWODIMS
hinv3 = hinv * hinv * hinv;
#else
hinv3 = hinv * hinv / boxSize_Z;
#endif
hinv4 = hinv3 * hinv;
rho = divv = rotv[0] = rotv[1] = rotv[2] = 0;
weighted_numngb = 0;
dhsmlrho = 0;
#ifdef ART_CONDUCTIVITY
gradux=graduy=graduz=0;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
egyrho=0; dhsmlegyrho=0;
#endif
startnode = All.MaxPart;
numngb = 0;
do
{
numngb_inbox = ngb_treefind_variable(&pos[0], h, phase, &startnode);
for(n = 0; n < numngb_inbox; n++)
{
j = Ngblist[n];
dx = pos[0] - P[j].Pos[0];
dy = pos[1] - P[j].Pos[1];
dz = pos[2] - P[j].Pos[2];
#ifdef PERIODIC /* now find the closest image in the given box size */
if(dx > boxHalf_X)
dx -= boxSize_X;
if(dx < -boxHalf_X)
dx += boxSize_X;
if(dy > boxHalf_Y)
dy -= boxSize_Y;
if(dy < -boxHalf_Y)
dy += boxSize_Y;
if(dz > boxHalf_Z)
dz -= boxSize_Z;
if(dz < -boxHalf_Z)
dz += boxSize_Z;
#endif
r2 = dx * dx + dy * dy + dz * dz;
if(r2 < h2)
{
numngb++;
r = sqrt(r2);
u = r * hinv;
if(u < 0.5)
{
wk = hinv3 * (KERNEL_COEFF_1 + KERNEL_COEFF_2 * (u - 1) * u * u);
dwk = hinv4 * u * (KERNEL_COEFF_3 * u - KERNEL_COEFF_4);
}
else
{
wk = hinv3 * KERNEL_COEFF_5 * (1.0 - u) * (1.0 - u) * (1.0 - u);
dwk = hinv4 * KERNEL_COEFF_6 * (1.0 - u) * (1.0 - u);
}
mass_j = P[j].Mass;
rho += mass_j * wk;
#ifdef CHIMIE_SMOOTH_METALS
for (k=0;k<NELEMENTS;k++)
rhometal[k] += SphP[j].MassMetal[k] * mass_j * wk;
#endif
weighted_numngb += NORM_COEFF * wk / hinv3;
dhsmlrho += -mass_j * (NUMDIMS * hinv * wk + u * dwk);
#ifdef DENSITY_INDEPENDENT_SPH
egyrho += mass_j * SphP[j].EntVarPred * wk;
dhsmlegyrho += -mass_j * SphP[j].EntVarPred * (NUMDIMS * hinv * wk + u * dwk);
#endif
if(r > 0)
{
fac = mass_j * dwk / r;
dvx = vel[0] - SphP[j].VelPred[0];
dvy = vel[1] - SphP[j].VelPred[1];
dvz = vel[2] - SphP[j].VelPred[2];
divv -= fac * (dx * dvx + dy * dvy + dz * dvz);
rotv[0] += fac * (dz * dvy - dy * dvz);
rotv[1] += fac * (dx * dvz - dz * dvx);
rotv[2] += fac * (dy * dvx - dx * dvy);
#ifdef ART_CONDUCTIVITY
if (All.NumCurrentTiStep==0)
fac = 0;
gradux += fac * (energyintpred-SphP[j].EnergyIntPred)*dx;
graduy += fac * (energyintpred-SphP[j].EnergyIntPred)*dy;
graduz += fac * (energyintpred-SphP[j].EnergyIntPred)*dz;
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
//RmsSpeed += -fac * (dvx * dvx + dvy * dvy + dvz * dvz) ; /* version used in revaz et al. 2016 */
RmsSpeed += mass_j * wk * (dvx * dvx + dvy * dvy + dvz * dvz) ;
#endif
}
}
}
}
while(startnode >= 0);
if(mode == 0)
{
SphP[target].NumNgb = weighted_numngb;
SphP[target].Density = rho;
SphP[target].DivVel = divv;
SphP[target].DhsmlDensityFactor = dhsmlrho;
SphP[target].Rot[0] = rotv[0];
SphP[target].Rot[1] = rotv[1];
SphP[target].Rot[2] = rotv[2];
#ifdef ART_CONDUCTIVITY
SphP[target].GradEnergyInt[0] = gradux;
SphP[target].GradEnergyInt[1] = graduy;
SphP[target].GradEnergyInt[2] = graduz;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
SphP[target].EgyWtDensity = egyrho;
SphP[target].DhsmlEgyDensityFactor = dhsmlegyrho;
#endif
#ifdef CHIMIE_SMOOTH_METALS
for (k=0;k<NELEMENTS;k++)
SphP[target].RhoMetal[k] = rhometal[k];
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
SphP[target].RmsSpeed = RmsSpeed;
#endif
}
else
{
DensDataResult[target].Rho = rho;
DensDataResult[target].Div = divv;
DensDataResult[target].Ngb = weighted_numngb;
DensDataResult[target].DhsmlDensity = dhsmlrho;
DensDataResult[target].Rot[0] = rotv[0];
DensDataResult[target].Rot[1] = rotv[1];
DensDataResult[target].Rot[2] = rotv[2];
#ifdef ART_CONDUCTIVITY
DensDataResult[target].GradEnergyInt[0] = gradux;
DensDataResult[target].GradEnergyInt[1] = graduy;
DensDataResult[target].GradEnergyInt[2] = graduz;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
DensDataResult[target].EgyRho = egyrho;
DensDataResult[target].DhsmlEgyDensity = dhsmlegyrho;
#endif
#ifdef CHIMIE_SMOOTH_METALS
for (k=0;k<NELEMENTS;k++)
DensDataResult[target].RhoMetal[k] = rhometal[k];
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
DensDataResult[target].RmsSpeed = RmsSpeed;
#endif
}
}
/*! This routine is a comparison kernel used in a sort routine to group
* particles that are exported to the same processor.
*/
int dens_compare_key(const void *a, const void *b)
{
if(((struct densdata_in *) a)->Task < (((struct densdata_in *) b)->Task))
return -1;
if(((struct densdata_in *) a)->Task > (((struct densdata_in *) b)->Task))
return +1;
return 0;
}
diff --git a/src/hydra.c b/src/hydra.c
index 6a16d5e..cc8288b 100644
--- a/src/hydra.c
+++ b/src/hydra.c
@@ -1,1851 +1,1865 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <mpi.h>
#include <gsl/gsl_math.h>
#include "allvars.h"
#include "proto.h"
/*! \file hydra.c
* \brief Computation of SPH forces and rate of entropy generation
*
* This file contains the "second SPH loop", where the SPH forces are
* computed, and where the rate of change of entropy due to the shock heating
* (via artificial viscosity) is computed.
*/
static double hubble_a, atime, hubble_a2, fac_mu, fac_vsic_fix, a3inv, fac_egy;
#ifdef FEEDBACK
static double fac_pow;
#endif
#ifdef JEANS_PRESSURE_FLOOR
static double ap3g4;
#endif
#ifdef PERIODIC
static double boxSize, boxHalf;
#ifdef LONG_X
static double boxSize_X, boxHalf_X;
#else
#define boxSize_X boxSize
#define boxHalf_X boxHalf
#endif
#ifdef LONG_Y
static double boxSize_Y, boxHalf_Y;
#else
#define boxSize_Y boxSize
#define boxHalf_Y boxHalf
#endif
#ifdef LONG_Z
static double boxSize_Z, boxHalf_Z;
#else
#define boxSize_Z boxSize
#define boxHalf_Z boxHalf
#endif
#endif
/*! This function is the driver routine for the calculation of hydrodynamical
* force and rate of change of entropy due to shock heating for all active
* particles .
*/
void hydro_force(void)
{
long long ntot, ntotleft;
int i, j, k, n, ngrp, maxfill, source, ndone;
int *nbuffer, *noffset, *nsend_local, *nsend, *numlist, *ndonelist;
int level, sendTask, recvTask, nexport, place;
double soundspeed_i;
double tstart, tend, sumt, sumcomm;
double timecomp = 0, timecommsumm = 0, timeimbalance = 0, sumimbalance;
MPI_Status status;
#ifdef ART_VISCO_CD
int ii,jj;
#endif
#ifdef DETAILED_CPU_OUTPUT_IN_HYDRA
double *timecomplist;
double *timecommsummlist;
double *timeimbalancelist;
#endif
#ifdef PERIODIC
boxSize = All.BoxSize;
boxHalf = 0.5 * All.BoxSize;
#ifdef LONG_X
boxHalf_X = boxHalf * LONG_X;
boxSize_X = boxSize * LONG_X;
#endif
#ifdef LONG_Y
boxHalf_Y = boxHalf * LONG_Y;
boxSize_Y = boxSize * LONG_Y;
#endif
#ifdef LONG_Z
boxHalf_Z = boxHalf * LONG_Z;
boxSize_Z = boxSize * LONG_Z;
#endif
#endif
#ifdef COMPUTE_VELOCITY_DISPERSION
double v1m,v2m;
#endif
if(All.ComovingIntegrationOn)
{
/* Factors for comoving integration of hydro */
hubble_a = All.Omega0 / (All.Time * All.Time * All.Time)
+ (1 - All.Omega0 - All.OmegaLambda) / (All.Time * All.Time) + All.OmegaLambda;
hubble_a = All.Hubble * sqrt(hubble_a);
hubble_a2 = All.Time * All.Time * hubble_a;
fac_mu = pow(All.Time, 3 * (GAMMA - 1) / 2) / All.Time;
fac_egy = pow(All.Time, 3 * (GAMMA - 1));
fac_vsic_fix = hubble_a * pow(All.Time, 3 * GAMMA_MINUS1);
a3inv = 1 / (All.Time * All.Time * All.Time);
atime = All.Time;
#ifdef FEEDBACK
fac_pow = fac_egy*atime*atime;
#endif
#ifdef JEANS_PRESSURE_FLOOR
ap3g4 = pow(All.Time,3*GAMMA-4.0);
#endif
}
else
{
hubble_a = hubble_a2 = atime = fac_mu = fac_vsic_fix = a3inv = fac_egy = 1.0;
#ifdef FEEDBACK
fac_pow = 1.0;
#endif
#ifdef JEANS_PRESSURE_FLOOR
ap3g4 = 1.0;
#endif
}
#ifdef OUTPUT_CONDUCTIVITY
for (i=0;i<N_gas;i++)
SphP[i].OptVar1 = sqrt( pow(SphP[i].GradEnergyInt[0],2)+pow(SphP[i].GradEnergyInt[1],2)+pow(SphP[i].GradEnergyInt[2],2))*SphP[i].Hsml/(SphP[i].Pressure/(SphP[i].Density*GAMMA_MINUS1)) ;
#endif
/* `NumSphUpdate' gives the number of particles on this processor that want a force update */
for(n = 0, NumSphUpdate = 0; n < N_gas; n++)
{
#ifdef SFR
if((P[n].Ti_endstep == All.Ti_Current) && (P[n].Type == 0))
#else
if(P[n].Ti_endstep == All.Ti_Current)
#endif
#ifdef MULTIPHASE
if(SphP[n].Phase == GAS_SPH)
#endif
NumSphUpdate++;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK)
for(j = 0; j < 3; j++)
SphP[n].FeedbackUpdatedAccel[j] = 0;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
SphP[n].MaxSignalVelFeedbackUpdated=0;
#endif
#ifdef METAL_DIFFUSION
SphP[n].MetalDiffusionA = 0;
for(j = 0; j < NELEMENTS; j++)
SphP[n].MetalDiffusionB[j] = 0;
#endif
}
numlist = malloc(NTask * sizeof(int) * NTask);
MPI_Allgather(&NumSphUpdate, 1, MPI_INT, numlist, 1, MPI_INT, MPI_COMM_WORLD);
for(i = 0, ntot = 0; i < NTask; i++)
ntot += numlist[i];
free(numlist);
noffset = malloc(sizeof(int) * NTask); /* offsets of bunches in common list */
nbuffer = malloc(sizeof(int) * NTask);
nsend_local = malloc(sizeof(int) * NTask);
nsend = malloc(sizeof(int) * NTask * NTask);
ndonelist = malloc(sizeof(int) * NTask);
i = 0; /* first particle for this task */
ntotleft = ntot; /* particles left for all tasks together */
while(ntotleft > 0)
{
for(j = 0; j < NTask; j++)
nsend_local[j] = 0;
/* do local particles and prepare export list */
tstart = second();
for(nexport = 0, ndone = 0; i < N_gas && nexport < All.BunchSizeHydro - NTask; i++)
#ifdef SFR
if((P[i].Ti_endstep == All.Ti_Current) && (P[i].Type == 0))
#else
if(P[i].Ti_endstep == All.Ti_Current)
#endif
{
#ifdef MULTIPHASE
if(SphP[i].Phase == GAS_SPH)
{
#endif
ndone++;
for(j = 0; j < NTask; j++)
Exportflag[j] = 0;
hydro_evaluate(i, 0);
for(j = 0; j < NTask; j++)
{
if(Exportflag[j])
{
for(k = 0; k < 3; k++)
{
HydroDataIn[nexport].Pos[k] = P[i].Pos[k];
HydroDataIn[nexport].Vel[k] = SphP[i].VelPred[k];
}
HydroDataIn[nexport].Hsml = SphP[i].Hsml;
#ifdef FEEDBACK
HydroDataIn[nexport].EnergySN = SphP[i].EnergySN;
#endif
HydroDataIn[nexport].Mass = P[i].Mass;
#ifdef DENSITY_INDEPENDENT_SPH
HydroDataIn[nexport].EgyRho = SphP[i].EgyWtDensity;
HydroDataIn[nexport].EntVarPred = SphP[i].EntVarPred;
HydroDataIn[nexport].DhsmlDensityFactor = SphP[i].DhsmlEgyDensityFactor;
#else
HydroDataIn[nexport].DhsmlDensityFactor = SphP[i].DhsmlDensityFactor;
#endif
HydroDataIn[nexport].Density = SphP[i].Density;
HydroDataIn[nexport].Pressure = SphP[i].Pressure;
HydroDataIn[nexport].Timestep = P[i].Ti_endstep - P[i].Ti_begstep;
#ifdef WITH_ID_IN_HYDRA
HydroDataIn[nexport].ID = P[i].ID;
#endif
#ifdef ART_CONDUCTIVITY
HydroDataIn[nexport].NormGradEnergyInt = sqrt( pow(SphP[i].GradEnergyInt[0],2)+pow(SphP[i].GradEnergyInt[1],2)+pow(SphP[i].GradEnergyInt[2],2));
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO) || defined(ART_VISCO_CD)
HydroDataIn[nexport].ArtBulkViscConst = SphP[i].ArtBulkViscConst;
#endif
/* calculation of F1 */
#ifdef DENSITY_INDEPENDENT_SPH
soundspeed_i = sqrt(GAMMA * SphP[i].Pressure / SphP[i].EgyWtDensity);
#else
soundspeed_i = sqrt(GAMMA * SphP[i].Pressure / SphP[i].Density);
#endif
HydroDataIn[nexport].F1 = fabs(SphP[i].DivVel) /
(fabs(SphP[i].DivVel) + SphP[i].CurlVel +
0.0001 * soundspeed_i / SphP[i].Hsml / fac_mu);
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[i].DeltaEgySpec>0) /* the particle is touch by feedback */
{
#ifdef DENSITY_INDEPENDENT_SPH
HydroDataIn[nexport].PressureFeedbackUpdated = updated_pressure_hydra(SphP[i].EntropyPred,SphP[i].EgyWtDensity,SphP[i].DeltaEgySpec);
soundspeed_i = sqrt(GAMMA * HydroDataIn[nexport].PressureFeedbackUpdated / SphP[i].EgyWtDensity);
#else
HydroDataIn[nexport].PressureFeedbackUpdated = updated_pressure_hydra(SphP[i].EntropyPred,SphP[i].Density,SphP[i].DeltaEgySpec);
soundspeed_i = sqrt(GAMMA * HydroDataIn[nexport].PressureFeedbackUpdated / SphP[i].Density);
#endif
HydroDataIn[nexport].F1FeedbackUpdated = fabs(SphP[i].DivVel) /
(fabs(SphP[i].DivVel) + SphP[i].CurlVel +
0.0001 * soundspeed_i / SphP[i].Hsml / fac_mu);
}
else
{
HydroDataIn[nexport].PressureFeedbackUpdated = SphP[i].Pressure;
HydroDataIn[nexport].F1FeedbackUpdated = HydroDataIn[nexport].F1;
}
#endif
#ifdef METAL_DIFFUSION
HydroDataIn[nexport].MetalDiffusionCoeff = SphP[i].MetalDiffusionCoeff;
#endif
HydroDataIn[nexport].Index = i;
HydroDataIn[nexport].Task = j;
nexport++;
nsend_local[j]++;
}
}
#ifdef MULTIPHASE
}
#endif
}
tend = second();
timecomp += timediff(tstart, tend);
qsort(HydroDataIn, nexport, sizeof(struct hydrodata_in), hydro_compare_key);
for(j = 1, noffset[0] = 0; j < NTask; j++)
noffset[j] = noffset[j - 1] + nsend_local[j - 1];
tstart = second();
MPI_Allgather(nsend_local, NTask, MPI_INT, nsend, NTask, MPI_INT, MPI_COMM_WORLD);
tend = second();
timeimbalance += timediff(tstart, tend);
/* now do the particles that need to be exported */
for(level = 1; level < (1 << PTask); level++)
{
tstart = second();
for(j = 0; j < NTask; j++)
nbuffer[j] = 0;
for(ngrp = level; ngrp < (1 << PTask); ngrp++)
{
maxfill = 0;
for(j = 0; j < NTask; j++)
{
if((j ^ ngrp) < NTask)
if(maxfill < nbuffer[j] + nsend[(j ^ ngrp) * NTask + j])
maxfill = nbuffer[j] + nsend[(j ^ ngrp) * NTask + j];
}
if(maxfill >= All.BunchSizeHydro)
break;
sendTask = ThisTask;
recvTask = ThisTask ^ ngrp;
if(recvTask < NTask)
{
if(nsend[ThisTask * NTask + recvTask] > 0 || nsend[recvTask * NTask + ThisTask] > 0)
{
/* get the particles */
MPI_Sendrecv(&HydroDataIn[noffset[recvTask]],
nsend_local[recvTask] * sizeof(struct hydrodata_in), MPI_BYTE,
recvTask, TAG_HYDRO_A,
&HydroDataGet[nbuffer[ThisTask]],
nsend[recvTask * NTask + ThisTask] * sizeof(struct hydrodata_in), MPI_BYTE,
recvTask, TAG_HYDRO_A, MPI_COMM_WORLD, &status);
}
}
for(j = 0; j < NTask; j++)
if((j ^ ngrp) < NTask)
nbuffer[j] += nsend[(j ^ ngrp) * NTask + j];
}
tend = second();
timecommsumm += timediff(tstart, tend);
/* now do the imported particles */
tstart = second();
for(j = 0; j < nbuffer[ThisTask]; j++)
hydro_evaluate(j, 1);
tend = second();
timecomp += timediff(tstart, tend);
/* do a block to measure imbalance */
tstart = second();
MPI_Barrier(MPI_COMM_WORLD);
tend = second();
timeimbalance += timediff(tstart, tend);
/* get the result */
tstart = second();
for(j = 0; j < NTask; j++)
nbuffer[j] = 0;
for(ngrp = level; ngrp < (1 << PTask); ngrp++)
{
maxfill = 0;
for(j = 0; j < NTask; j++)
{
if((j ^ ngrp) < NTask)
if(maxfill < nbuffer[j] + nsend[(j ^ ngrp) * NTask + j])
maxfill = nbuffer[j] + nsend[(j ^ ngrp) * NTask + j];
}
if(maxfill >= All.BunchSizeHydro)
break;
sendTask = ThisTask;
recvTask = ThisTask ^ ngrp;
if(recvTask < NTask)
{
if(nsend[ThisTask * NTask + recvTask] > 0 || nsend[recvTask * NTask + ThisTask] > 0)
{
/* send the results */
MPI_Sendrecv(&HydroDataResult[nbuffer[ThisTask]],
nsend[recvTask * NTask + ThisTask] * sizeof(struct hydrodata_out),
MPI_BYTE, recvTask, TAG_HYDRO_B,
&HydroDataPartialResult[noffset[recvTask]],
nsend_local[recvTask] * sizeof(struct hydrodata_out),
MPI_BYTE, recvTask, TAG_HYDRO_B, MPI_COMM_WORLD, &status);
/* add the result to the particles */
for(j = 0; j < nsend_local[recvTask]; j++)
{
source = j + noffset[recvTask];
place = HydroDataIn[source].Index;
for(k = 0; k < 3; k++)
SphP[place].HydroAccel[k] += HydroDataPartialResult[source].Acc[k];
SphP[place].DtEntropy += HydroDataPartialResult[source].DtEntropy;
#ifdef FEEDBACK
SphP[place].DtEgySpecFeedback += HydroDataPartialResult[source].DtEgySpecFeedback;
#endif
if(SphP[place].MaxSignalVel < HydroDataPartialResult[source].MaxSignalVel)
SphP[place].MaxSignalVel = HydroDataPartialResult[source].MaxSignalVel;
#ifdef COMPUTE_VELOCITY_DISPERSION
for(k = 0; k < VELOCITY_DISPERSION_SIZE; k++)
SphP[place].VelocityDispersion[k] += HydroDataPartialResult[source].VelocityDispersion[k];
#endif
#ifdef OUTPUT_CONDUCTIVITY
SphP[place].OptVar2 += HydroDataPartialResult[source].OptVar2;
#endif
#ifdef ART_VISCO_CD
/* reduce DmatCD and TmatCD*/
for (ii = 0; ii < 3; ii++)
for (jj = 0; jj < 3; jj++)
{
SphP[place].DmatCD[ii][jj] += HydroDataPartialResult[source].DmatCD[ii][jj];
SphP[place].TmatCD[ii][jj] += HydroDataPartialResult[source].TmatCD[ii][jj];
}
SphP[place].R_CD += HydroDataPartialResult[source].R_CD;
if(SphP[place].MaxSignalVelCD < HydroDataPartialResult[source].MaxSignalVelCD)
SphP[place].MaxSignalVelCD = HydroDataPartialResult[source].MaxSignalVelCD;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
for(k = 0; k < 3; k++)
SphP[place].FeedbackUpdatedAccel[k] += HydroDataPartialResult[source].AccFeedbackUpdated[k];
if(SphP[place].MaxSignalVelFeedbackUpdated < HydroDataPartialResult[source].maxSignalVelFeedbackUpdated)
SphP[place].MaxSignalVelFeedbackUpdated = HydroDataPartialResult[source].maxSignalVelFeedbackUpdated;
#endif
#ifdef METAL_DIFFUSION
for(k = 0; k < NELEMENTS; k++)
SphP[place].MetalDiffusionB[k] += HydroDataPartialResult[source].MetalDiffusionB[k];
SphP[place].MetalDiffusionA += HydroDataPartialResult[source].MetalDiffusionA;
#endif
}
}
}
for(j = 0; j < NTask; j++)
if((j ^ ngrp) < NTask)
nbuffer[j] += nsend[(j ^ ngrp) * NTask + j];
}
tend = second();
timecommsumm += timediff(tstart, tend);
level = ngrp - 1;
}
MPI_Allgather(&ndone, 1, MPI_INT, ndonelist, 1, MPI_INT, MPI_COMM_WORLD);
for(j = 0; j < NTask; j++)
ntotleft -= ndonelist[j];
}
free(ndonelist);
free(nsend);
free(nsend_local);
free(nbuffer);
free(noffset);
/* do final operations on results */
tstart = second();
// now done in timestep.c
//#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
// for(i = 0; i < N_gas; i++)
// SphP[i].MaxSignalVel=dmax(SphP[i].MaxSignalVel,SphP[i].MaxSignalVelFeedbackUpdated);
//#endif
for(i = 0; i < N_gas; i++)
#ifdef SFR
if((P[i].Ti_endstep == All.Ti_Current) && (P[i].Type == 0))
#else
if(P[i].Ti_endstep == All.Ti_Current)
#endif
{
#ifdef DENSITY_INDEPENDENT_SPH
SphP[i].DtEntropy *= GAMMA_MINUS1 / (hubble_a2 * pow(SphP[i].EgyWtDensity, GAMMA_MINUS1));
#else
SphP[i].DtEntropy *= GAMMA_MINUS1 / (hubble_a2 * pow(SphP[i].Density, GAMMA_MINUS1));
#endif
#ifdef SPH_BND_PARTICLES
if(P[i].ID == 0)
{
SphP[i].DtEntropy = 0;
for(k = 0; k < 3; k++)
SphP[i].HydroAccel[k] = 0;
}
#endif
#ifdef COMPUTE_VELOCITY_DISPERSION
if (SphP[i].VelocityDispersion[0] != 0)
{
/* compute sigma r */
v1m = SphP[i].VelocityDispersion[1]/SphP[i].VelocityDispersion[0];
v2m = SphP[i].VelocityDispersion[2]/SphP[i].VelocityDispersion[0];
if (v2m > v1m*v1m)
SphP[i].OptVar1 = sqrt(v2m - v1m*v1m);
else
SphP[i].OptVar1 = 0.0;
}
else
SphP[i].OptVar1 = 0.0;
#endif
#ifdef OUTPUT_CONDUCTIVITY
SphP[i].OptVar2*= GAMMA_MINUS1 / (hubble_a2 * pow(SphP[i].Density, GAMMA_MINUS1)); /* to dA/dt */
if (SphP[i].OptVar2!=0)
SphP[i].OptVar2=SphP[i].Entropy/fabs(SphP[i].OptVar2); /* to time*/
else
SphP[i].OptVar2=0;
#endif
#ifdef ART_VISCO_CD
compute_art_visc(i);
#endif
}
tend = second();
timecomp += timediff(tstart, tend);
/* collect some timing information */
MPI_Reduce(&timecomp, &sumt, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&timecommsumm, &sumcomm, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&timeimbalance, &sumimbalance, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if(ThisTask == 0)
{
All.CPU_HydCompWalk += sumt / NTask;
All.CPU_HydCommSumm += sumcomm / NTask;
All.CPU_HydImbalance += sumimbalance / NTask;
}
#ifdef DETAILED_CPU_OUTPUT_IN_HYDRA
numlist = malloc(sizeof(int) * NTask);
timecomplist = malloc(sizeof(double) * NTask);
timecommsummlist = malloc(sizeof(double) * NTask);
timeimbalancelist = malloc(sizeof(double) * NTask);
MPI_Gather(&NumSphUpdate, 1, MPI_INT, numlist, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gather(&timecomp, 1, MPI_DOUBLE, timecomplist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&timecommsumm, 1, MPI_DOUBLE, timecommsummlist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&timeimbalance, 1, MPI_DOUBLE, timeimbalancelist, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if(ThisTask == 0)
{
fprintf(FdTimings, "\n hydra\n\n");
fprintf(FdTimings, "Nupdate ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12d ",numlist[i]); /* nombre de part par proc */
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timecomp ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timecomplist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timecommsumm ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timecommsummlist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "timeimbalance ");
for (i=0;i<NTask;i++)
fprintf(FdTimings, "%12g ",timeimbalancelist[i]);
fprintf(FdTimings, "\n");
fprintf(FdTimings, "\n");
}
free(timeimbalancelist);
free(timecommsummlist);
free(timecomplist);
free(numlist);
#endif
}
/*! This function is the 'core' of the SPH force computation. A target
* particle is specified which may either be local, or reside in the
* communication buffer.
*/
void hydro_evaluate(int target, int mode)
{
int j, k, n, timestep, startnode, numngb;
FLOAT *pos, *vel;
FLOAT mass, h_i, dhsmlDensityFactor, rho, pressure, f1, f2;
double acc[3], dtEntropy, maxSignalVel;
double dx, dy, dz, dvx, dvy, dvz;
double h_i2, hinv=1, hinv4;
double p_over_rho2_i, p_over_rho2_j, soundspeed_i, soundspeed_j;
double hfc, dwk_i, vdotr, vdotr2, visc, mu_ij, rho_ij=0, vsig;
double h_j, dwk_j, r, r2, u=0, hfc_visc;
int phase=0;
#ifdef FEEDBACK
int EnergySN;
double wk,wk_i,wk_j,uintspec,hinv3;
double dtEgySpecFeedback=0;
#endif
#ifdef WITH_ID_IN_HYDRA
int id;
#endif
#ifdef COMPUTE_VELOCITY_DISPERSION
double VelocityDispersion[VELOCITY_DISPERSION_SIZE];
for(k = 0; k < VELOCITY_DISPERSION_SIZE; k++)
VelocityDispersion[k]=0.0;
#endif
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
#ifdef ART_CONDUCTIVITY
double hfc_cond,vsig_u,vsig_u_max;
double Arho_i,Arho_j;
double u_i,u_j;
double normGradEnergyInt_i, normGradEnergyInt_j;
double dtEntropy_artcond;
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)|| defined(ART_VISCO_CD)
double alpha_i, alpha_j;
double alpha_ij;
double beta_ij;
double soundspeed_ij;
#ifdef ART_VISCO_CD
double wk,wk_i,wk_j,hinv3;
int ii, jj;
double DmatCD[3][3];
double TmatCD[3][3];
double dv_dot_dx;
double R_CD;
double sign_DiVel;
double maxSignalVelCD;
#endif
#endif
#ifdef DENSITY_INDEPENDENT_SPH
double egyrho, entvarpred;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
double p_over_rho2_iFeedbackUpdated,soundspeed_iFeedbackUpdated=0;
double p_over_rho2_jFeedbackUpdated,soundspeed_jFeedbackUpdated=0;
double maxSignalVelFeedbackUpdated,hfcFeedbackUpdated,hfc_viscFeedbackUpdated,viscFeedbackUpdated;
double accFeedbackUpdated[3];
FLOAT f1FeedbackUpdated,f2FeedbackUpdated;
FLOAT pressureFeedbackUpdated;
#ifdef DENSITY_INDEPENDENT_SPH
double pup;
#endif
#endif
#ifdef METAL_DIFFUSION
FLOAT MetalDiffusionCoeff;
double Kij=0;
double MetalDiffusionA=0;
double MetalDiffusionB[NELEMENTS];
for (k = 0;k < NELEMENTS; k++)
MetalDiffusionB[k]=0;
#endif
if(mode == 0)
{
pos = P[target].Pos;
vel = SphP[target].VelPred;
h_i = SphP[target].Hsml;
#ifdef FEEDBACK
EnergySN = SphP[target].EnergySN;
#endif
#ifdef WITH_ID_IN_HYDRA
id = P[target].ID;
#endif
mass = P[target].Mass;
dhsmlDensityFactor = SphP[target].DhsmlDensityFactor;
rho = SphP[target].Density;
pressure = SphP[target].Pressure;
timestep = P[target].Ti_endstep - P[target].Ti_begstep;
#ifdef DENSITY_INDEPENDENT_SPH
soundspeed_i = sqrt(GAMMA * pressure / SphP[target].EgyWtDensity);
#else
soundspeed_i = sqrt(GAMMA * pressure / rho);
#endif
f1 = fabs(SphP[target].DivVel) /
(fabs(SphP[target].DivVel) + SphP[target].CurlVel +
0.0001 * soundspeed_i / SphP[target].Hsml / fac_mu);
#ifdef ART_CONDUCTIVITY
normGradEnergyInt_i = sqrt( pow(SphP[target].GradEnergyInt[0],2)+pow(SphP[target].GradEnergyInt[1],2)+pow(SphP[target].GradEnergyInt[2],2));
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO) || defined(ART_VISCO_CD)
alpha_i = SphP[target].ArtBulkViscConst;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
egyrho = SphP[target].EgyWtDensity;
entvarpred = SphP[target].EntVarPred;
dhsmlDensityFactor = SphP[target].DhsmlEgyDensityFactor;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[target].DeltaEgySpec>0)
{
#ifdef DENSITY_INDEPENDENT_SPH
pressureFeedbackUpdated = updated_pressure_hydra(SphP[target].EntropyPred,SphP[target].EgyWtDensity,SphP[target].DeltaEgySpec);
soundspeed_iFeedbackUpdated = sqrt(GAMMA * pressureFeedbackUpdated / SphP[target].EgyWtDensity);
#else
pressureFeedbackUpdated = updated_pressure_hydra(SphP[target].EntropyPred,SphP[target].Density,SphP[target].DeltaEgySpec);
soundspeed_iFeedbackUpdated = sqrt(GAMMA * pressureFeedbackUpdated / rho);
#endif
f1FeedbackUpdated = fabs(SphP[target].DivVel) /
(fabs(SphP[target].DivVel) + SphP[target].CurlVel +
0.0001 * soundspeed_iFeedbackUpdated / SphP[target].Hsml / fac_mu);
}
else
{
pressureFeedbackUpdated = SphP[target].Pressure;
f1FeedbackUpdated = f1;
}
#endif
#ifdef METAL_DIFFUSION
MetalDiffusionCoeff = SphP[target].MetalDiffusionCoeff;
#endif
}
else
{
pos = HydroDataGet[target].Pos;
vel = HydroDataGet[target].Vel;
h_i = HydroDataGet[target].Hsml;
#ifdef FEEDBACK
EnergySN = HydroDataGet[target].EnergySN;
#endif
#ifdef WITH_ID_IN_HYDRA
id = HydroDataGet[target].ID;
#endif
mass = HydroDataGet[target].Mass;
dhsmlDensityFactor = HydroDataGet[target].DhsmlDensityFactor;
rho = HydroDataGet[target].Density;
pressure = HydroDataGet[target].Pressure;
timestep = HydroDataGet[target].Timestep;
#ifdef DENSITY_INDEPENDENT_SPH
soundspeed_i = sqrt(GAMMA * pressure / HydroDataGet[target].EgyRho);
#else
soundspeed_i = sqrt(GAMMA * pressure / rho);
#endif
f1 = HydroDataGet[target].F1;
#ifdef ART_CONDUCTIVITY
normGradEnergyInt_i = HydroDataGet[target].NormGradEnergyInt;
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)|| defined(ART_VISCO_CD)
alpha_i = HydroDataGet[target].ArtBulkViscConst;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
egyrho = HydroDataGet[target].EgyRho;
entvarpred = HydroDataGet[target].EntVarPred;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
pressureFeedbackUpdated = HydroDataGet[target].PressureFeedbackUpdated;
#endif
#ifdef METAL_DIFFUSION
MetalDiffusionCoeff = HydroDataGet[target].MetalDiffusionCoeff;
#endif
}
/* initialize variables before SPH loop is started */
acc[0] = acc[1] = acc[2] = dtEntropy = 0;
maxSignalVel = 0;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
accFeedbackUpdated[0] = accFeedbackUpdated[1] = accFeedbackUpdated[2] = 0;
maxSignalVelFeedbackUpdated = 0;
#endif
#ifdef FEEDBACK
dtEgySpecFeedback=0;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
p_over_rho2_i = pressure / (egyrho * egyrho);
#else
p_over_rho2_i = pressure / (rho * rho) * dhsmlDensityFactor;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
#ifdef DENSITY_INDEPENDENT_SPH
p_over_rho2_iFeedbackUpdated = pressureFeedbackUpdated / (egyrho * egyrho);
#else
p_over_rho2_iFeedbackUpdated = pressureFeedbackUpdated / (rho * rho) * dhsmlDensityFactor;
#endif
#endif
h_i2 = h_i * h_i;
#ifdef ART_CONDUCTIVITY
Arho_i = pressure/rho;
u_i = pressure/(rho*GAMMA_MINUS1);
dtEntropy_artcond=0;
#endif
#ifdef ART_VISCO_CD
for (ii = 0; ii < 3; ii++)
for (jj = 0; jj < 3; jj++)
{
DmatCD[ii][jj] = 0.;
TmatCD[ii][jj] = 0.;
}
R_CD = 0.;
maxSignalVelCD=0;
#endif
/* Now start the actual SPH computation for this particle */
startnode = All.MaxPart;
do
{
numngb = ngb_treefind_pairs(&pos[0], h_i, phase, &startnode);
for(n = 0; n < numngb; n++)
{
j = Ngblist[n];
dx = pos[0] - P[j].Pos[0];
dy = pos[1] - P[j].Pos[1];
dz = pos[2] - P[j].Pos[2];
#ifdef PERIODIC /* find the closest image in the given box size */
if(dx > boxHalf_X)
dx -= boxSize_X;
if(dx < -boxHalf_X)
dx += boxSize_X;
if(dy > boxHalf_Y)
dy -= boxSize_Y;
if(dy < -boxHalf_Y)
dy += boxSize_Y;
if(dz > boxHalf_Z)
dz -= boxSize_Z;
if(dz < -boxHalf_Z)
dz += boxSize_Z;
#endif
r2 = dx * dx + dy * dy + dz * dz;
h_j = SphP[j].Hsml;
if(r2 < h_i2 || r2 < h_j * h_j)
{
r = sqrt(r2);
if(r > 0)
{
#ifdef DENSITY_INDEPENDENT_SPH
p_over_rho2_j = SphP[j].Pressure / (SphP[j].EgyWtDensity * SphP[j].EgyWtDensity);
soundspeed_j = sqrt(GAMMA * SphP[j].Pressure / SphP[j].EgyWtDensity);
#else
p_over_rho2_j = SphP[j].Pressure / (SphP[j].Density * SphP[j].Density);
soundspeed_j = sqrt(GAMMA * p_over_rho2_j * SphP[j].Density);
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[j].DeltaEgySpec>0) /* the particle is touch by feedback */
{
#ifdef DENSITY_INDEPENDENT_SPH
pup = updated_pressure_hydra(SphP[j].EntropyPred,SphP[j].EgyWtDensity,SphP[j].DeltaEgySpec);
p_over_rho2_jFeedbackUpdated = pup / (SphP[j].EgyWtDensity * SphP[j].EgyWtDensity);
soundspeed_jFeedbackUpdated = sqrt(GAMMA * pup / SphP[j].EgyWtDensity);
#else
p_over_rho2_jFeedbackUpdated = updated_pressure_hydra(SphP[j].EntropyPred,SphP[j].Density,SphP[j].DeltaEgySpec) / (SphP[j].Density * SphP[j].Density);
soundspeed_jFeedbackUpdated = sqrt(GAMMA * p_over_rho2_jFeedbackUpdated * SphP[j].Density);
#endif
}
else
{
p_over_rho2_jFeedbackUpdated = p_over_rho2_j;
soundspeed_jFeedbackUpdated = soundspeed_j;
}
#endif
dvx = vel[0] - SphP[j].VelPred[0];
dvy = vel[1] - SphP[j].VelPred[1];
dvz = vel[2] - SphP[j].VelPred[2];
vdotr = dx * dvx + dy * dvy + dz * dvz;
if(All.ComovingIntegrationOn)
vdotr2 = vdotr + hubble_a2 * r2;
else
vdotr2 = vdotr;
if(r2 < h_i2)
{
hinv = 1.0 / h_i;
#ifndef TWODIMS
hinv4 = hinv * hinv * hinv * hinv;
#else
hinv4 = hinv * hinv * hinv / boxSize_Z;
#endif
u = r * hinv;
if(u < 0.5)
dwk_i = hinv4 * u * (KERNEL_COEFF_3 * u - KERNEL_COEFF_4);
else
dwk_i = hinv4 * KERNEL_COEFF_6 * (1.0 - u) * (1.0 - u);
}
else
{
dwk_i = 0;
}
if(r2 < h_j * h_j)
{
hinv = 1.0 / h_j;
#ifndef TWODIMS
hinv4 = hinv * hinv * hinv * hinv;
#else
hinv4 = hinv * hinv * hinv / boxSize_Z;
#endif
u = r * hinv;
if(u < 0.5)
dwk_j = hinv4 * u * (KERNEL_COEFF_3 * u - KERNEL_COEFF_4);
else
dwk_j = hinv4 * KERNEL_COEFF_6 * (1.0 - u) * (1.0 - u);
}
else
{
dwk_j = 0;
}
if(soundspeed_i + soundspeed_j > maxSignalVel)
maxSignalVel = soundspeed_i + soundspeed_j;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[j].DeltaEgySpec>0) /* the particle is touch by feedback */
{
if(soundspeed_iFeedbackUpdated + soundspeed_jFeedbackUpdated > maxSignalVelFeedbackUpdated)
maxSignalVelFeedbackUpdated = soundspeed_iFeedbackUpdated + soundspeed_jFeedbackUpdated;
}
#endif
/*********************************/
/* standard form of viscosity */
/*********************************/
#if !defined(ART_VISCO_MM) && !defined(ART_VISCO_RO) && !defined(ART_VISCO_CD)
visc = artificial_viscosity(r,vdotr2,soundspeed_i,soundspeed_j,dwk_i,dwk_j,timestep,j,mass,rho,f1,&maxSignalVel);
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[j].DeltaEgySpec>0)
viscFeedbackUpdated = artificial_viscosity(r,vdotr2,soundspeed_iFeedbackUpdated,soundspeed_jFeedbackUpdated,dwk_i,dwk_j,timestep,j,mass,rho,f1FeedbackUpdated,&maxSignalVelFeedbackUpdated);
#endif
#endif
/**************************************/
/* alternative form of viscosity RO MM*/
/**************************************/
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)
visc = artificial_viscosity_improved(r,vdotr2,soundspeed_i,soundspeed_j,dwk_i,dwk_j,h_i,alpha_i,timestep,j,mass,rho,f1,&maxSignalVel);
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[j].DeltaEgySpec>0)
viscFeedbackUpdated = artificial_viscosity_improved(r,vdotr2,soundspeed_iFeedbackUpdated,soundspeed_jFeedbackUpdated,dwk_i,dwk_j,h_i,alpha_i,timestep,j,mass,rho,f1FeedbackUpdated,&maxSignalVelFeedbackUpdated);
#endif
#endif
/**************************************/
/* alternative form of viscosity CD */
/**************************************/
#if defined(ART_VISCO_CD)
visc = artificial_viscosity_CD(r,vdotr2,soundspeed_i,soundspeed_j,dwk_i,dwk_j,timestep,j,mass,rho,f1,&maxSignalVel);
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (SphP[j].DeltaEgySpec>0)
viscFeedbackUpdated = artificial_viscosity_CD(r,vdotr2,soundspeed_iFeedbackUpdated,soundspeed_jFeedbackUpdated,dwk_i,dwk_j,timestep,j,mass,rho,f1FeedbackUpdated,&maxSignalVelFeedbackUpdated);
#endif
#endif
/*********************************/
/* now finish sph */
/*********************************/
#ifndef DENSITY_INDEPENDENT_SPH
p_over_rho2_j *= SphP[j].DhsmlDensityFactor;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
p_over_rho2_jFeedbackUpdated *= SphP[j].DhsmlDensityFactor;
#endif
#endif
hfc_visc = 0.5 * P[j].Mass * visc * (dwk_i + dwk_j) / r;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
hfc_viscFeedbackUpdated = 0.5 * P[j].Mass * viscFeedbackUpdated * (dwk_i + dwk_j) / r;
#endif
#ifdef DENSITY_INDEPENDENT_SPH
hfc = hfc_visc;
/* leading-order term */
hfc += P[j].Mass *
(dwk_i*p_over_rho2_i*SphP[j].EntVarPred/entvarpred +
dwk_j*p_over_rho2_j*entvarpred/SphP[j].EntVarPred) / r;
/* grad-h corrections */
hfc += P[j].Mass *
(dwk_i*p_over_rho2_i*egyrho/rho*dhsmlDensityFactor +
dwk_j*p_over_rho2_j*SphP[j].EgyWtDensity/SphP[j].Density*SphP[j].DhsmlEgyDensityFactor) / r;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
hfcFeedbackUpdated = hfc_viscFeedbackUpdated;
/* leading-order term */
hfcFeedbackUpdated += P[j].Mass *
(dwk_i*p_over_rho2_iFeedbackUpdated*SphP[j].EntVarPred/entvarpred +
dwk_j*p_over_rho2_jFeedbackUpdated*entvarpred/SphP[j].EntVarPred) / r;
/* grad-h corrections */
hfcFeedbackUpdated += P[j].Mass *
(dwk_i*p_over_rho2_iFeedbackUpdated*egyrho/rho*dhsmlDensityFactor +
dwk_j*p_over_rho2_jFeedbackUpdated*SphP[j].EgyWtDensity/SphP[j].Density*SphP[j].DhsmlEgyDensityFactor) / r;
#endif
#else /* if not DENSITY_INDEPENDENT_SPH */
hfc = hfc_visc + P[j].Mass * (p_over_rho2_i * dwk_i + p_over_rho2_j * dwk_j) / r;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
hfcFeedbackUpdated = hfc_viscFeedbackUpdated + P[j].Mass * (p_over_rho2_iFeedbackUpdated * dwk_i + p_over_rho2_jFeedbackUpdated * dwk_j) / r;
#endif
#endif /* DENSITY_INDEPENDENT_SPH */
acc[0] -= hfc * dx;
acc[1] -= hfc * dy;
acc[2] -= hfc * dz;
dtEntropy += 0.5 * hfc_visc * vdotr2;
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
accFeedbackUpdated[0] -= hfcFeedbackUpdated * dx;
accFeedbackUpdated[1] -= hfcFeedbackUpdated * dy;
accFeedbackUpdated[2] -= hfcFeedbackUpdated * dz;
if(P[j].Ti_endstep == All.Ti_Current)
{
if(SphP[j].DeltaEgySpec == 0) /* the particle is active but not affected by feedback */
SphP[j].DeltaEgySpec = -1;
if(maxSignalVelFeedbackUpdated > SphP[j].MaxSignalVelFeedbackUpdated)
{
SphP[j].MaxSignalVelFeedbackUpdated = maxSignalVelFeedbackUpdated;
}
SphP[j].FeedbackUpdatedAccel[0] -= hfcFeedbackUpdated * dx;
SphP[j].FeedbackUpdatedAccel[1] -= hfcFeedbackUpdated * dy;
SphP[j].FeedbackUpdatedAccel[2] -= hfcFeedbackUpdated * dz;
}
#endif
/*********************************/
/* prediction for the next step */
/*********************************/
#ifdef ART_VISCO_CD
artificial_viscosity_CD_prediction(r,vdotr2,soundspeed_i,soundspeed_j,dwk_i,dwk_j,timestep,j,mass,rho,f1,&maxSignalVel);
#endif
/*****************************************/
/* ART CONDUCTIVITY */
/*****************************************/
#ifdef ART_CONDUCTIVITY
mu_ij = fac_mu * vdotr2 / r;
vsig_u = soundspeed_i + soundspeed_j - 3 * mu_ij;
Arho_j = SphP[j].Pressure / SphP[j].Density;
rho_ij = 0.5 * (rho + SphP[j].Density);
/* switch */
normGradEnergyInt_j = sqrt( pow(SphP[j].GradEnergyInt[0],2)+pow(SphP[j].GradEnergyInt[1],2)+pow(SphP[j].GradEnergyInt[2],2));
u_j = SphP[j].Pressure/(SphP[j].Density*GAMMA_MINUS1);
hfc_cond = P[j].Mass * All.ArtCondConst * vsig_u * (Arho_i-Arho_j)/ rho_ij * 0.5*(dwk_i + dwk_j);
dtEntropy_artcond = hfc_cond / GAMMA_MINUS1;
dtEntropy += dtEntropy_artcond ;
#endif
/*****************************************/
/* METAL DIFFUSION */
/*****************************************/
#ifdef METAL_DIFFUSION
if(MetalDiffusionCoeff!=0 && SphP[j].MetalDiffusionCoeff!=0)
{
Kij = P[j].Mass / (SphP[j].Density * rho ) * 4.0 * MetalDiffusionCoeff * SphP[j].MetalDiffusionCoeff / ( MetalDiffusionCoeff + SphP[j].MetalDiffusionCoeff ) * 0.5 * (dwk_i + dwk_j) / r ;
MetalDiffusionA += Kij;
for(k=0;k<NELEMENTS;k++)
MetalDiffusionB[k] += Kij * SphP[j].Metal[k] ;
}
#endif
/*****************************************/
/* FEEDBACK INTERACTION */
/*****************************************/
#ifdef FEEDBACK
rho_ij = 0.5 * (rho + SphP[j].Density);
if(P[j].Ti_endstep == All.Ti_Current)
{
/* additional feedback entropy */
if ((EnergySN > 0)||(SphP[j].EnergySN > 0))
{
/* find the thermal specific energy to release */
uintspec = 0.;
if (EnergySN > 0)
{
uintspec = 0;
}
if (SphP[j].EnergySN > 0)
{
uintspec += SphP[j].EnergySN * (1-All.SupernovaFractionInEgyKin)/ mass;
}
if(r2 < h_i2)
{
hinv = 1.0 / h_i;
hinv3 = hinv * hinv * hinv ;
u = r * hinv;
if(u < 0.5)
wk_i = hinv3 * (KERNEL_COEFF_1 + KERNEL_COEFF_2 * (u - 1) * u * u);
else
wk_i = hinv3 * KERNEL_COEFF_5 * (1.0 - u) * (1.0 - u) * (1.0 - u);
}
else
wk_i = 0;
if(r2 < h_j * h_j)
{
hinv = 1.0 / h_j;
hinv3 = hinv * hinv * hinv ;
u = r * hinv;
if(u < 0.5)
wk_j = hinv3 * (KERNEL_COEFF_1 + KERNEL_COEFF_2 * (u - 1) * u * u);
else
wk_j = hinv3 * KERNEL_COEFF_5 * (1.0 - u) * (1.0 - u) * (1.0 - u);
}
else
wk_j = 0;
wk = 0.5*(wk_i+wk_j);
/* dt in physical units */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval/ hubble_a;
if(dt <= 0);
uintspec = 0;
/* thermal feedback */
uintspec = (uintspec/dt) *wk *0.5*(mass + P[j].Mass) /rho_ij *fac_pow ;
dtEntropy += uintspec;
dtEgySpecFeedback += uintspec;
}
}
#endif /* FEEDBACK */
}
}
}
}
while(startnode >= 0);
/* Now collect the result at the right place */
if(mode == 0)
{
for(k = 0; k < 3; k++)
SphP[target].HydroAccel[k] = acc[k];
SphP[target].DtEntropy = dtEntropy;
#ifdef FEEDBACK
SphP[target].DtEgySpecFeedback = dtEgySpecFeedback;
#endif
SphP[target].MaxSignalVel = maxSignalVel;
#ifdef COMPUTE_VELOCITY_DISPERSION
for(k = 0; k < VELOCITY_DISPERSION_SIZE; k++)
SphP[target].VelocityDispersion[k] = VelocityDispersion[k];
#endif
#ifdef OUTPUT_CONDUCTIVITY
SphP[target].OptVar2 = dtEntropy_artcond;
#endif
#ifdef ART_VISCO_CD
/*collect DmatCD, TmatCD*/
for (ii = 0; ii < 3; ii++)
for (jj = 0; jj < 3; jj++)
{
SphP[target].DmatCD[ii][jj] = DmatCD[ii][jj];
SphP[target].TmatCD[ii][jj] = TmatCD[ii][jj];
}
SphP[target].R_CD = R_CD;
SphP[target].MaxSignalVelCD = maxSignalVelCD;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
if (maxSignalVelFeedbackUpdated>SphP[target].MaxSignalVelFeedbackUpdated)
SphP[target].MaxSignalVelFeedbackUpdated = maxSignalVelFeedbackUpdated;
for(k = 0; k < 3; k++)
SphP[target].FeedbackUpdatedAccel[k] = accFeedbackUpdated[k];
#endif
#ifdef METAL_DIFFUSION
SphP[target].MetalDiffusionA = MetalDiffusionA;
for(k = 0; k < NELEMENTS; k++)
SphP[target].MetalDiffusionB[k] = MetalDiffusionB[k];
#endif
}
else
{
for(k = 0; k < 3; k++)
HydroDataResult[target].Acc[k] = acc[k];
HydroDataResult[target].DtEntropy = dtEntropy;
#ifdef FEEDBACK
HydroDataResult[target].DtEgySpecFeedback = dtEgySpecFeedback;
#endif
HydroDataResult[target].MaxSignalVel = maxSignalVel;
#ifdef COMPUTE_VELOCITY_DISPERSION
for(k = 0; k < VELOCITY_DISPERSION_SIZE; k++)
HydroDataResult[target].VelocityDispersion[k] = VelocityDispersion[k];
#endif
#ifdef OUTPUT_CONDUCTIVITY
HydroDataResult[target].OptVar2 = dtEntropy_artcond;
#endif
#ifdef ART_VISCO_CD
/*collect DmatCD, TmatCD*/
for (ii = 0; ii < 3; ii++)
for (jj = 0; jj < 3; jj++)
{
HydroDataResult[target].DmatCD[ii][jj] = DmatCD[ii][jj];
HydroDataResult[target].TmatCD[ii][jj] = TmatCD[ii][jj];
}
HydroDataResult[target].R_CD = R_CD;
HydroDataResult[target].MaxSignalVelCD = maxSignalVelCD;
#endif
#if defined(TIMESTEP_UPDATE_FOR_FEEDBACK) && defined(CHIMIE_THERMAL_FEEDBACK)
HydroDataResult[target].maxSignalVelFeedbackUpdated = maxSignalVelFeedbackUpdated;
for(k = 0; k < 3; k++)
HydroDataResult[target].AccFeedbackUpdated[k] = accFeedbackUpdated[k];
#endif
#ifdef METAL_DIFFUSION
HydroDataResult[target].MetalDiffusionA = MetalDiffusionA;
for(k = 0; k < NELEMENTS; k++)
HydroDataResult[target].MetalDiffusionB[k] = MetalDiffusionB[k];
#endif
}
}
/*! This is a comparison kernel for a sort routine, which is used to group
* particles that are going to be exported to the same CPU.
*/
int hydro_compare_key(const void *a, const void *b)
{
if(((struct hydrodata_in *) a)->Task < (((struct hydrodata_in *) b)->Task))
return -1;
if(((struct hydrodata_in *) a)->Task > (((struct hydrodata_in *) b)->Task))
return +1;
return 0;
}
/*! default from Gadget-2
*/
double artificial_viscosity(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
if(vdotr2 < 0) /* ... artificial viscosity */
{
mu_ij = fac_mu * vdotr2 / r; /* note: this is negative! */
vsig = soundspeed_i + soundspeed_j - 3 * mu_ij;
if(vsig > *maxSignalVel)
*maxSignalVel = vsig;
rho_ij = 0.5 * (rho + SphP[j].Density);
f2 = fabs(SphP[j].DivVel) / (fabs(SphP[j].DivVel) + SphP[j].CurlVel + 0.0001 * soundspeed_j / fac_mu / SphP[j].Hsml);
visc = 0.25 * All.ArtBulkViscConst * vsig * (-mu_ij) / rho_ij * (f1 + f2);
/* .... end artificial viscosity evaluation */
#ifndef NOVISCOSITYLIMITER
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 / (0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
#endif
}
else
visc = 0;
return visc;
}
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)
/*! Tiret version
*/
double artificial_viscosity_improved_old_tiret(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
double alpha_i,alpha_j,alpha_ij,beta_ij,soundspeed_ij;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
if(vdotr2 < 0) /* ... artificial viscosity */
{
alpha_j = SphP[j].ArtBulkViscConst;
alpha_ij = 0.5*(alpha_i + alpha_j);
beta_ij = 3/2. * alpha_ij; /* 3/2 is compatible with Springel 05 */
mu_ij = fac_mu * vdotr2 / r; /* note: this is negative! */
vsig = soundspeed_i + soundspeed_j - 2*beta_ij/alpha_ij * mu_ij;
if(vsig > *maxSignalVel)
*maxSignalVel = vsig;
soundspeed_ij = 0.5 * (soundspeed_i + soundspeed_j);
f2 =
fabs(SphP[j].DivVel) / (fabs(SphP[j].DivVel) + SphP[j].CurlVel +
0.0001 * soundspeed_j / fac_mu / SphP[j].Hsml);
rho_ij = 0.5 * (rho + SphP[j].Density);
visc = (- alpha_ij * soundspeed_ij * mu_ij + beta_ij * mu_ij * mu_ij) / rho_ij * 0.5*(f1 + f2) ;
#ifndef NOVISCOSITYLIMITER
if(vdotr2 < 0)
{
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 /
(0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
}
#endif
}
else
visc = 0;
return visc;
}
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)
/*! Monaghan + variation of coefficient (!!! this may diverge for small rij)
*/
double artificial_viscosity_improved_old_Arnaudon(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,double h_i,double alpha_i,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
double alpha_j,alpha_ij,beta_ij,soundspeed_ij;
double h_ij,r2;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
if(vdotr2 < 0) /* ... artificial viscosity */
{
r2 = r*r;
h_ij= 0.5 * (h_i + SphP[j].Hsml);
mu_ij = h_ij* fac_mu * vdotr2 / r2;
alpha_j = SphP[j].ArtBulkViscConst;
alpha_ij = 0.5*(alpha_i + alpha_j);
beta_ij = 2 * alpha_ij; /* 3/2 is compatible with Springel 05 */
soundspeed_ij = 0.5 * (soundspeed_i + soundspeed_j);
rho_ij = 0.5 * (rho + SphP[j].Density);
f2 =
fabs(SphP[j].DivVel) / (fabs(SphP[j].DivVel) + SphP[j].CurlVel +
0.0001 * soundspeed_j / fac_mu / SphP[j].Hsml);
visc = (-alpha_ij *soundspeed_ij + beta_ij*mu_ij )*mu_ij / rho_ij *0.5 *(f1 + f2);
/* .... end artificial viscosity evaluation */
#ifndef NOVISCOSITYLIMITER
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 /
(0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
#endif
}
else
visc = 0;
return visc;
}
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)
/*! Rosswog (with divergence corrected)
*/
double artificial_viscosity_improved(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,double h_i,double alpha_i,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
double alpha_j,alpha_ij,beta_ij,soundspeed_ij;
double h_ij,r2;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
if(vdotr2 < 0) /* ... artificial viscosity */
{
r2 = r*r;
h_ij= 0.5 * (h_i + SphP[j].Hsml);
mu_ij = h_ij* fac_mu * vdotr2 / (r2+0.01*(h_ij*h_ij));
vsig = soundspeed_i + soundspeed_j - 3 * mu_ij;
if(vsig > *maxSignalVel)
*maxSignalVel = vsig;
alpha_j = SphP[j].ArtBulkViscConst;
alpha_ij = 0.5*(alpha_i + alpha_j);
beta_ij = 2 * alpha_ij; /* 3/2 is compatible with Springel 05 */
soundspeed_ij = 0.5 * (soundspeed_i + soundspeed_j);
rho_ij = 0.5 * (rho + SphP[j].Density);
f2 =
fabs(SphP[j].DivVel) / (fabs(SphP[j].DivVel) + SphP[j].CurlVel +
0.0001 * soundspeed_j / fac_mu / SphP[j].Hsml);
visc = (-alpha_ij *soundspeed_ij + beta_ij*mu_ij )*mu_ij / rho_ij *0.5 *(f1 + f2);
/* .... end artificial viscosity evaluation */
#ifndef NOVISCOSITYLIMITER
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 /
(0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
#endif
}
else
visc = 0;
return visc;
}
#endif
#if defined(ART_VISCO_MM)|| defined(ART_VISCO_RO)
/*! Springel + Rosswog
*/
double artificial_viscosity_improved_springel(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,double h_i,double alpha_i,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
double alpha_j,alpha_ij,beta_ij,soundspeed_ij;
double h_ij,r2;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
if(vdotr2 < 0) /* ... artificial viscosity */
{
alpha_j = SphP[j].ArtBulkViscConst;
alpha_ij = 0.5*(alpha_i + alpha_j);
mu_ij = fac_mu * vdotr2 / r; /* note: this is negative! */
vsig = soundspeed_i + soundspeed_j - 3 * mu_ij;
if(vsig > *maxSignalVel)
*maxSignalVel = vsig;
rho_ij = 0.5 * (rho + SphP[j].Density);
f2 = fabs(SphP[j].DivVel) / (fabs(SphP[j].DivVel) + SphP[j].CurlVel + 0.0001 * soundspeed_j / fac_mu / SphP[j].Hsml);
visc = 0.25 * alpha_ij * vsig * (-mu_ij) / rho_ij * (f1 + f2);
/* .... end artificial viscosity evaluation */
#ifndef NOVISCOSITYLIMITER
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 / (0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
#endif
}
else
visc = 0;
return visc;
}
#endif
#if defined(ART_VISCO_CD)
/*! Cullen-Dehnen artificial viscosity
*/
double artificial_viscosity_CD(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
double visc,vsig,rho_ij,mu_ij;
FLOAT f2;
#ifndef NOVISCOSITYLIMITER
double dt;
#endif
alpha_j = SphP[j].ArtBulkViscConst;
alpha_ij = 0.5*(alpha_i + alpha_j);
beta_ij = 3/2. * alpha_ij;
mu_ij = fac_mu * vdotr2 / r; /* note: this is negative! */
vsig = soundspeed_i + soundspeed_j - 2*beta_ij/alpha_ij * mu_ij;
if(vsig > maxSignalVel)
maxSignalVel = vsig;
soundspeed_ij = 0.5 * (soundspeed_i + soundspeed_j);
rho_ij = 0.5 * (rho + SphP[j].Density);
visc = (- alpha_ij * soundspeed_ij * mu_ij + beta_ij * mu_ij * mu_ij) / rho_ij;
#ifndef NOVISCOSITYLIMITER
if(vdotr2 < 0)
{
/* make sure that viscous acceleration is not too large */
dt = imax(timestep, (P[j].Ti_endstep - P[j].Ti_begstep)) * All.Timebase_interval;
if(dt > 0 && (dwk_i + dwk_j) < 0)
{
visc = dmin(visc, 0.5 * fac_vsic_fix * vdotr2 /
(0.5 * (mass + P[j].Mass) * (dwk_i + dwk_j) * r * dt));
}
}
#endif
return visc;
}
#endif
#if defined(ART_VISCO_CD)
/*! Cullen-Dehnen artificial viscosity
*/
double artificial_viscosity_CD_prediction(double r,double vdotr2,double soundspeed_i,double soundspeed_j,double dwk_i,double dwk_j,double mu_ij,int timestep,int j,FLOAT mass,FLOAT rho,FLOAT f1,double *maxSignalVel)
{
/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING
This part is not finished and should not compile.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING * /
/* COMPUTE wk_i, wk_j, wk */
if(r2 < h_i2)
{
hinv = 1.0 / h_i;
hinv3 = hinv * hinv * hinv ;
u = r * hinv;
if(u < 0.5)
wk_i = hinv3 * (KERNEL_COEFF_1 + KERNEL_COEFF_2 * (u - 1) * u * u);
else
wk_i = hinv3 * KERNEL_COEFF_5 * (1.0 - u) * (1.0 - u) * (1.0 - u);
}
else
wk_i = 0;
if(r2 < h_j * h_j)
{
hinv = 1.0 / h_j;
hinv3 = hinv * hinv * hinv ;
u = r * hinv;
if(u < 0.5)
wk_j = hinv3 * (KERNEL_COEFF_1 + KERNEL_COEFF_2 * (u - 1) * u * u);
else
wk_j = hinv3 * KERNEL_COEFF_5 * (1.0 - u) * (1.0 - u) * (1.0 - u);
}
else
wk_j = 0;
/* wk = 0.5*(wk_i+wk_j); */
wk = 0.5*(dwk_i + dwk_j)/r;
/* CHOICE OF THE WEIGHT */
wk = P[j].Mass * wk / SphP[j].Density;
/* COMPUTE the matrix Di, Ti */
DmatCD[0][0] += dvx * dx * wk;
DmatCD[1][0] += dvy * dx * wk;
DmatCD[2][0] += dvz * dx * wk;
DmatCD[0][1] += dvx * dy * wk;
DmatCD[1][1] += dvy * dy * wk;
DmatCD[2][1] += dvz * dy * wk;
DmatCD[0][2] += dvx * dz * wk;
DmatCD[1][2] += dvy * dz * wk;
DmatCD[2][2] += dvz * dz * wk;
TmatCD[0][0] += dx * dx * wk;
TmatCD[1][0] += dy * dx * wk;
TmatCD[2][0] += dz * dx * wk;
TmatCD[0][1] += dx * dy * wk;
TmatCD[1][1] += dy * dy * wk;
TmatCD[2][1] += dz * dy * wk;
TmatCD[0][2] += dx * dz * wk;
TmatCD[1][2] += dy * dz * wk;
TmatCD[2][2] += dz * dz * wk;
/* COMPUTE maxSignalVel */
dv_dot_dx = dvx * dx + dvy * dy + dvz * dz;
vsig = soundspeed_ij - dmin(0., dv_dot_dx);
if(vsig > maxSignalVelCD)
maxSignalVelCD = vsig;
/* compute chock indicator */
if (SphP[j].DiVelAccurate>0.)
sign_DiVel = 1.;
else
sign_DiVel = -1.;
R_CD += 0.5 * sign_DiVel * P[j].Mass * (wk_i + wk_j);
}
#endif
#ifdef TIMESTEP_UPDATE_FOR_FEEDBACK
/*! This function return the pressure as a function
* of entropy and density, but add the contribution
* of the feedback energy.
*/
FLOAT updated_pressure_hydra(FLOAT EntropyPred,FLOAT Density,FLOAT DeltaEgySpec)
{
FLOAT pressure;
FLOAT EgySpec,EgySpecUpdated;
/* energy from entropy */
EgySpec = EntropyPred / GAMMA_MINUS1 * pow(Density*a3inv, GAMMA_MINUS1);
EgySpecUpdated = EgySpec + DeltaEgySpec;
/* pressure */
pressure = GAMMA_MINUS1 * Density * EgySpecUpdated / pow(a3inv, GAMMA_MINUS1);
return pressure;
}
#endif
#ifdef JEANS_PRESSURE_FLOOR
double JeansPressureFloor(int i)
{
double Pjeans;
double density;
#ifdef DENSITY_INDEPENDENT_SPH
density = SphP[i].EgyWtDensity;
#else
density = SphP[i].Density;
#endif
#ifdef AGORA
Pjeans = 4/PI * All.JeansMassFactor * (All.SofteningTable[0]*All.SofteningTable[0]) * (density*density) * All.G/GAMMA;
#else
Pjeans = 4/PI * All.JeansMassFactor * (SphP[i].Hsml*SphP[i].Hsml) * (density*density) * All.G/GAMMA;
-#endif
+
+
+#ifdef JEANS_PRESSURE_FLOOR_INCLUDE_VELOCITY_DISP
+
+ double Psigma;
+
+ Psigma = SphP[i].Density * SphP[i].RmsSpeed/GAMMA; /* SphP[i].RmsSpeed = Sigma^2 */
+
+ if ((Pjeans-Psigma) > 0)
+ Pjeans = Pjeans-Psigma;
+#endif
+
+#endif /* AGORA */
+
+
Pjeans = Pjeans* ap3g4;
return Pjeans;
}
#endif
diff --git a/src/python_interface.c b/src/python_interface.c
index 0727628..1d39ec4 100644
--- a/src/python_interface.c
+++ b/src/python_interface.c
@@ -1,4918 +1,4918 @@
#ifdef PY_INTERFACE
#include <Python.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <numpy/arrayobject.h>
#include <mpi.h>
#include "allvars.h"
#include "proto.h"
#define TO_INT(a) ( (PyArrayObject*) PyArray_CastToType(a, PyArray_DescrFromType(NPY_INT) ,0) )
#define TO_DOUBLE(a) ( (PyArrayObject*) PyArray_CastToType(a, PyArray_DescrFromType(NPY_DOUBLE) ,0) )
#define TO_FLOAT(a) ( (PyArrayObject*) PyArray_CastToType(a, PyArray_DescrFromType(NPY_FLOAT) ,0) )
static int Init()
{
/* main.c */
RestartFlag = 0;
All.CPU_TreeConstruction = All.CPU_TreeWalk = All.CPU_Gravity = All.CPU_Potential = All.CPU_Domain =
All.CPU_Snapshot = All.CPU_Total = All.CPU_CommSum = All.CPU_Imbalance = All.CPU_Hydro =
All.CPU_HydCompWalk = All.CPU_HydCommSumm = All.CPU_HydImbalance =
All.CPU_EnsureNgb = All.CPU_Predict = All.CPU_TimeLine = All.CPU_PM = All.CPU_Peano = 0;
CPUThisRun = 0;
/* from init.c, after read ic */
int i, j;
double a3;
All.Time = All.TimeBegin;
All.Ti_Current = 0;
if(All.ComovingIntegrationOn)
{
All.Timebase_interval = (log(All.TimeMax) - log(All.TimeBegin)) / TIMEBASE;
a3 = All.Time * All.Time * All.Time;
}
else
{
All.Timebase_interval = (All.TimeMax - All.TimeBegin) / TIMEBASE;
a3 = 1;
}
set_softenings();
All.NumCurrentTiStep = 0; /* setup some counters */
All.SnapshotFileCount = 0;
if(RestartFlag == 2)
All.SnapshotFileCount = atoi(All.InitCondFile + strlen(All.InitCondFile) - 3) + 1;
All.TotNumOfForces = 0;
All.NumForcesSinceLastDomainDecomp = 0;
if(All.ComovingIntegrationOn)
if(All.PeriodicBoundariesOn == 1)
check_omega();
All.TimeLastStatistics = All.TimeBegin - All.TimeBetStatistics;
#ifdef AGN_ACCRETION
All.TimeLastAccretion = All.TimeBegin - All.TimeBetAccretion;
All.LastMTotInRa = 0;
#endif
#ifdef BONDI_ACCRETION
All.BondiTimeLast = All.TimeBegin - All.BondiTimeBet;
#endif
#ifdef CHIMIE
#ifdef CHIMIE_TIMEBET
All.ChimieTimeLastChimie = All.TimeBegin - All.ChimieTimeBetChimie;
#endif
#endif
#ifdef FOF
All.FoF_TimeLastFoF = All.TimeBegin - All.FoF_TimeBetFoF;
#endif
#ifdef BUBBLES
All.EnergyBubbles=0;
#endif
if(All.ComovingIntegrationOn) /* change to new velocity variable */
{
for(i = 0; i < NumPart; i++)
for(j = 0; j < 3; j++)
P[i].Vel[j] *= sqrt(All.Time) * All.Time;
}
for(i = 0; i < NumPart; i++) /* start-up initialization */
{
for(j = 0; j < 3; j++)
P[i].GravAccel[j] = 0;
#ifdef PMGRID
for(j = 0; j < 3; j++)
P[i].GravPM[j] = 0;
#endif
P[i].Ti_endstep = 0;
P[i].Ti_begstep = 0;
P[i].OldAcc = 0;
P[i].GravCost = 1;
P[i].Potential = 0;
}
#ifdef PMGRID
All.PM_Ti_endstep = All.PM_Ti_begstep = 0;
#endif
#ifdef FLEXSTEPS
All.PresentMinStep = TIMEBASE;
for(i = 0; i < NumPart; i++) /* start-up initialization */
{
P[i].FlexStepGrp = (int) (TIMEBASE * get_random_number(P[i].ID));
}
#endif
for(i = 0; i < N_gas; i++) /* initialize sph_properties */
{
for(j = 0; j < 3; j++)
{
SphP[i].VelPred[j] = P[i].Vel[j];
SphP[i].HydroAccel[j] = 0;
}
SphP[i].DtEntropy = 0;
if(RestartFlag == 0)
{
SphP[i].Hsml = 0;
SphP[i].Density = -1;
}
}
ngb_treeallocate(MAX_NGB);
force_treeallocate(All.TreeAllocFactor * All.MaxPart, All.MaxPart);
All.NumForcesSinceLastDomainDecomp = 1 + All.TotNumPart * All.TreeDomainUpdateFrequency;
Flag_FullStep = 1; /* to ensure that Peano-Hilber order is done */
domain_Decomposition(); /* do initial domain decomposition (gives equal numbers of particles) */
ngb_treebuild(); /* will build tree */
setup_smoothinglengths();
#ifdef CHIMIE
#ifndef CHIMIE_INPUT_ALL
stars_setup_smoothinglengths();
#endif
#endif
#ifdef TESSEL
setup_searching_radius();
#endif
TreeReconstructFlag = 1;
#ifndef TESSEL /*do not convert if tessel is used. In tessel, the conversion is done with tessel_convert_energy_to_entropy() */
/* at this point, the entropy variable normally contains the
* internal energy, read in from the initial conditions file, unless the file
* explicitly signals that the initial conditions contain the entropy directly.
* Once the density has been computed, we can convert thermal energy to entropy.
*/
#ifndef DENSITY_INDEPENDENT_SPH /* in this case, entropy is correctely defined in setup_smoothinglengths */
#ifndef ISOTHERM_EQS
if(header.flag_entropy_instead_u == 0)
{
for(i = 0; i < N_gas; i++)
{
#ifdef MULTIPHASE
{
switch(SphP[i].Phase)
{
case GAS_SPH:
SphP[i].Entropy = GAMMA_MINUS1 * SphP[i].Entropy / pow(SphP[i].Density / a3, GAMMA_MINUS1);
break;
case GAS_STICKY:
break;
case GAS_DARK:
SphP[i].Entropy = -SphP[i].Entropy;
break;
}
}
#else
SphP[i].Entropy = GAMMA_MINUS1 * SphP[i].Entropy / pow(SphP[i].Density / a3, GAMMA_MINUS1);
#endif
}
}
#endif
#endif /* DENSITY_INDEPENDENT_SPH */
#ifdef ENTROPYPRED
for(i = 0; i < N_gas; i++)
SphP[i].EntropyPred = SphP[i].Entropy;
#endif
#endif /* TESSEL */
return 1;
}
static void Begrun1()
{
struct global_data_all_processes all;
if(ThisTask == 0)
{
printf("\nThis is pyGadget, version `%s'.\n", GADGETVERSION);
printf("\nRunning on %d processors.\n", NTask);
}
//read_parameter_file(ParameterFile); /* ... read in parameters for this run */
allocate_commbuffers(); /* ... allocate buffer-memory for particle
exchange during force computation */
set_units();
#if defined(PERIODIC) && (!defined(PMGRID) || defined(FORCETEST))
ewald_init();
#endif
//open_outputfiles();
random_generator = gsl_rng_alloc(gsl_rng_ranlxd1);
gsl_rng_set(random_generator, 42); /* start-up seed */
#ifdef PMGRID
long_range_init();
#endif
All.TimeLastRestartFile = CPUThisRun;
if(RestartFlag == 0 || RestartFlag == 2)
{
set_random_numbers();
}
else
{
all = All; /* save global variables. (will be read from restart file) */
restart(RestartFlag); /* ... read restart file. Note: This also resets
all variables in the struct `All'.
However, during the run, some variables in the parameter
file are allowed to be changed, if desired. These need to
copied in the way below.
Note: All.PartAllocFactor is treated in restart() separately.
*/
All.MinSizeTimestep = all.MinSizeTimestep;
All.MaxSizeTimestep = all.MaxSizeTimestep;
All.BufferSize = all.BufferSize;
All.BunchSizeForce = all.BunchSizeForce;
All.BunchSizeDensity = all.BunchSizeDensity;
All.BunchSizeHydro = all.BunchSizeHydro;
All.BunchSizeDomain = all.BunchSizeDomain;
All.TimeLimitCPU = all.TimeLimitCPU;
All.ResubmitOn = all.ResubmitOn;
All.TimeBetSnapshot = all.TimeBetSnapshot;
All.TimeBetStatistics = all.TimeBetStatistics;
All.CpuTimeBetRestartFile = all.CpuTimeBetRestartFile;
All.ErrTolIntAccuracy = all.ErrTolIntAccuracy;
All.MaxRMSDisplacementFac = all.MaxRMSDisplacementFac;
All.ErrTolForceAcc = all.ErrTolForceAcc;
All.TypeOfTimestepCriterion = all.TypeOfTimestepCriterion;
All.TypeOfOpeningCriterion = all.TypeOfOpeningCriterion;
All.NumFilesWrittenInParallel = all.NumFilesWrittenInParallel;
All.TreeDomainUpdateFrequency = all.TreeDomainUpdateFrequency;
All.SnapFormat = all.SnapFormat;
All.NumFilesPerSnapshot = all.NumFilesPerSnapshot;
All.MaxNumNgbDeviation = all.MaxNumNgbDeviation;
All.ArtBulkViscConst = all.ArtBulkViscConst;
All.OutputListOn = all.OutputListOn;
All.CourantFac = all.CourantFac;
All.OutputListLength = all.OutputListLength;
memcpy(All.OutputListTimes, all.OutputListTimes, sizeof(double) * All.OutputListLength);
strcpy(All.ResubmitCommand, all.ResubmitCommand);
strcpy(All.OutputListFilename, all.OutputListFilename);
strcpy(All.OutputDir, all.OutputDir);
strcpy(All.RestartFile, all.RestartFile);
strcpy(All.EnergyFile, all.EnergyFile);
strcpy(All.InfoFile, all.InfoFile);
strcpy(All.CpuFile, all.CpuFile);
strcpy(All.TimingsFile, all.TimingsFile);
strcpy(All.SnapshotFileBase, all.SnapshotFileBase);
if(All.TimeMax != all.TimeMax)
readjust_timebase(All.TimeMax, all.TimeMax);
}
}
static void Begrun2()
{
if(RestartFlag == 0 || RestartFlag == 2)
Init(); /* ... read in initial model */
#ifdef PMGRID
long_range_init_regionsize();
#endif
#ifndef PY_INTERFACE
if(All.ComovingIntegrationOn)
init_drift_table();
#endif
//if(RestartFlag == 2)
// All.Ti_nextoutput = find_next_outputtime(All.Ti_Current + 1);
//else
// All.Ti_nextoutput = find_next_outputtime(All.Ti_Current);
All.TimeLastRestartFile = CPUThisRun;
}
/************************************************************/
/* PYTHON INTERFACE */
/************************************************************/
static PyObject *gadget_Info(PyObject *self, PyObject *args, PyObject *kwds)
{
printf("I am proc %d among %d procs.\n",ThisTask,NTask);
return Py_BuildValue("i",1);
}
static PyObject *gadget_InitMPI(PyObject *self, PyObject *args, PyObject *kwds)
{
//MPI_Init(0, 0); /* this is done in mpi4py */
MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask);
MPI_Comm_size(MPI_COMM_WORLD, &NTask);
for(PTask = 0; NTask > (1 << PTask); PTask++);
return Py_BuildValue("i",1);
}
static PyObject * gadget_InitDefaultParameters(PyObject* self)
{
/* list of Gadget parameters */
/*
All.InitCondFile ="ICs/cluster_littleendian.dat";
All.OutputDir ="cluster/";
All.EnergyFile ="energy.txt";
All.InfoFile ="info.txt";
All.TimingsFile ="timings.txt";
All.CpuFile ="cpu.txt";
All.RestartFile ="restart";
All.SnapshotFileBase ="snapshot";
All.OutputListFilename ="parameterfiles/outputs_lcdm_gas.txt";
*/
/* CPU time -limit */
All.TimeLimitCPU = 36000; /* = 10 hours */
All.ResubmitOn = 0;
//All.ResubmitCommand = "my-scriptfile";
All.ICFormat = 1;
All.SnapFormat = 1;
All.ComovingIntegrationOn = 0;
All.TypeOfTimestepCriterion = 0;
All.OutputListOn = 0;
All.PeriodicBoundariesOn = 0;
/* Caracteristics of run */
All.TimeBegin = 0.0; /*% Begin of the simulation (z=23)*/
All.TimeMax = 1.0;
All.Omega0 = 0;
All.OmegaLambda = 0;
All.OmegaBaryon = 0;
All.HubbleParam = 0;
All.BoxSize = 0;
/* Output frequency */
All.TimeBetSnapshot = 0.1;
All.TimeOfFirstSnapshot = 0.0; /*% 5 constant steps in log(a) */
All.CpuTimeBetRestartFile = 36000.0; /* here in seconds */
All.TimeBetStatistics = 0.05;
All.NumFilesPerSnapshot = 1;
All.NumFilesWrittenInParallel = 1;
/* Accuracy of time integration */
All.ErrTolIntAccuracy = 0.025;
All.MaxRMSDisplacementFac = 0.2;
All.CourantFac = 0.15;
All.MaxSizeTimestep = 0.03;
All.MinSizeTimestep = 0.0;
/* Tree algorithm, force accuracy, domain update frequency */
All.ErrTolTheta = 0.7;
All.TypeOfOpeningCriterion = 0;
All.ErrTolForceAcc = 0.005;
All.TreeDomainUpdateFrequency = 0.1;
/* Further parameters of SPH */
All.DesNumNgb = 50;
All.MaxNumNgbDeviation = 2;
All.ArtBulkViscConst = 0.8;
All.InitGasTemp = 0;
All.MinGasTemp = 0;
/* Memory allocation */
All.PartAllocFactor = 2.0;
All.TreeAllocFactor = 2.0;
All.BufferSize = 30;
/* System of units */
All.UnitLength_in_cm = 3.085678e21; /* 1.0 kpc */
All.UnitMass_in_g = 1.989e43; /* 1.0e10 solar masses */
All.UnitVelocity_in_cm_per_s = 1e5; /* 1 km/sec */
All.GravityConstantInternal = 0;
/* Softening lengths */
All.MinGasHsmlFractional = 0.25;
All.SofteningGas = 0.5;
All.SofteningHalo = 0.5;
All.SofteningDisk = 0.5;
All.SofteningBulge = 0.5;
All.SofteningStars = 0.5;
All.SofteningBndry = 0.5;
All.SofteningGasMaxPhys = 0.5;
All.SofteningHaloMaxPhys = 0.5;
All.SofteningDiskMaxPhys = 0.5;
All.SofteningBulgeMaxPhys = 0.5;
All.SofteningStarsMaxPhys = 0.5;
All.SofteningBndryMaxPhys = 0.5;
return Py_BuildValue("i",1);
}
static PyObject * gadget_GetParameters()
{
PyObject *dict;
PyObject *key;
PyObject *value;
dict = PyDict_New();
/* CPU time -limit */
key = PyString_FromString("TimeLimitCPU");
value = PyFloat_FromDouble(All.TimeLimitCPU);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("ResubmitOn");
value = PyFloat_FromDouble(All.ResubmitOn);
PyDict_SetItem(dict,key,value);
//All.ResubmitCommand
key = PyString_FromString("ICFormat");
value = PyInt_FromLong(All.ICFormat);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SnapFormat");
value = PyInt_FromLong(All.SnapFormat);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("ComovingIntegrationOn");
value = PyInt_FromLong(All.ComovingIntegrationOn);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TypeOfTimestepCriterion");
value = PyInt_FromLong(All.TypeOfTimestepCriterion);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("OutputListOn");
value = PyInt_FromLong(All.OutputListOn);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("PeriodicBoundariesOn");
value = PyInt_FromLong(All.PeriodicBoundariesOn);
PyDict_SetItem(dict,key,value);
/* Caracteristics of run */
key = PyString_FromString("TimeBegin");
value = PyFloat_FromDouble(All.TimeBegin);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TimeMax");
value = PyFloat_FromDouble(All.TimeMax);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("Omega0");
value = PyFloat_FromDouble(All.Omega0);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("OmegaLambda");
value = PyFloat_FromDouble(All.OmegaLambda);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("OmegaBaryon");
value = PyFloat_FromDouble(All.OmegaBaryon);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("HubbleParam");
value = PyFloat_FromDouble(All.HubbleParam);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("BoxSize");
value = PyFloat_FromDouble(All.BoxSize);
PyDict_SetItem(dict,key,value);
/* Output frequency */
key = PyString_FromString("TimeBetSnapshot");
value = PyFloat_FromDouble(All.TimeBetSnapshot);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TimeOfFirstSnapshot");
value = PyFloat_FromDouble(All.TimeOfFirstSnapshot);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("CpuTimeBetRestartFile");
value = PyFloat_FromDouble(All.CpuTimeBetRestartFile);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TimeBetStatistics");
value = PyFloat_FromDouble(All.TimeBetStatistics);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("NumFilesPerSnapshot");
value = PyInt_FromLong(All.NumFilesPerSnapshot);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("NumFilesWrittenInParallel");
value = PyInt_FromLong(All.NumFilesWrittenInParallel);
PyDict_SetItem(dict,key,value);
/* Accuracy of time integration */
key = PyString_FromString("ErrTolIntAccuracy");
value = PyFloat_FromDouble(All.ErrTolIntAccuracy);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("MaxRMSDisplacementFac");
value = PyFloat_FromDouble(All.MaxRMSDisplacementFac);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("CourantFac");
value = PyFloat_FromDouble(All.CourantFac);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("MaxSizeTimestep");
value = PyFloat_FromDouble(All.MaxSizeTimestep);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("MinSizeTimestep");
value = PyFloat_FromDouble(All.MinSizeTimestep);
PyDict_SetItem(dict,key,value);
/* Tree algorithm, force accuracy, domain update frequency */
key = PyString_FromString("ErrTolTheta");
value = PyFloat_FromDouble(All.ErrTolTheta);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TypeOfOpeningCriterion");
value = PyInt_FromLong(All.TypeOfOpeningCriterion);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("ErrTolForceAcc");
value = PyFloat_FromDouble(All.ErrTolForceAcc);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TreeDomainUpdateFrequency");
value = PyFloat_FromDouble(All.TreeDomainUpdateFrequency);
PyDict_SetItem(dict,key,value);
/* Further parameters of SPH */
key = PyString_FromString("DesNumNgb");
value = PyInt_FromLong(All.DesNumNgb);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("MaxNumNgbDeviation");
value = PyInt_FromLong(All.MaxNumNgbDeviation);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("ArtBulkViscConst");
value = PyInt_FromLong(All.ArtBulkViscConst);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("InitGasTemp");
value = PyInt_FromLong(All.InitGasTemp);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("MinGasTemp");
value = PyInt_FromLong(All.MinGasTemp);
PyDict_SetItem(dict,key,value);
/* Memory allocation */
key = PyString_FromString("PartAllocFactor");
value = PyFloat_FromDouble(All.PartAllocFactor);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("TreeAllocFactor");
value = PyFloat_FromDouble(All.TreeAllocFactor);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("BufferSize");
value = PyInt_FromLong(All.BufferSize);
PyDict_SetItem(dict,key,value);
/* System of units */
key = PyString_FromString("UnitLength_in_cm");
value = PyFloat_FromDouble(All.UnitLength_in_cm);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("UnitMass_in_g");
value = PyFloat_FromDouble(All.UnitMass_in_g);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("UnitVelocity_in_cm_per_s");
value = PyFloat_FromDouble(All.UnitVelocity_in_cm_per_s);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("GravityConstantInternal");
value = PyFloat_FromDouble(All.GravityConstantInternal);
PyDict_SetItem(dict,key,value);
/* Softening lengths */
key = PyString_FromString("MinGasHsmlFractional");
value = PyFloat_FromDouble(All.MinGasHsmlFractional);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningGas");
value = PyFloat_FromDouble(All.SofteningGas);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningHalo");
value = PyFloat_FromDouble(All.SofteningHalo);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningDisk");
value = PyFloat_FromDouble(All.SofteningDisk);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningBulge");
value = PyFloat_FromDouble(All.SofteningBulge);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningStars");
value = PyFloat_FromDouble(All.SofteningStars);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningBndry");
value = PyFloat_FromDouble(All.SofteningBndry);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningGasMaxPhys");
value = PyFloat_FromDouble(All.SofteningGasMaxPhys);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningHaloMaxPhys");
value = PyFloat_FromDouble(All.SofteningHaloMaxPhys);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningDiskMaxPhys");
value = PyFloat_FromDouble(All.SofteningDiskMaxPhys);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningBulgeMaxPhys");
value = PyFloat_FromDouble(All.SofteningBulgeMaxPhys);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningStarsMaxPhys");
value = PyFloat_FromDouble(All.SofteningStarsMaxPhys);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("SofteningBndryMaxPhys");
value = PyFloat_FromDouble(All.SofteningBndryMaxPhys);
PyDict_SetItem(dict,key,value);
/*
key = PyString_FromString("OutputInfo");
value = PyFloat_FromDouble(All.OutputInfo);
PyDict_SetItem(dict,key,value);
key = PyString_FromString("PeanoHilbertOrder");
value = PyFloat_FromDouble(All.PeanoHilbertOrder);
PyDict_SetItem(dict,key,value);
*/
#ifdef SFR
PyDict_Merge(dict,sfr_GetParameters(),1);
#endif
return Py_BuildValue("O",dict);
}
static PyObject * gadget_SetParameters(PyObject *self, PyObject *args)
{
PyObject *dict;
PyObject *key;
PyObject *value;
/* here, we can have either arguments or dict directly */
if(PyDict_Check(args))
{
dict = args;
}
else
{
if (! PyArg_ParseTuple(args, "O",&dict))
return NULL;
}
/* check that it is a PyDictObject */
if(!PyDict_Check(dict))
{
PyErr_SetString(PyExc_AttributeError, "argument is not a dictionary.");
return NULL;
}
Py_ssize_t pos=0;
while(PyDict_Next(dict,&pos,&key,&value))
{
if(PyString_Check(key))
{
/* CPU time -limit */
if(strcmp(PyString_AsString(key), "TimeLimitCPU")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeLimitCPU = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "ResubmitOn")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ResubmitOn = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "ICFormat")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ICFormat = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "SnapFormat")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SnapFormat = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "ComovingIntegrationOn")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ComovingIntegrationOn = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "TypeOfTimestepCriterion")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TypeOfTimestepCriterion = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "OutputListOn")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.OutputListOn = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "PeriodicBoundariesOn")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.PeriodicBoundariesOn = PyInt_AsLong(value);
}
/* Caracteristics of run */
if(strcmp(PyString_AsString(key), "TimeBegin")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeBegin = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TimeMax")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeMax = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "Omega0")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.Omega0 = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "OmegaLambda")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.OmegaLambda = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "OmegaBaryon")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.OmegaBaryon = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "HubbleParam")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.HubbleParam = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "BoxSize")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.BoxSize = PyFloat_AsDouble(value);
}
/* Output frequency */
if(strcmp(PyString_AsString(key), "TimeBetSnapshot")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeBetSnapshot = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TimeOfFirstSnapshot")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeOfFirstSnapshot = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "CpuTimeBetRestartFile")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.CpuTimeBetRestartFile = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TimeBetStatistics")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TimeBetStatistics = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "NumFilesPerSnapshot")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.NumFilesPerSnapshot = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "NumFilesWrittenInParallel")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.NumFilesWrittenInParallel = PyInt_AsLong(value);
}
/* Accuracy of time integration */
if(strcmp(PyString_AsString(key), "ErrTolIntAccuracy")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ErrTolIntAccuracy = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "MaxRMSDisplacementFac")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MaxRMSDisplacementFac = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "CourantFac")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.CourantFac = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "MaxSizeTimestep")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MaxSizeTimestep = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "MinSizeTimestep")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MinSizeTimestep = PyFloat_AsDouble(value);
}
/* Tree algorithm, force accuracy, domain update frequency */
if(strcmp(PyString_AsString(key), "ErrTolTheta")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ErrTolTheta = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TypeOfOpeningCriterion")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TypeOfOpeningCriterion = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "ErrTolForceAcc")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ErrTolForceAcc = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TreeDomainUpdateFrequency")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TreeDomainUpdateFrequency = PyFloat_AsDouble(value);
}
/* Further parameters of SPH */
if(strcmp(PyString_AsString(key), "DesNumNgb")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.DesNumNgb = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "MaxNumNgbDeviation")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MaxNumNgbDeviation = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "ArtBulkViscConst")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.ArtBulkViscConst = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "InitGasTemp")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.InitGasTemp = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "MinGasTemp")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MinGasTemp = PyInt_AsLong(value);
}
/* Memory allocation */
if(strcmp(PyString_AsString(key), "PartAllocFactor")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.PartAllocFactor = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "TreeAllocFactor")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.TreeAllocFactor = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "BufferSize")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.BufferSize = PyInt_AsLong(value);
}
/* System of units */
if(strcmp(PyString_AsString(key), "UnitLength_in_cm")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitLength_in_cm = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "UnitMass_in_g")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitMass_in_g = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "UnitVelocity_in_cm_per_s")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitVelocity_in_cm_per_s = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "GravityConstantInternal")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.GravityConstantInternal = PyFloat_AsDouble(value);
}
/* Softening lengths */
if(strcmp(PyString_AsString(key), "MinGasHsmlFractional")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.MinGasHsmlFractional = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningGas")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningGas = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningHalo")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningHalo = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningDisk")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningDisk = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningBulge")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningBulge = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningStars")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningStars = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningBndry")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningBndry = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningGasMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningGasMaxPhys = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningHaloMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningHaloMaxPhys = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningDiskMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningDiskMaxPhys = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningBulgeMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningBulgeMaxPhys = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningStarsMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningStarsMaxPhys = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "SofteningBndryMaxPhys")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.SofteningBndryMaxPhys = PyFloat_AsDouble(value);
}
/* FoF */
#ifdef FOF
if(strcmp(PyString_AsString(key), "FoF_Density")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_Density = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_ThresholdDensityFactor")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_ThresholdDensityFactor = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_MinHeadDensityFactor")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_MinHeadDensityFactor = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_MinGroupMembers")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_MinGroupMembers = PyInt_AsLong(value);
}
if(strcmp(PyString_AsString(key), "FoF_MinGroupMass")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_MinGroupMass = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_VirialFractionThreshold")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_VirialFractionThreshold = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_HsmlSearchRadiusFactor")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_HsmlSearchRadiusFactor = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "FoF_StarFormationType")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.FoF_StarFormationType = PyInt_AsLong(value);
}
#endif
}
}
#ifdef SFR
sfr_SetParameters(self,args);
#endif
return Py_BuildValue("i",1);
}
static PyObject *
gadget_check_parser(PyObject *self, PyObject *args, PyObject *keywds)
{
int voltage;
char *state = "a stiff";
char *action = "voom";
char *type = "Norwegian Blue";
static char *kwlist[] = {"voltage", "state", "action", "type", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
&voltage, &state, &action, &type))
return NULL;
printf("-- This parrot wouldn't %s if you put %i Volts through it.\n",
action, voltage);
printf("-- Lovely plumage, the %s -- It's %s!\n", type, state);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *gadget_Free(PyObject *self, PyObject *args, PyObject *kwds)
{
free_memory();
ngb_treefree();
force_treefree();
free(Exportflag );
free(DomainStartList);
free(DomainEndList);
free(TopNodes);
free(DomainWork);
free(DomainCount);
free(DomainCountSph);
free(DomainTask);
free(DomainNodeIndex);
free(DomainTreeNodeLen);
free(DomainHmax);
free(DomainMoment);
free(CommBuffer);
gsl_rng_free(random_generator);
return Py_BuildValue("i",1);
}
static PyObject *gadget_Start(PyObject *self, PyObject *args, PyObject *kwds)
{
/* define argc, argv */
/*
if(argc < 2)
{
if(ThisTask == 0)
{
printf("Parameters are missing.\n");
printf("Call with <ParameterFile> [<RestartFlag>]\n");
}
endrun(0);
}
strcpy(ParameterFile, argv[1]);
if(argc >= 3)
RestartFlag = atoi(argv[2]);
else
RestartFlag = 0;
*/
strcpy(ParameterFile,"params");
RestartFlag=0;
begrun(); /* set-up run */
return Py_BuildValue("i",1);
}
static PyObject *gadget_LoadParticles(PyObject *self, PyObject *args, PyObject *kwds)
{
int i,j;
size_t bytes;
PyArrayObject *ntype=Py_None;
PyArrayObject *pos=Py_None;
PyArrayObject *vel=Py_None;
PyArrayObject *mass=Py_None;
PyArrayObject *num=Py_None;
PyArrayObject *tpe=Py_None;
PyArrayObject *u=Py_None;
PyArrayObject *rho=Py_None;
static char *kwlist[] = {"npart", "pos","vel","mass","num","tpe","u","rho", NULL};
if (! PyArg_ParseTupleAndKeywords(args,kwds, "OOOOOO|OO",kwlist,&ntype,&pos,&vel,&mass,&num,&tpe,&u,&rho ))
return NULL;
/* check type */
if (!(PyArray_Check(pos)))
{
PyErr_SetString(PyExc_ValueError,"aruments 2 must be array.");
return NULL;
}
/* check type */
if (!(PyArray_Check(mass)))
{
PyErr_SetString(PyExc_ValueError,"aruments 3 must be array.");
return NULL;
}
/* check dimension */
if ( (pos->nd!=2))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 2 must be 2.");
return NULL;
}
/* check dimension */
if ( (mass->nd!=1))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 3 must be 1.");
return NULL;
}
/* check size */
if ( (pos->dimensions[1]!=3))
{
PyErr_SetString(PyExc_ValueError,"First size of argument must be 3.");
return NULL;
}
/* check size */
if ( (pos->dimensions[0]!=mass->dimensions[0]))
{
PyErr_SetString(PyExc_ValueError,"Size of argument 2 must be similar to argument 3.");
return NULL;
}
/* ensure double */
ntype = TO_INT(ntype);
pos = TO_FLOAT(pos);
vel = TO_FLOAT(vel);
mass = TO_FLOAT(mass);
num = TO_INT(num);
tpe = TO_INT(tpe);
/* optional variables */
if (u!=Py_None)
u = TO_FLOAT(u);
if (rho!=Py_None)
rho = TO_FLOAT(rho);
/***************************************
* some inits *
/***************************************/
RestartFlag = 0;
Begrun1();
/***************************************
* LOAD PARTICLES *
/***************************************/
NumPart = 0;
N_gas = *(int*) (ntype->data + 0*(ntype->strides[0]));
for (i = 0; i < 6; i++)
NumPart += *(int*) (ntype->data + i*(ntype->strides[0]));
if (NumPart!=pos->dimensions[0])
{
PyErr_SetString(PyExc_ValueError,"Numpart != pos->dimensions[0].");
return NULL;
}
MPI_Allreduce(&NumPart, &All.TotNumPart, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce(&N_gas, &All.TotN_gas, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
All.MaxPart = All.PartAllocFactor * (All.TotNumPart / NTask);
All.MaxPartSph = All.PartAllocFactor * (All.TotN_gas / NTask);
#ifdef STELLAR_PROP
All.MaxPartStars = All.PartAllocFactor * (All.TotN_stars / NTask); /* existing star particles */
#ifdef SFR
All.MaxPartStars = All.MaxPartStars + All.StarFormationNStarsFromGas*All.MaxPartSph*All.StarsAllocFactor; /* potental star particles */
#endif
#endif
/*********************/
/* allocate memory */
/*********************/
allocate_memory();
/*********************/
/* init P */
/*********************/
for (i = 0; i < NumPart; i++)
{
P[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
P[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
P[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
P[i].Vel[0] = *(float *) (vel->data + i*(vel->strides[0]) + 0*vel->strides[1]);
P[i].Vel[1] = *(float *) (vel->data + i*(vel->strides[0]) + 1*vel->strides[1]);
P[i].Vel[2] = *(float *) (vel->data + i*(vel->strides[0]) + 2*vel->strides[1]);
P[i].Mass = *(float *) (mass->data + i*(mass->strides[0]));
P[i].ID = *(unsigned int *) (num->data + i*(num->strides[0]));
P[i].Type = *(int *) (tpe->data + i*(tpe->strides[0]));
//P[i].Active = 1;
//printf(" P.ID=%d%09d\n", (int) (P[i].ID / 1000000000), (int) (P[i].ID % 1000000000));
#ifdef TESSEL
P[i].iPref = -1;
#endif
}
/*********************/
/* init SphP */
/*********************/
if (u!=Py_None)
for (i = 0; i < NumPart; i++)
{
SphP[i].Entropy = *(float *) (u->data + i*(u->strides[0]));
//#ifndef ISOTHERM_EQS
// SphP[i].Entropy = GAMMA_MINUS1 * SphP[i].Entropy / pow(SphP[i].Density / a3, GAMMA_MINUS1);
//#endif
}
if (rho!=Py_None)
for (i = 0; i < NumPart; i++)
{
SphP[i].Density = *(float *) (rho->data + i*(rho->strides[0]));
}
/***************************************
* END LOAD PARTICLES *
/***************************************/
/***************************************
* finish inits *
/***************************************/
Begrun2();
/***************************************
* free memory *
/***************************************/
/* free the memory allocated,
because these vectors where casted
and their memory is now handeled by the C part */
Py_DECREF(ntype);
Py_DECREF(pos);
Py_DECREF(vel);
Py_DECREF(mass);
Py_DECREF(num);
Py_DECREF(tpe);
/* optional variables */
if (u!=Py_None)
Py_DECREF(u);
if (rho!=Py_None)
Py_DECREF(rho);
return Py_BuildValue("i",1);
}
static PyObject *gadget_LoadParticlesQ(PyObject *self, PyObject *args, PyObject *kwds)
{
int i,j;
size_t bytes;
PyArrayObject *ntype,*pos,*vel,*mass,*num,*tpe;
static char *kwlist[] = {"npart", "pos","vel","mass","num","tpe", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO",kwlist,&ntype,&pos,&vel,&mass,&num,&tpe))
return Py_BuildValue("i",1);
/* check type */
if (!(PyArray_Check(pos)))
{
PyErr_SetString(PyExc_ValueError,"aruments 1 must be array.");
return NULL;
}
/* check type */
if (!(PyArray_Check(mass)))
{
PyErr_SetString(PyExc_ValueError,"aruments 2 must be array.");
return NULL;
}
/* check dimension */
if ( (pos->nd!=2))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 1 must be 2.");
return NULL;
}
/* check dimension */
if ( (mass->nd!=1))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 2 must be 1.");
return NULL;
}
/* check size */
if ( (pos->dimensions[1]!=3))
{
PyErr_SetString(PyExc_ValueError,"First size of argument must be 3.");
return NULL;
}
/* check size */
if ( (pos->dimensions[0]!=mass->dimensions[0]))
{
PyErr_SetString(PyExc_ValueError,"Size of argument 1 must be similar to argument 2.");
return NULL;
}
/* ensure double */
ntype = TO_INT(ntype);
pos = TO_FLOAT(pos);
vel = TO_FLOAT(vel);
mass = TO_FLOAT(mass);
num = TO_FLOAT(num);
tpe = TO_FLOAT(tpe);
/***************************************
* some inits *
/***************************************/
allocate_commbuffersQ();
/***************************************
* LOAD PARTILES *
/***************************************/
NumPartQ = 0;
N_gasQ = *(int*) (ntype->data + 0*(ntype->strides[0]));
for (i = 0; i < 6; i++)
NumPartQ += *(int*) (ntype->data + i*(ntype->strides[0]));
if (NumPartQ!=pos->dimensions[0])
{
PyErr_SetString(PyExc_ValueError,"NumpartQ != pos->dimensions[0].");
return NULL;
}
MPI_Allreduce(&NumPartQ, &All.TotNumPartQ, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce(&N_gasQ, &All.TotN_gasQ, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
All.MaxPartQ = All.PartAllocFactor * (All.TotNumPartQ / NTask);
All.MaxPartSphQ = All.PartAllocFactor * (All.TotN_gasQ / NTask);
/*********************/
/* allocate Q */
/*********************/
if(!(Q = malloc(bytes = All.MaxPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = All.MaxPartSphQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB) %d.\n", bytes / (1024.0 * 1024.0), sizeof(struct sph_particle_data));
endrun(1);
}
/*********************/
/* init P */
/*********************/
for (i = 0; i < NumPartQ; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
Q[i].Vel[0] = *(float *) (vel->data + i*(vel->strides[0]) + 0*vel->strides[1]);
Q[i].Vel[1] = *(float *) (vel->data + i*(vel->strides[0]) + 1*vel->strides[1]);
Q[i].Vel[2] = *(float *) (vel->data + i*(vel->strides[0]) + 2*vel->strides[1]);
Q[i].Mass = *(float *) (mass->data + i*(mass->strides[0]));
Q[i].ID = *(unsigned int *) (num->data + i*(num->strides[0]));
Q[i].Type = *(int *) (tpe->data + i*(tpe->strides[0]));
//Q[i].Active = 1;
}
/***************************************
* END LOAD PARTILES *
/***************************************/
domain_DecompositionQ();
/***************************************
* finish inits *
/***************************************/
return Py_BuildValue("i",1);
}
static PyObject *gadget_AllPotential(PyObject *self)
{
compute_potential();
return Py_BuildValue("i",1);
}
static PyObject * gadget_GetAllPotential(PyObject* self)
{
PyArrayObject *pot;
npy_intp ld[1];
int i;
ld[0] = NumPart;
pot = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < pot->dimensions[0]; i++)
{
*(float *) (pot->data + i*(pot->strides[0])) = P[i].Potential;
}
return PyArray_Return(pot);
}
static PyObject *gadget_AllAcceleration(PyObject *self)
{
NumForceUpdate = NumPart;
gravity_tree();
return Py_BuildValue("i",1);
}
static PyObject * gadget_GetAllAcceleration(PyObject* self)
{
PyArrayObject *acc;
npy_intp ld[2];
int i;
ld[0] = NumPart;
ld[1] = 3;
acc = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < acc->dimensions[0]; i++)
{
*(float *) (acc->data + i*(acc->strides[0]) + 0*acc->strides[1]) = P[i].GravAccel[0];
*(float *) (acc->data + i*(acc->strides[0]) + 1*acc->strides[1]) = P[i].GravAccel[1];
*(float *) (acc->data + i*(acc->strides[0]) + 2*acc->strides[1]) = P[i].GravAccel[2];
}
return PyArray_Return(acc);
}
static PyObject *gadget_GetAllDensities(PyObject* self)
{
PyArrayObject *rho;
npy_intp ld[1];
int i;
ld[0] = N_gas;
rho = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < rho->dimensions[0]; i++)
{
*(float *) (rho->data + i*(rho->strides[0])) = SphP[i].Density;
}
return PyArray_Return(rho);
}
#ifdef DENSITY_INDEPENDENT_SPH
static PyObject *gadget_GetAllEgyWtDensities(PyObject* self)
{
PyArrayObject *rho;
npy_intp ld[1];
int i;
ld[0] = N_gas;
rho = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < rho->dimensions[0]; i++)
{
*(float *) (rho->data + i*(rho->strides[0])) = SphP[i].EgyWtDensity;
}
return PyArray_Return(rho);
}
#endif
static PyObject *gadget_GetAllHsml(PyObject* self)
{
PyArrayObject *hsml;
npy_intp ld[1];
int i;
ld[0] = N_gas;
hsml = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < hsml->dimensions[0]; i++)
{
*(float *) (hsml->data + i*(hsml->strides[0])) = SphP[i].Hsml;
}
return PyArray_Return(hsml);
}
static PyObject *gadget_GetAllPositions(PyObject* self)
{
PyArrayObject *pos;
npy_intp ld[2];
int i;
ld[0] = NumPart;
ld[1] = 3;
pos = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]) = P[i].Pos[0];
*(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]) = P[i].Pos[1];
*(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]) = P[i].Pos[2];
}
return PyArray_Return(pos);
}
static PyObject *gadget_GetAllVelocities(PyObject* self)
{
PyArrayObject *vel;
npy_intp ld[2];
int i;
ld[0] = NumPart;
ld[1] = 3;
vel = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < vel->dimensions[0]; i++)
{
*(float *) (vel->data + i*(vel->strides[0]) + 0*vel->strides[1]) = P[i].Vel[0];
*(float *) (vel->data + i*(vel->strides[0]) + 1*vel->strides[1]) = P[i].Vel[1];
*(float *) (vel->data + i*(vel->strides[0]) + 2*vel->strides[1]) = P[i].Vel[2];
}
return PyArray_Return(vel);
}
static PyObject *gadget_GetAllCurlVel(PyObject* self)
{
PyArrayObject *curlvel;
npy_intp ld[1];
int i;
ld[0] = NumPart;
curlvel = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < curlvel->dimensions[0]; i++)
{
*(float *) (curlvel->data + i*(curlvel->strides[0])) = SphP[i].CurlVel;
}
return PyArray_Return(curlvel);
}
static PyObject *gadget_GetAllDivVel(PyObject* self)
{
PyArrayObject *divvel;
npy_intp ld[1];
int i;
ld[0] = NumPart;
divvel = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < divvel->dimensions[0]; i++)
{
*(float *) (divvel->data + i*(divvel->strides[0])) = SphP[i].DivVel;
}
return PyArray_Return(divvel);
}
static PyObject *gadget_GetAllMasses(PyObject* self)
{
PyArrayObject *mass;
npy_intp ld[1];
int i;
ld[0] = NumPart;
mass = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < mass->dimensions[0]; i++)
{
*(float *) (mass->data + i*(mass->strides[0])) = P[i].Mass;
}
return PyArray_Return(mass);
}
static PyObject *gadget_GetAllEntropy(PyObject* self)
{
PyArrayObject *entropy;
npy_intp ld[1];
int i;
ld[0] = NumPart;
entropy = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < entropy->dimensions[0]; i++)
{
*(float *) (entropy->data + i*(entropy->strides[0])) = SphP[i].Entropy;
}
return PyArray_Return(entropy);
}
static PyObject *gadget_GetAllEnergySpec(PyObject* self)
{
PyArrayObject *energy;
npy_intp ld[1];
int i;
double a3inv;
ld[0] = NumPart;
energy = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
if(All.ComovingIntegrationOn)
{
a3inv = 1 / (All.Time * All.Time * All.Time);
}
else
a3inv = 1;
for (i = 0; i < energy->dimensions[0]; i++)
{
#ifdef ISOTHERM_EQS
*(float *) (energy->data + i*(energy->strides[0])) = SphP[i].Entropy;
#else
a3inv = 1.;
#ifdef DENSITY_INDEPENDENT_SPH
*(float *) (energy->data + i*(energy->strides[0])) = dmax(All.MinEgySpec,SphP[i].Entropy / GAMMA_MINUS1 * pow(SphP[i].EgyWtDensity * a3inv, GAMMA_MINUS1));
#else
*(float *) (energy->data + i*(energy->strides[0])) = dmax(All.MinEgySpec,SphP[i].Entropy / GAMMA_MINUS1 * pow(SphP[i].Density * a3inv, GAMMA_MINUS1));
#endif
#endif
}
return PyArray_Return(energy);
}
static PyObject *gadget_GetAllID(PyObject* self)
{
PyArrayObject *id;
npy_intp ld[1];
int i;
ld[0] = NumPart;
id = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0; i < id->dimensions[0]; i++)
{
*(int *) (id->data + i*(id->strides[0])) = P[i].ID;
}
return PyArray_Return(id);
}
static PyObject *gadget_GetAllTypes(PyObject* self)
{
PyArrayObject *type;
npy_intp ld[1];
int i;
ld[0] = NumPart;
type = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0; i < type->dimensions[0]; i++)
{
*(int *) (type->data + i*(type->strides[0])) = P[i].Type;
}
return PyArray_Return(type);
}
#ifdef CHIMIE
static PyObject *gadget_GetAllMetal(PyObject* self)
{
PyArrayObject *metal;
npy_intp ld[2];
int i,j;
ld[0] = NumPart;
ld[1] = NELEMENTS;
metal = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < metal->dimensions[0]; i++)
{
for (j=0;j<NELEMENTS;j++)
*(float *) (metal->data + i*(metal->strides[0]) + j*metal->strides[1]) = SphP[i].Metal[0];
}
return PyArray_Return(metal);
}
#endif
-#ifdef METAL_DIFFUSION
+#if defined(COMPUTE_VELOCITY_DISP) || defined(METAL_DIFFUSION)
static PyObject *gadget_GetAllRmsSpeed(PyObject* self)
{
PyArrayObject *rmsspeed;
npy_intp ld[1];
int i;
ld[0] = NumPart;
rmsspeed = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < rmsspeed->dimensions[0]; i++)
{
*(float *) (rmsspeed->data + i*(rmsspeed->strides[0])) = SphP[i].RmsSpeed;
}
return PyArray_Return(rmsspeed);
}
#endif
static PyObject *gadget_GetAllPositionsQ(PyObject* self)
{
PyArrayObject *pos;
npy_intp ld[2];
int i;
ld[0] = NumPartQ;
ld[1] = 3;
pos = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]) = Q[i].Pos[0];
*(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]) = Q[i].Pos[1];
*(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]) = Q[i].Pos[2];
}
return PyArray_Return(pos);
}
static PyObject *gadget_GetAllVelocitiesQ(PyObject* self)
{
PyArrayObject *vel;
npy_intp ld[2];
int i;
ld[0] = NumPartQ;
ld[1] = 3;
vel = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < vel->dimensions[0]; i++)
{
*(float *) (vel->data + i*(vel->strides[0]) + 0*vel->strides[1]) = Q[i].Vel[0];
*(float *) (vel->data + i*(vel->strides[0]) + 1*vel->strides[1]) = Q[i].Vel[1];
*(float *) (vel->data + i*(vel->strides[0]) + 2*vel->strides[1]) = Q[i].Vel[2];
}
return PyArray_Return(vel);
}
static PyObject *gadget_GetAllMassesQ(PyObject* self)
{
PyArrayObject *mass;
npy_intp ld[1];
int i;
ld[0] = NumPartQ;
mass = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
for (i = 0; i < mass->dimensions[0]; i++)
{
*(float *) (mass->data + i*(mass->strides[0])) = Q[i].Mass;
}
return PyArray_Return(mass);
}
static PyObject *gadget_GetAllIDQ(PyObject* self)
{
PyArrayObject *id;
npy_intp ld[1];
int i;
ld[0] = NumPartQ;
id = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0; i < id->dimensions[0]; i++)
{
*(float *) (id->data + i*(id->strides[0])) = Q[i].ID;
}
return PyArray_Return(id);
}
static PyObject *gadget_GetAllTypesQ(PyObject* self)
{
PyArrayObject *type;
npy_intp ld[1];
int i;
ld[0] = NumPartQ;
type = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0; i < type->dimensions[0]; i++)
{
*(int *) (type->data + i*(type->strides[0])) = Q[i].Type;
}
return PyArray_Return(type);
}
static PyObject *gadget_GetPos(PyObject *self, PyObject *args, PyObject *kwds)
{
int i,j;
size_t bytes;
PyArrayObject *pos;
if (! PyArg_ParseTuple(args, "O",&pos))
return PyString_FromString("error : GetPos");
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]) = P[i].Pos[0];
*(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]) = P[i].Pos[1];
*(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]) = P[i].Pos[2];
}
//return PyArray_Return(Py_None);
return Py_BuildValue("i",1);
}
static PyObject * gadget_Potential(PyObject* self, PyObject *args)
{
PyArrayObject *pos;
float eps;
if (! PyArg_ParseTuple(args, "Of",&pos,&eps))
return PyString_FromString("error");
PyArrayObject *pot;
int i;
npy_intp ld[1];
int input_dimension;
size_t bytes;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
pos = TO_FLOAT(pos);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
pot = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
NumPartQ = pos->dimensions[0];
All.ForceSofteningQ = eps;
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
Q[i].Type = 0;
Q[i].Mass = 0;
Q[i].Potential = 0;
}
compute_potential_sub();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(pot->data + i*(pot->strides[0])) = Q[i].Potential;
}
free(Q);
free(SphQ);
return PyArray_Return(pot);
}
static PyObject * gadget_Acceleration(PyObject* self, PyObject *args)
{
PyArrayObject *pos;
float eps;
if (! PyArg_ParseTuple(args, "Of",&pos,&eps))
return PyString_FromString("error");
PyArrayObject *acc;
int i;
int input_dimension;
size_t bytes;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
pos = TO_FLOAT(pos);
/* create a NumPy object */
acc = (PyArrayObject *) PyArray_SimpleNew(pos->nd,pos->dimensions,PyArray_FLOAT);
NumPartQ = pos->dimensions[0];
All.ForceSofteningQ = eps;
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
Q[i].Type = 0;
Q[i].Mass = 0;
Q[i].GravAccel[0] = 0;
Q[i].GravAccel[1] = 0;
Q[i].GravAccel[2] = 0;
}
gravity_tree_sub();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(acc->data + i*(acc->strides[0]) + 0*acc->strides[1]) = Q[i].GravAccel[0];
*(float *)(acc->data + i*(acc->strides[0]) + 1*acc->strides[1]) = Q[i].GravAccel[1];
*(float *)(acc->data + i*(acc->strides[0]) + 2*acc->strides[1]) = Q[i].GravAccel[2];
}
free(Q);
free(SphQ);
return PyArray_Return(acc);
}
static PyObject * gadget_InitHsml(PyObject* self, PyObject *args)
{
PyArrayObject *pos;
if (! PyArg_ParseTuple(args, "O",&pos))
return PyString_FromString("error");
int i;
int input_dimension;
size_t bytes;
int ld[1];
PyArrayObject *vden,*vhsml;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
pos = TO_FLOAT(pos);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
vden = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
vhsml = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
NumPartQ = pos->dimensions[0];
N_gasQ = NumPartQ;
All.Ti_Current=1; /* need to flag active particles */
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
}
setup_smoothinglengths_sub();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(vhsml->data + i*(vhsml->strides[0])) = SphQ[i].Hsml;
*(float *)(vden->data + i*(vden->strides[0])) = SphQ[i].Density;
}
free(Q);
free(SphQ);
return Py_BuildValue("OO",vden,vhsml);
}
static PyObject * gadget_Density(PyObject* self, PyObject *args)
{
PyArrayObject *pos,*hsml;
if (! PyArg_ParseTuple(args, "OO",&pos,&hsml))
return PyString_FromString("error");
int i;
int input_dimension;
size_t bytes;
int ld[1];
PyArrayObject *vden,*vhsml;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
if (pos->dimensions[0] != hsml->dimensions[0])
PyErr_SetString(PyExc_ValueError,"pos and hsml must have the same dimension.");
pos = TO_FLOAT(pos);
hsml = TO_FLOAT(hsml);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
vden = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
vhsml = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
NumPartQ = pos->dimensions[0];
N_gasQ = NumPartQ;
All.Ti_Current=1; /* need to flag active particles */
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
SphQ[i].Hsml = *(float *) (hsml->data + i*(hsml->strides[0]));
}
density_sub();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(vhsml->data + i*(vhsml->strides[0])) = SphQ[i].Hsml;
*(float *)(vden->data + i*(vden->strides[0])) = SphQ[i].Density;
}
free(Q);
free(SphQ);
return Py_BuildValue("OO",vden,vhsml);
}
static PyObject * gadget_SphEvaluate(PyObject* self, PyObject *args)
{
PyArrayObject *pos,*hsml,*obs;
if (! PyArg_ParseTuple(args, "OOO",&pos,&hsml,&obs))
return PyString_FromString("error");
int i;
int input_dimension;
size_t bytes;
int ld[1];
PyArrayObject *vobs;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
if (pos->dimensions[0] != hsml->dimensions[0])
PyErr_SetString(PyExc_ValueError,"pos and hsml must have the same dimension.");
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
pos = TO_FLOAT(pos);
hsml = TO_FLOAT(hsml);
obs = TO_FLOAT(obs);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
vobs = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
NumPartQ = pos->dimensions[0];
N_gasQ = NumPartQ;
All.Ti_Current=1; /* need to flag active particles */
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
SphQ[i].Hsml = *(float *) (hsml->data + i*(hsml->strides[0]));
}
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph_sub();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(vobs->data + i*(vobs->strides[0])) = SphQ[i].Observable;
}
free(Q);
free(SphQ);
return Py_BuildValue("O",vobs);
}
static PyObject * gadget_SphEvaluateW(PyObject* self, PyObject *args)
{
PyArrayObject *pos,*hsml,*obs;
int wmode;
if (! PyArg_ParseTuple(args, "OOOi",&pos,&hsml,&obs,&wmode))
return PyString_FromString("error");
int i;
int input_dimension;
size_t bytes;
int ld[1];
PyArrayObject *vobs;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
if (pos->dimensions[0] != hsml->dimensions[0])
PyErr_SetString(PyExc_ValueError,"pos and hsml must have the same dimension.");
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
pos = TO_FLOAT(pos);
hsml = TO_FLOAT(hsml);
obs = TO_FLOAT(obs);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
vobs = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
NumPartQ = pos->dimensions[0];
N_gasQ = NumPartQ;
All.Ti_Current=1; /* need to flag active particles */
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
SphQ[i].Hsml = *(float *) (hsml->data + i*(hsml->strides[0]));
}
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph_subW(wmode);
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(vobs->data + i*(vobs->strides[0])) = SphQ[i].Observable;
}
free(Q);
free(SphQ);
return Py_BuildValue("O",vobs);
}
static PyObject * gadget_NgbsW(PyObject* self, PyObject *args)
{
PyArrayObject *pos,*hsml,*obs;
if (! PyArg_ParseTuple(args, "OOO",&pos,&hsml,&obs))
return PyString_FromString("error");
int i;
int input_dimension;
size_t bytes;
int ld[1];
PyArrayObject *vobs;
input_dimension =pos->nd;
if (input_dimension != 2)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 2");
if (pos->dimensions[0] != hsml->dimensions[0])
PyErr_SetString(PyExc_ValueError,"pos and hsml must have the same dimension.");
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
pos = TO_FLOAT(pos);
hsml = TO_FLOAT(hsml);
obs = TO_FLOAT(obs);
/* create a NumPy object */
ld[0]=pos->dimensions[0];
vobs = (PyArrayObject *) PyArray_SimpleNew(1,pos->dimensions,pos->descr->type_num);
NumPartQ = pos->dimensions[0];
N_gasQ = NumPartQ;
All.Ti_Current=1; /* need to flag active particles */
if(!(Q = malloc(bytes = NumPartQ * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `Q' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphQ = malloc(bytes = NumPartQ * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphQ' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
for (i = 0; i < pos->dimensions[0]; i++)
{
Q[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
Q[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
Q[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
SphQ[i].Hsml = *(float *) (hsml->data + i*(hsml->strides[0]));
}
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph_NgbsW();
for (i = 0; i < pos->dimensions[0]; i++)
{
*(float *)(vobs->data + i*(vobs->strides[0])) = SphQ[i].Observable;
}
free(Q);
free(SphQ);
return Py_BuildValue("O",vobs);
}
static PyObject * gadget_Ngbs(PyObject* self, PyObject *args)
{
PyArrayObject *pos;
float eps;
if (! PyArg_ParseTuple(args, "Of",&pos,&eps))
return PyString_FromString("error");
PyArrayObject *poss;
int i,j,n,nn;
int input_dimension;
size_t bytes;
int startnode,numngb;
int phase=0;
FLOAT searchcenter[3];
double dx,dy,dz,r2,eps2;
input_dimension =pos->nd;
if (input_dimension != 1)
PyErr_SetString(PyExc_ValueError,"dimension of first argument must be 1");
pos = TO_FLOAT(pos);
eps2 = eps*eps;
searchcenter[0] = (FLOAT)*(float *) (pos->data + 0*(pos->strides[0]));
searchcenter[1] = (FLOAT)*(float *) (pos->data + 1*(pos->strides[0]));
searchcenter[2] = (FLOAT)*(float *) (pos->data + 2*(pos->strides[0]));
startnode = All.MaxPart;
/* ici, il faut faire une fct qui fonctionne en //, cf hydra --> Exportflag */
numngb = ngb_treefind_pairs(&searchcenter[0], (FLOAT)eps, phase, &startnode);
nn=0;
for(n = 0;n < numngb; n++)
{
j = Ngblist[n];
dx = searchcenter[0] - P[j].Pos[0];
dy = searchcenter[1] - P[j].Pos[1];
dz = searchcenter[2] - P[j].Pos[2];
r2 = dx * dx + dy * dy + dz * dz;
if (r2<=eps2)
{
printf("%d r=%g\n",nn,sqrt(r2));
nn++;
}
}
return PyArray_Return(pos);
}
static PyObject * gadget_SphEvaluateOrigAll(PyObject* self, PyObject *args)
{
PyArrayObject *obs;
if (! PyArg_ParseTuple(args, "O",&obs))
return PyString_FromString("error");
int i;
size_t bytes;
int ld[1];
PyArrayObject *vobs;
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
obs = TO_FLOAT(obs);
/* create a NumPy object */
ld[0]=NumPart;
vobs = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
/* flag all particles as active */
for (i = 0; i < NumPart; i++)
P[i].Ti_endstep == All.Ti_Current;
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph_orig();
for (i = 0; i < NumPart; i++)
{
*(float *)(vobs->data + i*(vobs->strides[0])) = SphP[i].Observable;
}
return Py_BuildValue("O",vobs);
}
static PyObject * gadget_SphEvaluateAll(PyObject* self, PyObject *args)
{
PyArrayObject *obs;
if (! PyArg_ParseTuple(args, "O",&obs))
return PyString_FromString("error");
int i;
size_t bytes;
int ld[1];
PyArrayObject *vobs;
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
obs = TO_FLOAT(obs);
/* create a NumPy object */
ld[0]=NumPart;
vobs = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_FLOAT);
/* flag all particles as active */
for (i = 0; i < NumPart; i++)
P[i].Ti_endstep == All.Ti_Current;
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph();
for (i = 0; i < NumPart; i++)
{
*(float *)(vobs->data + i*(vobs->strides[0])) = SphP[i].Observable;
}
return Py_BuildValue("O",vobs);
}
static PyObject * gadget_SphEvaluateGradientAll(PyObject* self, PyObject *args)
{
PyArrayObject *obs;
if (! PyArg_ParseTuple(args, "O",&obs))
return PyString_FromString("error");
int i;
size_t bytes;
npy_intp ld[2];
PyArrayObject *grad;
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
obs = TO_FLOAT(obs);
All.Ti_Current=1; /* need to flag active particles */
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
sph();
/* create a NumPy object */
ld[0] = NumPart;
ld[1] = 3;
grad = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < NumPart; i++)
{
*(float *) (grad->data + i*(grad->strides[0]) + 0*grad->strides[1]) = SphP[i].GradObservable[0];
*(float *) (grad->data + i*(grad->strides[0]) + 1*grad->strides[1]) = SphP[i].GradObservable[1];
*(float *) (grad->data + i*(grad->strides[0]) + 2*grad->strides[1]) = SphP[i].GradObservable[2];
}
return PyArray_Return(grad);
}
static PyObject * gadget_DensityEvaluateAll(PyObject* self, PyObject *args)
{
int i;
/* flag all particles as active */
//All.Ti_Current=1; /* need to flag active particles */
for (i = 0; i < NumPart; i++)
P[i].Ti_endstep == All.Ti_Current;
density(0);
return Py_BuildValue("i",1);
}
static PyObject * gadget_DensityEvaluateGradientAll(PyObject* self, PyObject *args)
{
PyArrayObject *obs;
if (! PyArg_ParseTuple(args, "O",&obs))
return PyString_FromString("error");
int i;
size_t bytes;
npy_intp ld[2];
PyArrayObject *grad;
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
obs = TO_FLOAT(obs);
//All.Ti_Current=1; /* need to flag active particles */
for (i = 0; i < NumPart; i++)
P[i].Ti_endstep == All.Ti_Current;
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
density_sph_gradient();
/* create a NumPy object */
ld[0] = NumPart;
ld[1] = 3;
grad = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < NumPart; i++)
{
*(float *) (grad->data + i*(grad->strides[0]) + 0*grad->strides[1]) = SphP[i].GradObservable[0];
*(float *) (grad->data + i*(grad->strides[0]) + 1*grad->strides[1]) = SphP[i].GradObservable[1];
*(float *) (grad->data + i*(grad->strides[0]) + 2*grad->strides[1]) = SphP[i].GradObservable[2];
}
return PyArray_Return(grad);
}
static PyObject * gadget_EvaluateThermalConductivity(PyObject* self, PyObject *args)
{
PyArrayObject *obs;
if (! PyArg_ParseTuple(args, "O",&obs))
return PyString_FromString("error");
int i;
size_t bytes;
npy_intp ld[2];
PyArrayObject *grad;
if (obs->nd != 1)
PyErr_SetString(PyExc_ValueError,"dimension of obs must be 1.");
if (obs->dimensions[0] != NumPart)
PyErr_SetString(PyExc_ValueError,"The size of obs must be NumPart.");
obs = TO_FLOAT(obs);
//All.Ti_Current=1; /* need to flag active particles */
for (i = 0; i < NumPart; i++)
P[i].Ti_endstep == All.Ti_Current;
/* now, give observable value for P */
for (i = 0; i < NumPart; i++)
{
SphP[i].Observable = *(float *) (obs->data + i*(obs->strides[0]));
}
density_sph_gradient();
// equivalent of SphP[i].GradEnergyInt[0] is now in
//SphP[i].GradObservable[0]
//SphP[i].GradObservable[1]
//SphP[i].GradObservable[2]
/* now, compute thermal conductivity */
sph_thermal_conductivity();
/* create a NumPy object */
ld[0] = NumPart;
ld[1] = 3;
grad = (PyArrayObject *) PyArray_SimpleNew(2,ld,PyArray_FLOAT);
for (i = 0; i < NumPart; i++)
{
*(float *) (grad->data + i*(grad->strides[0]) + 0*grad->strides[1]) = SphP[i].GradObservable[0];
*(float *) (grad->data + i*(grad->strides[0]) + 1*grad->strides[1]) = SphP[i].GradObservable[1];
*(float *) (grad->data + i*(grad->strides[0]) + 2*grad->strides[1]) = SphP[i].GradObservable[2];
}
return PyArray_Return(grad);
}
static PyObject *gadget_LoadParticles2(PyObject *self, PyObject *args, PyObject *kwds)
{
int i,j;
size_t bytes;
PyArrayObject *ntype,*pos,*vel,*mass,*num,*tpe;
static char *kwlist[] = {"npart", "pos","vel","mass","num","tpe", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO",kwlist,&ntype,&pos,&vel,&mass,&num,&tpe))
return Py_BuildValue("i",1);
/* check type */
if (!(PyArray_Check(pos)))
{
PyErr_SetString(PyExc_ValueError,"aruments 1 must be array.");
return NULL;
}
/* check type */
if (!(PyArray_Check(mass)))
{
PyErr_SetString(PyExc_ValueError,"aruments 2 must be array.");
return NULL;
}
/* check dimension */
if ( (pos->nd!=2))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 1 must be 2.");
return NULL;
}
/* check dimension */
if ( (mass->nd!=1))
{
PyErr_SetString(PyExc_ValueError,"Dimension of argument 2 must be 1.");
return NULL;
}
/* check size */
if ( (pos->dimensions[1]!=3))
{
PyErr_SetString(PyExc_ValueError,"First size of argument must be 3.");
return NULL;
}
/* check size */
if ( (pos->dimensions[0]!=mass->dimensions[0]))
{
PyErr_SetString(PyExc_ValueError,"Size of argument 1 must be similar to argument 2.");
return NULL;
}
/* ensure double */
// ntype = TO_INT(ntype);
// pos = TO_FLOAT(pos);
// vel = TO_FLOAT(vel);
// mass = TO_FLOAT(mass);
// num = TO_FLOAT(num);
// tpe = TO_FLOAT(tpe);
/***************************************
* some inits *
/***************************************/
RestartFlag = 0;
Begrun1();
/***************************************
* LOAD PARTILES *
/***************************************/
NumPart = 0;
N_gas = *(int*) (ntype->data + 0*(ntype->strides[0]));
for (i = 0; i < 6; i++)
NumPart += *(int*) (ntype->data + i*(ntype->strides[0]));
if (NumPart!=pos->dimensions[0])
{
PyErr_SetString(PyExc_ValueError,"Numpart != pos->dimensions[0].");
return NULL;
}
MPI_Allreduce(&NumPart, &All.TotNumPart, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce(&N_gas, &All.TotN_gas, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
All.MaxPart = All.PartAllocFactor * (All.TotNumPart / NTask);
All.MaxPartSph = All.PartAllocFactor * (All.TotN_gas / NTask);
/*********************/
/* allocate P */
/*********************/
if(!(P = malloc(bytes = All.MaxPart * sizeof(struct particle_data))))
{
printf("failed to allocate memory for `P' (%g MB).\n", bytes / (1024.0 * 1024.0));
endrun(1);
}
if(!(SphP = malloc(bytes = All.MaxPartSph * sizeof(struct sph_particle_data))))
{
printf("failed to allocate memory for `SphP' (%g MB) %d.\n", bytes / (1024.0 * 1024.0), sizeof(struct sph_particle_data));
endrun(1);
}
/*********************/
/* init P */
/*********************/
float * fpt;
for (i = 0; i < NumPart; i++)
{
//P[i].Pos[0] = *(float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
//P[i].Pos[1] = *(float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
//P[i].Pos[2] = *(float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
//&P[i].Pos[0] = (float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
//&P[i].Pos[1] = (float *) (pos->data + i*(pos->strides[0]) + 1*pos->strides[1]);
//&P[i].Pos[2] = (float *) (pos->data + i*(pos->strides[0]) + 2*pos->strides[1]);
fpt = (float *) (pos->data + i*(pos->strides[0]) + 0*pos->strides[1]);
P[i].Vel[0] = *(float *) (vel->data + i*(vel->strides[0]) + 0*vel->strides[1]);
P[i].Vel[1] = *(float *) (vel->data + i*(vel->strides[0]) + 1*vel->strides[1]);
P[i].Vel[2] = *(float *) (vel->data + i*(vel->strides[0]) + 2*vel->strides[1]);
P[i].Mass = *(float *) (mass->data + i*(mass->strides[0]));
P[i].ID = *(unsigned int *) (num->data + i*(num->strides[0]));
P[i].Type = *(int *) (tpe->data + i*(tpe->strides[0]));
//P[i].Active = 1;
}
/***************************************
* END LOAD PARTILES *
/***************************************/
/***************************************
* finish inits *
/***************************************/
Begrun2();
return Py_BuildValue("i",1);
}
static PyObject *gadget_domain_Decomposition(PyObject *self, PyObject *args, PyObject *kwds)
{
All.NumForcesSinceLastDomainDecomp = 1 + All.TotNumPart * All.TreeDomainUpdateFrequency;
Flag_FullStep = 1; /* to ensure that Peano-Hilber order is done */
domain_Decomposition();
return Py_BuildValue("i",1);
}
static PyObject *gadget_gravity_tree(PyObject *self, PyObject *args, PyObject *kwds)
{
gravity_tree();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_set_particles_timestep(self, args)
PyObject *self;
PyObject *args;
{
int i;
double dt;
if (!PyArg_ParseTuple(args, "d", &dt))
return NULL;
All.Ti_Current = (int) (dt / All.Timebase_interval);
for (i = 0; i < NumPart; i++)
{
P[i].Ti_begstep = (int) 0;
P[i].Ti_endstep = All.Ti_Current;
}
return Py_BuildValue("i",1);
}
#ifdef SFR
static PyObject *
gadget_star_formation(self, args)
PyObject *self;
PyObject *args;
{
star_formation();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_get_id_of_new_stars(self, args)
PyObject *self;
PyObject *args;
{
int i,j;
int Nstars = 0;
PyArrayObject *ids;
npy_intp ld[1];
/* count */
for (i = 0; i < N_gas; i++)
{
if(P[i].Type == ST)
Nstars++;
}
/* create a NumPy object */
ld[0] = Nstars;
ids = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0,j =0; i < N_gas; i++)
if(P[i].Type == ST)
{
*(int *) (ids->data + j*(ids->strides[0])) = P[i].ID;
j++;
}
return PyArray_Return(ids);
}
#endif
#ifdef CHIMIE
static PyObject * Chimie_SetParameters(PyObject *dict)
{
PyObject *key;
PyObject *value;
int ivalue;
float fvalue;
double dvalue;
/* check that it is a PyDictObject */
if(!PyDict_Check(dict))
{
PyErr_SetString(PyExc_AttributeError, "argument is not a dictionary.");
return NULL;
}
if (PyDict_Size(dict)==0)
return Py_BuildValue("i",0);
Py_ssize_t pos=0;
while(PyDict_Next(dict,&pos,&key,&value))
{
if(PyString_Check(key))
{
/* System of units */
if(strcmp(PyString_AsString(key), "UnitLength_in_cm")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitLength_in_cm = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "UnitMass_in_g")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitMass_in_g = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "UnitVelocity_in_cm_per_s")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.UnitVelocity_in_cm_per_s = PyFloat_AsDouble(value);
}
if(strcmp(PyString_AsString(key), "GravityConstantInternal")==0)
{
if(PyInt_Check(value)||PyLong_Check(value)||PyFloat_Check(value))
All.GravityConstantInternal = PyFloat_AsDouble(value);
}
}
}
return Py_BuildValue("i",1);
}
static PyObject * chemistry_InitDefaultParameters(void)
{
/* list of Gadget parameters */
/* System of units */
All.UnitLength_in_cm = 3.085e+21; /* 1.0 kpc */
All.UnitMass_in_g = 1.989e+43; /* 1.0e10 solar masses */
All.UnitVelocity_in_cm_per_s = 20725573.785998672; /* 207 km/sec */
All.GravityConstantInternal = 0;
All.UnitTime_in_s = All.UnitLength_in_cm / All.UnitVelocity_in_cm_per_s;
All.UnitTime_in_Megayears=All.UnitTime_in_s / SEC_PER_MEGAYEAR;
return Py_BuildValue("i",1);
}
static PyObject *
gadget_init_chimie(PyObject *self, PyObject *args, PyObject *kwds)
{
int NumberOfTables=1;
int DefaultTable=0;
PyObject *paramsDict=NULL;
paramsDict= PyDict_New();
//PyObject *filename;
//if (! PyArg_ParseTuple(args, "Oii",&filename,&NumberOfTables,&DefaultTable))
// {
// PyErr_SetString(PyExc_ValueError,"init_chimie, error in parsing.");
// return NULL;
// }
static char *kwlist[] = {"filename","NumberOfTables","DefaultTable","params", NULL};
PyObject *filename=PyString_FromString("chimie.yr.dat");
/* this fails with python2.6, I do not know why ??? */
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OiiO",kwlist,&filename,&NumberOfTables,&DefaultTable,&paramsDict))
{
PyErr_SetString(PyExc_ValueError,"init_chimie, error in parsing arguments.");
return NULL;
}
if (!PyString_Check(filename))
{
PyErr_SetString(PyExc_ValueError,"Argument must be a string.");
return NULL;
}
/* copy filename */
All.ChimieParameterFile = PyString_AsString(filename);
/* set number of tables */
All.ChimieNumberOfParameterFiles = NumberOfTables;
/* check if the file exists */
if(!(fopen(All.ChimieParameterFile, "r")))
{
PyErr_SetString(PyExc_ValueError,"The parameter file does not exists.");
return NULL;
}
/* use default parameters */
chemistry_InitDefaultParameters();
/* check if units are given */
/* check that it is a PyDictObject */
if(!PyDict_Check(paramsDict))
{
PyErr_SetString(PyExc_AttributeError, "argument is not a dictionary.");
return NULL;
}
else
{
Chimie_SetParameters(paramsDict);
}
init_chimie();
/* by default, set the first one */
set_table(DefaultTable);
return Py_BuildValue("O",Py_None);
}
#endif
#ifdef INTEGRAL_CONSERVING_DISSIPATION
static PyObject *
gadget_icd_set_LocalDissipationOn(self, args)
PyObject *self;
PyObject *args;
{
icd_set_LocalDissipationOn();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_icd_set_LocalDissipationOff(self, args)
PyObject *self;
PyObject *args;
{
icd_set_LocalDissipationOff();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_compute_integrals_m1(self, args)
PyObject *self;
PyObject *args;
{
compute_integrals_m1();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_compute_alpha_m1(self, args)
PyObject *self;
PyObject *args;
{
compute_alpha_m1();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_apply_transformation_m1(self, args)
PyObject *self;
PyObject *args;
{
apply_transformation_m1();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_icd_find_ngbs(self, args)
PyObject *self;
PyObject *args;
{
icd_find_ngbs();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_icd_allocate_numlist(self, args)
PyObject *self;
PyObject *args;
{
icd_allocate_numlist();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_icd_free_numlist(self, args)
PyObject *self;
PyObject *args;
{
icd_free_numlist();
return Py_BuildValue("i",1);
}
static PyObject *
gadget_icd_get_alpha(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_alpha());
}
static PyObject *
gadget_icd_get_M(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_M());
}
static PyObject *
gadget_icd_get_X(self, args)
PyObject *self;
PyObject *args;
{
int i;
double x[3];
PyArrayObject *xv;
npy_intp ld[1];
icd_get_X(x);
/* create a NumPy object */
ld[0] = 3;
xv = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_DOUBLE);
for (i = 0; i < 3; i++)
*(double *) (xv->data + i*(xv->strides[0])) = x[i];
return PyArray_Return(xv);
}
static PyObject *
gadget_icd_get_V(self, args)
PyObject *self;
PyObject *args;
{
int i;
double v[3];
PyArrayObject *vv;
npy_intp ld[1];
icd_get_V(v);
/* create a NumPy object */
ld[0] = 3;
vv = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_DOUBLE);
for (i = 0; i < 3; i++)
*(double *) (vv->data + i*(vv->strides[0])) = v[i];
return PyArray_Return(vv);
}
static PyObject *
gadget_icd_get_T(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_T());
}
static PyObject *
gadget_icd_get_I(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_I());
}
static PyObject *
gadget_icd_get_J(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_J());
}
static PyObject *
gadget_icd_get_DeltaTmin(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",icd_get_DeltaTmin());
}
static PyObject *
gadget_icd_set_des_nngb(self, args)
PyObject *self;
PyObject *args;
{
int n;
if (!PyArg_ParseTuple(args, "i", &n))
return NULL;
icd_set_des_nngb(n);
return Py_BuildValue("d",0);
}
static PyObject *
gadget_icd_set_xc(self, args)
PyObject *self;
PyObject *args;
{
int i;
double x[3];
PyArrayObject *vx;
if (!PyArg_ParseTuple(args, "O", &vx))
return NULL;
for (i = 0; i < 3; i++)
x[i] = *(double *) (vx->data + i*(vx->strides[0])) ;
icd_set_xc(x);
return Py_BuildValue("d",0);
}
static PyObject *
gadget_get_Total_Gas_energy_kin(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("d",get_Total_Gas_energy_kin());
}
#endif
#ifdef FOF
static PyObject *
gadget_fof(self, args)
PyObject *self;
PyObject *args;
{
fof();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_init(self, args)
PyObject *self;
PyObject *args;
{
fof_init();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_find_densest_neighbour(self, args)
PyObject *self;
PyObject *args;
{
fof_find_densest_neighbour();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_find_local_heads(self, args)
PyObject *self;
PyObject *args;
{
fof_find_local_heads();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_link_particles_to_local_head(self, args)
PyObject *self;
PyObject *args;
{
fof_link_particles_to_local_head();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_clean_local_groups(self, args)
PyObject *self;
PyObject *args;
{
fof_clean_local_groups();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_compute_local_tails(self, args)
PyObject *self;
PyObject *args;
{
fof_compute_local_tails();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_regroup_pseudo_heads(self, args)
PyObject *self;
PyObject *args;
{
fof_regroup_pseudo_heads();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_send_and_link_pseudo_heads(self, args)
PyObject *self;
PyObject *args;
{
fof_send_and_link_pseudo_heads();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_regroup_exported_pseudo_heads(self, args)
PyObject *self;
PyObject *args;
{
fof_regroup_exported_pseudo_heads();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_write_all_groups(self, args)
PyObject *self;
PyObject *args;
{
fof_write_all_groups();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_allocate_groups(self, args)
PyObject *self;
PyObject *args;
{
fof_allocate_groups();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_compute_groups_properties(self, args)
PyObject *self;
PyObject *args;
{
fof_compute_groups_properties();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_write_groups_properties(self, args)
PyObject *self;
PyObject *args;
{
fof_write_groups_properties();
return Py_BuildValue("i",0);
}
#ifdef SFR
static PyObject *
gadget_fof_star_formation(self, args)
PyObject *self;
PyObject *args;
{
fof_star_formation();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_star_formation_and_IMF_sampling(self, args)
PyObject *self;
PyObject *args;
{
fof_star_formation_and_IMF_sampling();
return Py_BuildValue("i",0);
}
#endif
static PyObject *
gadget_fof_free_groups(self, args)
PyObject *self;
PyObject *args;
{
fof_free_groups();
return Py_BuildValue("i",0);
}
static PyObject *
gadget_fof_get_Total_NumberOfGroups(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("i",Tot_Ngroups);
}
static PyObject *
gadget_fof_get_Total_NumberOfSfrGroups(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("i",Tot_Nsfrgroups);
}
static PyObject *
gadget_fof_get_NumberOfGroups(self, args)
PyObject *self;
PyObject *args;
{
return Py_BuildValue("i",Ngroups);
}
static PyObject *
gadget_fof_get_IDOfParticlesInSfrGroups(self, args)
PyObject *self;
PyObject *args;
{
PyArrayObject *ids;
PyArrayObject *gids;
npy_intp ld[1];
int i,j;
int *id_list;
int gid;
int *nlist,*noffset;
int head_id;
int next;
/*
1) get list of true heads
*/
id_list = malloc(Ntsfrgroups * sizeof(int));
Tot_HeadID_list = malloc(Tot_Ntsfrgroups * sizeof(int));
nlist = malloc(sizeof(int) * NTask);
noffset = malloc(sizeof(int) * NTask);
/* loop over true heads */
if (Nsfrgroups>0)
{
for (gid=0,j=0;gid<Ngroups;gid++)
if( Groups[gid].Task == ThisTask ) /* a true group */
{
if( Groups[gid].SfrFlag == 1 ) /* a groups forming stars */
{
id_list[j] = Groups[gid].HeadID;
//printf("(%d) -->> %d\n",ThisTask,Groups[gid].HeadID);
j++;
}
}
/* print to check */
//for (j=0;j<Ntgroups;j++)
// printf("(%d) --> %d\n",ThisTask,id_list[j]);
}
/* now, the master needs to gather all lists */
//MPI_Gather(&Ntsfrgroups, 1, MPI_INT, nlist, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Allgather(&Ntsfrgroups, 1, MPI_INT, nlist, 1, MPI_INT, MPI_COMM_WORLD);
for(i = 0, noffset[0] = 0; i < NTask; i++)
if(i > 0)
noffset[i] = noffset[i - 1] + nlist[i - 1];
//MPI_Gatherv(id_list,Ntsfrgroups,MPI_INT, Tot_HeadID_list, nlist, noffset, MPI_INT,0, MPI_COMM_WORLD );
MPI_Allgatherv(id_list,Ntsfrgroups,MPI_INT, Tot_HeadID_list, nlist, noffset, MPI_INT, MPI_COMM_WORLD );
free(noffset);
free(nlist);
free(id_list);
/* now, the python part */
ld[0] = Tot_Ntsfrgroups;
ids = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i = 0; i < ids->dimensions[0]; i++)
*(int *) (ids->data + i*(ids->strides[0])) = Tot_HeadID_list[i];
/*
3) get list of particles in each group
*/
PyObject *dict;
PyObject *key;
dict = PyDict_New();
/* loop over all groups */
for (i=0;i<Tot_Ngroups;i++)
{
head_id = Tot_HeadID_list[i]; /* select a true head among the total list */
/* loop over groups */
if (Nsfrgroups>0)
{
for (gid=0;gid<Ngroups;gid++)
{
if(Groups[gid].HeadID==head_id)
{
if(Groups[gid].SfrFlag == 1) /* a groups forming stars */
{
//printf("(%d) >>> %d\n",ThisTask,Groups[gid].Nlocal); /* here, we know how many particles are linked to the head */
/* this works */
//PyDict_SetItem( dict, PyInt_FromLong((long)head_id), PyInt_FromLong((long)Groups[gid].Nlocal) );
/* now, the python part */
ld[0] = Groups[gid].Nlocal;
gids = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (j = 0; j < ids->dimensions[0]; j++)
*(int *) (ids->data + j*(ids->strides[0])) = Tot_HeadID_list[j];
next=Groups[gid].LocalHead;
j=0;
while(next!=-1) /* loop over all local members */
{
//printf("(%d) id=%d\n",ThisTask,P[next].ID); /* here, we get the ids */
*(int *) (gids->data + j*(gids->strides[0])) = P[next].ID;
//printf("(%d) head_id=%d j=%d id=%d\n",ThisTask,head_id,j,P[next].ID);
next=SphP[next].FOF_Next;
j++;
}
PyDict_SetItem( dict, PyInt_FromLong((long)head_id), gids );
}
}
}
}
}
/* release memory */
free(Tot_HeadID_list);
return Py_BuildValue("OO",ids,dict);
//return PyArray_Return(ids);
}
static PyObject *
gadget_fof_get_HeadIDs(self, args)
PyObject *self;
PyObject *args;
{
PyArrayObject *ids;
npy_intp ld[1];
int gid,i;
ld[0] = Ntgroups;
ids = (PyArrayObject *) PyArray_SimpleNew(1,ld,PyArray_INT);
for (i=0,gid=0;gid<Ngroups;gid++)
if( Groups[gid].Task == ThisTask )
{
*(int *) (ids->data + i*(ids->strides[0])) = Groups[gid].HeadID;
i++;
}
return PyArray_Return(ids);
}
#endif // FOF
#ifdef TESSEL
static PyObject *gadget_ConstructDelaunay(PyObject *self, PyObject *args, PyObject *kwds)
{
ConstructDelaunay();
return Py_BuildValue("i",1);
}
static PyObject *gadget_ComputeVoronoi(PyObject *self, PyObject *args, PyObject *kwds)
{
ComputeVoronoi();
return Py_BuildValue("i",1);
}
static PyObject *gadget_ComputeTesselAccelerations(PyObject *self, PyObject *args, PyObject *kwds)
{
tessel_compute_accelerations();
return Py_BuildValue("i",1);
}
static PyObject *gadget_InitvEntropy(PyObject *self, PyObject *args, PyObject *kwds)
{
tessel_convert_energy_to_entropy();
return Py_BuildValue("i",1);
}
static PyObject *gadget_tessel_drift(PyObject *self, PyObject *args, PyObject *kwds)
{
float dt;
if (!PyArg_ParseTuple(args,"f",&dt))
return NULL;
tessel_drift(dt);
return Py_BuildValue("i",1);
}
static PyObject *gadget_tessel_kick(PyObject *self, PyObject *args, PyObject *kwds)
{
float dt;
if (!PyArg_ParseTuple(args,"f",&dt))
return NULL;
tessel_kick(dt);
return Py_BuildValue("i",1);
}
static PyObject *gadget_tessel_get_timestep(PyObject *self, PyObject *args, PyObject *kwds)
{
double dt;
dt = tessel_get_timestep();
return Py_BuildValue("f",(float)dt);
}
static PyObject *gadget_tessel_dump_triangles(PyObject *self, PyObject *args, PyObject *kwds)
{
char *filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
dump_triangles(filename);
return Py_BuildValue("i",1);
}
static PyObject *gadget_tessel_dump_voronoi(PyObject *self, PyObject *args, PyObject *kwds)
{
char *filename;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
dump_voronoi(filename);
return Py_BuildValue("i",1);
}
#endif /*TESSEL*/
/* definition of the method table */
static PyMethodDef gadgetMethods[] = {
{"Info", (PyCFunction)gadget_Info, METH_VARARGS,
"give some info"},
{"InitMPI", (PyCFunction)gadget_InitMPI, METH_VARARGS,
"Init MPI"},
{"InitDefaultParameters", (PyCFunction)gadget_InitDefaultParameters, METH_VARARGS,
"Init default parameters"},
{"GetParameters", (PyCFunction)gadget_GetParameters, METH_VARARGS,
"get gadget parameters"},
{"SetParameters", (PyCFunction)gadget_SetParameters, METH_VARARGS,
"Set gadget parameters"},
{"check_parser", (PyCFunction)gadget_check_parser, METH_VARARGS|METH_KEYWORDS,
"check the parser"},
{"Start", (PyCFunction)gadget_Start, METH_VARARGS|METH_KEYWORDS,
"Start gadget"},
{"LoadParticles", (PyCFunction)gadget_LoadParticles, METH_VARARGS|METH_KEYWORDS,
"LoadParticles partilces"},
{"LoadParticlesQ", (PyCFunction)gadget_LoadParticlesQ, METH_VARARGS,
"LoadParticles partilces Q"},
{"LoadParticles2", (PyCFunction)gadget_LoadParticles2, METH_VARARGS,
"LoadParticles partilces"},
{"AllPotential", (PyCFunction)gadget_AllPotential, METH_VARARGS,
"Computes the potential for each particle"},
{"AllAcceleration", (PyCFunction)gadget_AllAcceleration, METH_VARARGS,
"Computes the gravitational acceleration for each particle"},
{"GetAllAcceleration", (PyCFunction)gadget_GetAllAcceleration, METH_VARARGS,
"get the gravitational acceleration for each particle"},
{"GetAllPotential", (PyCFunction)gadget_GetAllPotential, METH_VARARGS,
"get the potential for each particle"},
{"GetAllDensities", (PyCFunction)gadget_GetAllDensities, METH_VARARGS,
"get the densities for each particle"},
#ifdef DENSITY_INDEPENDENT_SPH
{"GetAllEgyWtDensities", (PyCFunction)gadget_GetAllEgyWtDensities, METH_VARARGS,
"get the egywtdensities for each particle"},
#endif
{"GetAllHsml", (PyCFunction)gadget_GetAllHsml, METH_VARARGS,
"get the sph smoothing length for each particle"},
{"GetAllPositions", (PyCFunction)gadget_GetAllPositions, METH_VARARGS,
"get the position for each particle"},
{"GetAllVelocities", (PyCFunction)gadget_GetAllVelocities, METH_VARARGS,
"get the velocities for each particle"},
{"GetAllCurlVel", (PyCFunction)gadget_GetAllCurlVel, METH_VARARGS,
"get the curl for each particle"},
{"GetAllDivVel", (PyCFunction)gadget_GetAllDivVel, METH_VARARGS,
"get the div for each particle"},
{"GetAllMasses", (PyCFunction)gadget_GetAllMasses, METH_VARARGS,
"get the mass for each particle"},
{"GetAllEnergySpec", (PyCFunction)gadget_GetAllEnergySpec, METH_VARARGS,
"get the specific energy for each particle"},
{"GetAllEntropy", (PyCFunction)gadget_GetAllEntropy, METH_VARARGS,
"get the entropy for each particle"},
{"GetAllID", (PyCFunction)gadget_GetAllID, METH_VARARGS,
"get the ID for each particle"},
{"GetAllTypes", (PyCFunction)gadget_GetAllTypes, METH_VARARGS,
"get the type for each particle"},
#ifdef CHIMIE
{"GetAllMetal", (PyCFunction)gadget_GetAllMetal, METH_VARARGS,
"get the metal for each particle"},
#endif
#ifdef METAL_DIFFUSION
{"GetAllRmsSpeed", (PyCFunction)gadget_GetAllRmsSpeed, METH_VARARGS,
- "get the RmsSpeed for each particle"},
+ "get the RmsSpeed (it corresonds to the square of it) for each particle"},
#endif
{"GetPos", (PyCFunction)gadget_GetPos, METH_VARARGS,
"get the position for each particle (no memory overhead)"},
{"Potential", (PyCFunction)gadget_Potential, METH_VARARGS,
"get the potential for a givent sample of points"},
{"Acceleration", (PyCFunction)gadget_Acceleration, METH_VARARGS,
"get the acceleration for a givent sample of points"},
{"SphEvaluateOrigAll", (PyCFunction)gadget_SphEvaluateOrigAll, METH_VARARGS,
"run the original sph routine."},
{"SphEvaluateAll", (PyCFunction)gadget_SphEvaluateAll, METH_VARARGS,
"compute mean value of a given field based on the sph convolution for all points."},
{"SphEvaluateGradientAll", (PyCFunction)gadget_SphEvaluateGradientAll, METH_VARARGS,
"compute the gradient of a given field based on the sph convolution for all points."},
{"DensityEvaluateAll", (PyCFunction)gadget_DensityEvaluateAll, METH_VARARGS,
"simply run the density function"},
{"DensityEvaluateGradientAll", (PyCFunction)gadget_DensityEvaluateGradientAll, METH_VARARGS,
"run the modified density function and compute a gradient from the given value"},
{"EvaluateThermalConductivity", (PyCFunction)gadget_EvaluateThermalConductivity, METH_VARARGS,
"evaluate the thermal coductivity for each particle"},
{"SphEvaluate", (PyCFunction)gadget_SphEvaluate, METH_VARARGS,
"compute mean value based on the sph convolution for a given number of points"},
{"SphEvaluateW", (PyCFunction)gadget_SphEvaluateW, METH_VARARGS,
"compute mean value based on the sph convolution for a given number of points. The user must specify the kind of weighting (no=0,mass=1,volue=2)"},
{"InitHsml", (PyCFunction)gadget_InitHsml, METH_VARARGS,
"Init hsml based on the three for a given number of points"},
{"Density", (PyCFunction)gadget_Density, METH_VARARGS,
"compute Density based on the three for a given number of points"},
{"NgbsW", (PyCFunction)gadget_NgbsW, METH_VARARGS,
"compute ngbs weights for a given number of points"},
{"Ngbs", (PyCFunction)gadget_Ngbs, METH_VARARGS,
"return the position of the neighbors for a given point"},
{"GetAllPositionsQ", (PyCFunction)gadget_GetAllPositionsQ, METH_VARARGS,
"get the position for each particle Q"},
{"GetAllVelocitiesQ", (PyCFunction)gadget_GetAllVelocitiesQ, METH_VARARGS,
"get the velocities for each particle Q"},
{"GetAllMassesQ", (PyCFunction)gadget_GetAllMassesQ, METH_VARARGS,
"get the mass for each particle Q"},
{"GetAllIDQ", (PyCFunction)gadget_GetAllIDQ, METH_VARARGS,
"get the ID for each particle Q"},
{"GetAllTypesQ", (PyCFunction)gadget_GetAllTypesQ, METH_VARARGS,
"get the type for each particle Q"},
{"Free", (PyCFunction)gadget_Free, METH_VARARGS,
"release memory"},
{"domain_Decomposition", (PyCFunction)gadget_domain_Decomposition, METH_VARARGS,
"call domain_Decomposition"},
{"gravity_tree", (PyCFunction)gadget_gravity_tree, METH_VARARGS,
"call gravity_tree"},
#ifdef SFR
{"set_particles_timestep", gadget_set_particles_timestep, METH_VARARGS,
"Give a time step to each particles"},
{"star_formation", gadget_star_formation, METH_VARARGS,
"compute star formation"},
{"get_id_of_new_stars", gadget_get_id_of_new_stars, METH_VARARGS,
"get id of new stars"},
#endif
#ifdef CHIMIE
{"init_chimie", gadget_init_chimie, METH_VARARGS| METH_KEYWORDS,
"init the chemistry module"},
#endif
#ifdef INTEGRAL_CONSERVING_DISSIPATION
{"icd_set_LocalDissipationOn", gadget_icd_set_LocalDissipationOn, METH_VARARGS,
"Enable local dissipation for the intergral conserving dissipation scheme"},
{"icd_set_LocalDissipationOff", gadget_icd_set_LocalDissipationOff, METH_VARARGS,
"Disable local dissipation for the intergral conserving dissipation scheme"},
{"icd_set_des_nngb", gadget_icd_set_des_nngb, METH_VARARGS,
"set number of neighbors for the intergral conserving dissipation scheme"},
{"icd_set_xc", gadget_icd_set_xc, METH_VARARGS,
"set center for the intergral conserving dissipation scheme"},
{"compute_integrals_m1", gadget_compute_integrals_m1, METH_VARARGS,
"Compute integrals needed for the intergral conserving dissipation scheme"},
{"compute_alpha_m1", gadget_compute_alpha_m1, METH_VARARGS,
"Compute alpha needed for the intergral conserving dissipation scheme"},
{"apply_transformation_m1", gadget_apply_transformation_m1, METH_VARARGS,
"apply the velocity transformation for the intergral conserving dissipation scheme"},
{"icd_find_ngbs", gadget_icd_find_ngbs, METH_VARARGS,
"find neighboring particles for the intergral conserving dissipation scheme"},
{"icd_find_ngbs", gadget_icd_find_ngbs, METH_VARARGS,
"find neighboring particles for the intergral conserving dissipation scheme"},
{"icd_allocate_numlist", gadget_icd_allocate_numlist, METH_VARARGS,
"allocate numlist particles for the intergral conserving dissipation scheme"},
{"icd_free_numlist", gadget_icd_free_numlist, METH_VARARGS,
"free numlist particles for the intergral conserving dissipation scheme"},
{"icd_get_alpha", gadget_icd_get_alpha, METH_VARARGS,
"Get alpha needed for the intergral conserving dissipation scheme"},
{"icd_get_M", gadget_icd_get_M, METH_VARARGS,
"Get mass involved for the intergral conserving dissipation scheme"},
{"icd_get_X", gadget_icd_get_X, METH_VARARGS,
"Get X involved for the intergral conserving dissipation scheme"},
{"icd_get_V", gadget_icd_get_V, METH_VARARGS,
"Get V involved for the intergral conserving dissipation scheme"},
{"icd_get_T", gadget_icd_get_T, METH_VARARGS,
"Get kinetic inergy involved for the intergral conserving dissipation scheme"},
{"icd_get_I", gadget_icd_get_I, METH_VARARGS,
"Get I inergy involved for the intergral conserving dissipation scheme"},
{"icd_get_J", gadget_icd_get_J, METH_VARARGS,
"Get J inergy involved for the intergral conserving dissipation scheme"},
{"icd_get_DeltaTmin", gadget_icd_get_DeltaTmin, METH_VARARGS,
"Get DeltaTmin for the intergral conserving dissipation scheme"},
{"get_Total_Gas_energy_kin", gadget_get_Total_Gas_energy_kin, METH_VARARGS,
"Get the total gas kinetic energy"},
#endif
#ifdef FOF
{"fof", gadget_fof, METH_VARARGS,
"compute friends of friends (call the full routine)"},
{"fof_init", gadget_fof_init, METH_VARARGS,
"init fof parameters"},
{"fof_find_densest_neighbour", gadget_fof_find_densest_neighbour, METH_VARARGS,
"find densest neighbour"},
{"fof_find_local_heads", gadget_fof_find_local_heads, METH_VARARGS,
"find local heads"},
{"fof_link_particles_to_local_head", gadget_fof_link_particles_to_local_head, METH_VARARGS,
"link particles to local head"},
{"fof_clean_local_groups", gadget_fof_clean_local_groups, METH_VARARGS,
"clean local groups"},
{"fof_compute_local_tails", gadget_fof_compute_local_tails, METH_VARARGS,
"compute local tails"},
{"fof_regroup_pseudo_heads", gadget_fof_regroup_pseudo_heads, METH_VARARGS,
"regroup pseudo heads"},
{"fof_send_and_link_pseudo_heads", gadget_fof_send_and_link_pseudo_heads, METH_VARARGS,
"send and link pseudo heads"},
{"fof_regroup_exported_pseudo_heads", gadget_fof_regroup_exported_pseudo_heads, METH_VARARGS,
"regroup exported pseudo heads"},
{"fof_write_all_groups", gadget_fof_write_all_groups, METH_VARARGS,
"write all groups"},
{"fof_allocate_groups", gadget_fof_allocate_groups, METH_VARARGS,
"allocate memory for the group structure"},
{"fof_compute_groups_properties", gadget_fof_compute_groups_properties, METH_VARARGS,
"compute groups properties"},
{"fof_write_groups_properties", gadget_fof_write_groups_properties, METH_VARARGS,
"write groups properties"},
#ifdef SFR
{"fof_star_formation", gadget_fof_star_formation, METH_VARARGS,
"turn particles of star forming groups into stellar particles"},
{"fof_star_formation_and_IMF_sampling", gadget_fof_star_formation_and_IMF_sampling, METH_VARARGS,
"turn particles of star forming groups into stellar particles and adress them stellar properties according to an IMF"},
#endif
{"fof_free_groups", gadget_fof_free_groups, METH_VARARGS,
"release memory for the group structure"},
{"fof_get_Total_NumberOfGroups", gadget_fof_get_Total_NumberOfGroups, METH_VARARGS,
"get the total number of groups"},
{"fof_get_Total_NumberOfSfrGroups", gadget_fof_get_Total_NumberOfSfrGroups, METH_VARARGS,
"get the total number of star forming groups"},
{"fof_get_NumberOfGroups", gadget_fof_get_NumberOfGroups, METH_VARARGS,
"get the local number of groups"},
{"fof_get_IDOfParticlesInSfrGroups", gadget_fof_get_IDOfParticlesInSfrGroups, METH_VARARGS,
"get Head ID's"},
{"fof_get_HeadIDs", gadget_fof_get_HeadIDs, METH_VARARGS,
"get local Head ID's"},
#endif // FOF
#ifdef TESSEL
{"ConstructDelaunay", (PyCFunction)gadget_ConstructDelaunay, METH_VARARGS,
"Construct the Delaunay tesselation"},
{"ComputeVoronoi", (PyCFunction)gadget_ComputeVoronoi, METH_VARARGS,
"Compute the Voronoi tesselation"},
{"ComputeTesselAccelerations", (PyCFunction)gadget_ComputeTesselAccelerations, METH_VARARGS,
"Compute the acceleration using the tesselation"},
{"InitvEntropy", (PyCFunction)gadget_InitvEntropy, METH_VARARGS,
"Initialize vEntropy using internal energy."},
{"tessel_drift", (PyCFunction)gadget_tessel_drift, METH_VARARGS,
"drift particles"},
{"tessel_kick", (PyCFunction)gadget_tessel_kick, METH_VARARGS,
"kick particles"},
{"tessel_get_timestep", (PyCFunction)gadget_tessel_get_timestep, METH_VARARGS,
"get timestep for tessel"},
{"tessel_dump_triangles", (PyCFunction)gadget_tessel_dump_triangles, METH_VARARGS,
"dump triangles"},
{"tessel_dump_voronoi", (PyCFunction)gadget_tessel_dump_voronoi, METH_VARARGS,
"dump voronoi"},
{"GetAllDelaunayTriangles", (PyCFunction)gadget_GetAllDelaunayTriangles, METH_VARARGS,
"Get all the Delaunay Triangles"},
{"GetAllvPoints", gadget_GetAllvPoints, METH_VARARGS,
"Get voronoi points"},
{"GetAllvDensities", gadget_GetAllvDensities, METH_VARARGS,
"Get voronoi density of all points"},
{"GetAllvVolumes", gadget_GetAllvVolumes, METH_VARARGS,
"Get voronoi volumes of all points"},
{"GetAllvPressures", gadget_GetAllvPressures, METH_VARARGS,
"Get voronoi presures of all points"},
{"GetAllvEnergySpec", gadget_GetAllvEnergySpec, METH_VARARGS,
"Get voronoi energyspec of all points"},
{"GetAllvAccelerations", gadget_GetAllvAccelerations, METH_VARARGS,
"Get voronoi accelerations of all points"},
{"GetvPointsForOnePoint", gadget_GetvPointsForOnePoint, METH_VARARGS,
"Get voronoi points for a given point"},
{"GetNgbPointsForOnePoint", gadget_GetNgbPointsForOnePoint, METH_VARARGS,
"Get neighbors points for a given point"},
{"GetNgbPointsAndFacesForOnePoint", gadget_GetNgbPointsAndFacesForOnePoint, METH_VARARGS,
"Get neighbors points and faces for a given point"},
{"GetAllGhostPositions", gadget_GetAllGhostPositions, METH_VARARGS,
"Get all positions of the ghosts points"},
{"GetAllGhostvDensities", gadget_GetAllGhostvDensities, METH_VARARGS,
"Get all densities of the ghosts points"},
{"GetAllGhostvVolumes", gadget_GetAllGhostvVolumes, METH_VARARGS,
"Get all volumes of the ghosts points"},
#endif
{NULL, NULL, 0, NULL} /* Sentinel */
};
void initgadget(void)
{
(void) Py_InitModule("gadget", gadgetMethods);
import_array();
}
#endif /*PY_INTERFACE*/

Event Timeline