-
Matthieu Schaller authored
Former-commit-id: b506d1bb917124e96c060792920ebfe0856d83f6
Matthieu Schaller authoredFormer-commit-id: b506d1bb917124e96c060792920ebfe0856d83f6
multipole.c 4.78 KiB
/*******************************************************************************
* This file is part of SWIFT.
* Coypright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
/* Config parameters. */
#include "../config.h"
/* Some standard headers. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <limits.h>
/* MPI headers. */
#ifdef WITH_MPI
#include <mpi.h>
#endif
/* Local headers. */
#include "error.h"
#include "const.h"
#include "cycle.h"
#include "atomic.h"
#include "lock.h"
#include "space.h"
#include "part.h"
#include "multipole.h"
#include "cell.h"
/**
* @brief Merge two multipoles.
*
* @param ma The #multipole which will contain the merged result.
* @param mb The other #multipole.
*/
void multipole_merge ( struct multipole *ma , struct multipole *mb ) {
#if multipole_order == 1
/* Correct the position. */
float mma = ma->coeffs[0], mmb = mb->coeffs[0];
float w = 1.0f / ( mma + mmb );
for ( int k = 0 ; k < 3 ; k++ )
ma->x[k] = ( ma->x[k]*mma + mb->x[k]*mmb ) * w;
/* Add the particle to the moments. */
ma->coeffs[0] = mma + mmb;
#else
#error( "Multipoles of order %i not yet implemented." , multipole_order )
#endif
}
/**
* @brief Add a particle to the given multipole.
*
* @param m The #multipole.
* @param p The #gpart.
*/
void multipole_addpart ( struct multipole *m , struct gpart *p ) {
#if multipole_order == 1
/* Correct the position. */
float mm = m->coeffs[0], mp = p->mass;
float w = 1.0f / ( mm + mp );
for ( int k = 0 ; k < 3 ; k++ )
m->x[k] = ( m->x[k]*mm + p->x[k]*mp ) * w;
/* Add the particle to the moments. */
m->coeffs[0] = mm + mp;
#else
#error( "Multipoles of order %i not yet implemented." , multipole_order )
#endif
}
/**
* @brief Add a group of particles to the given multipole.
*
* @param m The #multipole.
* @param p The #gpart array.
* @param N Number of parts to add.
*/
void multipole_addparts ( struct multipole *m , struct gpart *p , int N ) {
#if multipole_order == 1
/* Get the combined mass and positions. */
double xp[3] = { 0.0 , 0.0 , 0.0 };
float mp = 0.0f, w;
for ( int k = 0 ; k < N ; k++ ) {
w = p[k].mass;
mp += w;
xp[0] += p[k].x[0] * w;
xp[1] += p[k].x[1] * w;
xp[2] += p[k].x[2] * w;
}
/* Correct the position. */
float mm = m->coeffs[0];
w = 1.0f / ( mm + mp );
for ( int k = 0 ; k < 3 ; k++ )
m->x[k] = ( m->x[k]*mm + xp[k] ) * w;
/* Add the particle to the moments. */
m->coeffs[0] = mm + mp;
#else
#error( "Multipoles of order %i not yet implemented." , multipole_order )
#endif
}
/**
* @brief Init a multipole from a set of particles.
*
* @param m The #multipole.
* @param parts The #gpart.
* @param N The number of particles.
*/
void multipole_init ( struct multipole *m , struct gpart *parts , int N ) {
#if multipole_order == 1
float mass = 0.0f, w;
double x[3] = { 0.0 , 0.0 , 0.0 };
int k;
/* Collect the particle data. */
for ( k = 0 ; k < N ; k++ ) {
w = parts[k].mass;
mass += w;
x[0] += parts[k].x[0] * w;
x[1] += parts[k].x[1] * w;
x[2] += parts[k].x[2] * w;
}
/* Store the data on the multipole. */
m->coeffs[0] = mass;
m->x[0] = x[0] / mass;
m->x[1] = x[1] / mass;
m->x[2] = x[2] / mass;
#else
#error( "Multipoles of order %i not yet implemented." , multipole_order )
#endif
}
/**
* @brief Reset the data of a #multipole.
*
* @param m The #multipole.
*/
void multipole_reset ( struct multipole *m ) {
/* Just bzero the struct. */
bzero( m , sizeof(struct multipole) );
}