/*
DFT++ is a density functional package developed by the research group
of Professor Tomas Arias
Copyright 1996-2003 Sohrab Ismail-Beigi
This file is part of DFT++.
DFT++ is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
DFT++ 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 General Public License
along with DFT++; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Please see the file CREDITS for a list of authors.
For academic users, we request that publications using results obtained with
this software reference
"New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi
and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000).
and, if using the wavelet basis, further reference
"Multiresolution analysis of electronic structure: semicardinal and wavelet bases,"
T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999).
and
"Robust ab initio calculation of condensed matter: transparent convergence through
semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and
Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003).
For your convenience, preprints of the above articles may be obtained from
http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively.
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <fcntl.h> /* for low level i/o */
#include <time.h>
#include <unistd.h>
#include "WL_header.h"
double gauss_sigma=4.;
/*****************************************************************************/
/* Evaluating a function on the Grid */
/* Computes zero function at a point in space (OUTPUT)
r: real-space point
return value: value of function
*/
double zero(struct Dvec r)
{
return( 0. );
}
/* Computes identity function at a point in space (OUTPUT)
r: real-space point
return value: value of function
*/
double one(struct Dvec r)
{
return( 1. );
}
/* Computes random number uniformly on [-0.5,0.5) at a point in
space (OUTPUT)
r: real-space point
return value: value of function
*/
double rnd(struct Dvec r)
{
static int randflag=1;
if(randflag){
printf("\n WARNING: rand() is ***COMPILER DEPENDENT***!!!!\n");
printf(" Make sure rnd(Dvec) gives doubles in (-.5:.5)\n");
printf("\trand() ?? [int]\t rand()/(RAND_MAX+1.) ?? [0..1)\n");
printf("CHECK: %f\t\t %f\n\n",1.0*rand(),rand()/(RAND_MAX+1.));
randflag=0;
}
return( rand()/(RAND_MAX+1.0)-0.5 );
}
double X(struct Dvec r)
{
return r.x;
}
double Y(struct Dvec r)
{
return r.y;
}
double Z(struct Dvec r)
{
return r.z;
}
double TEST(struct Dvec r, struct Dvec param)
{
return param.x;
}
double sinx(struct Dvec r)
{
return sin( (r.x+r.y +r.z));
}
double SIN(struct Dvec r, struct Dvec k)
{
return sin(r.x*k.x+r.y*k.y+r.z*k.z);
}
double COS(struct Dvec r, struct Dvec k)
{
return cos(r.x*k.x+r.y*k.y+r.z*k.z);
}
/* Computes random number uniformly on [0.095,1.005)
1% (actually +/-05%) random noise
*/
double rnd01()
{
static int randflag=1;
if(randflag){
printf(" WARNING: rand() is ***COMPILER DEPENDENT***!!!!\n");
printf(" CHECK if rand() gives doubles in (0:1)\n\n");
randflag=0;
}
return( 1.+ 0.01*(rand()/(RAND_MAX+1.)-0.5 ));
}
/* Computes random number uniformly on [0.95,1.05)
10% (actually +/-5%) random noise
*/
double rnd10()
{
static int randflag=1;
if(randflag){
printf(" WARNING: rand() is ***COMPILER DEPENDENT***!!!!\n");
printf(" CHECK if rand() gives doubles in (0:1)\n\n");
randflag=0;
}
return( 1.+ 0.5*(rand()/(RAND_MAX+1.)-0.5 ));
}
/* Computes the electrostatic potential at a point in space (OUTPUT)
based on the chargedensity from Teter's "pseudo-nuclear potential"
r: real-space point
return value: value of function
*/
double Z1V(struct Dvec r)
{
const double pi = M_PI;
double absr,output;
double Z,c1,c2,c3,d,d1,d2,d3;
Z=10.;
c1=3.132576693428;c2=-2.68355838224;c3=1-c1-c2;
d=1./(4.*Z);
d1=d/sqrt(2.);d2=d;d3=sqrt(2.)*d;
absr= sqrt(pow(r.x,2.)+pow(r.y,2.)+pow(r.z,2.));
if ( absr<.0000000000001)
output=
Z*c1*2./(sqrt(pi)*d1)+
Z*c2*2./(sqrt(pi)*d2)+
Z*c3*2./(sqrt(pi)*d3);
else
output=
Z*c1*erf(absr/d1)/absr+
Z*c2*erf(absr/d2)/absr+
Z*c3*erf(absr/d3)/absr;
return(output);
}
/* Computes a 1s wavefunction at a point in space (OUTPUT)
r: real-space point
return value: value of function
*/
double s1(struct Dvec r)
{
const double pi = M_PI;
double absr;
absr= sqrt(pow(r.x,2)+pow(r.y,2)+pow(r.z,2));
return( exp(-absr)/sqrt(pi) );
}
/* Computes a multinomial function at a point in space (OUTPUT)
r: real-space point
return value: value of function
*/
int gaussflag=1;
double gauss(struct Dvec r)
{
const double pi = M_PI;
double xce=12.0, yce=12.0, zce=12.0; /* centered at (12., 12., 12.) */
double rsq;
if (gaussflag){
printf("Sigma = %lf\n",gauss_sigma);
gaussflag=0;
}
/* rsq= pow(r.x,2)+pow(r.y,2)+pow(r.z,2); */
rsq = (r.x-xce)*(r.x-xce) + (r.y-yce)*(r.y-yce) + (r.z-zce)*(r.z-zce);
/* this one is for wave functions */
return sqrt(sqrt(2./pi)/(gauss_sigma*gauss_sigma*gauss_sigma*4.*pi)
*exp(-rsq/(2.*gauss_sigma*gauss_sigma)) );
/* this is original gaussian */
return sqrt(sqrt(2./pi)/(gauss_sigma*gauss_sigma*gauss_sigma*4.*pi)
*exp(-rsq/(2.*gauss_sigma*gauss_sigma)) );
}
/* Parabolic potential for a SHO */
int SHOflag=1;
double SHO(struct Dvec in)
{
/* double xce=8.,yce=8.,zce=8.; */
/* double k=1.; */
double xce=12.0, yce=12.0, zce=12.0;/* centered at (12., 12., 12.) */
double k=0.00390625; /* 1/256 for sigma=4. */
int alpha=2;int beta=2;int gamma=2;
if (SHOflag)
{
printf("Center of potential taken to be %f %f %f\n",xce,yce,zce);
printf("Spring constant taken to be %f => sigma ~= %f.\n",k,pow(k,-0.25));
SHOflag=0;
}
return( 0.5*k*(pow(in.x-xce,alpha)+pow(in.y-yce,beta)+pow(in.z-zce,gamma)) );
}
/*
Copy the grid to 1D aray to consolidate te memory, so that we can use
BLAS routines RECURSIVE FUNCTION
a: pointer to pointer of the array where we are going to write
needs to be pointer to pointer in order that called children
and siblings are able to update it, after they fill the data in
self: pointer to the current data of the grid
the array has to be alocated in the calling function!!!
we cannot check if we have enough space from here
*/
void
copygridtoarray(double **a,struct Grid *ingrid)
{
/* the memory has to be allocated in the calling function */
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (ingrid==NULL)
return;
/* IPD: can we roll te pointer back??
NO, because only the top level knows it the whole size
but we can teach all the levels to know it :) later*/
/* Fill in data */
{
int i,j,k;
for (i=0; i<ingrid->dim.x; i++)
for (j=0; j<ingrid->dim.y; j++)
for (k=0; k<ingrid->dim.z; k++){
/* printf("k= %d *a= %d **a= %d\n",k, *a, **a); */
**a = *( ingrid->dat+(i*ingrid->dim.y+j)*ingrid->dim.z+k );
/* printf("k= %d *a= %d **a= %f\n",k, *a, **a); */
(*a)++;
}
}
/* Call sibling and child, return immediately if none */
/* we choose the order to match readfromfile() and writetofile() */
if (ingrid->sibling!=NULL){
/* printf("Copying next sibling...\n"); */
copygridtoarray(a,ingrid->sibling);
}
if (ingrid->child!=NULL) {
/* printf("Copying next child...\n"); */
copygridtoarray(a,ingrid->child);
}
return;
}
/*
Copy 1D aray to grid; inverse to copygridtoarray
a: pointer to pointer of the array where we are going to write
needs to be pointer to pointer in order that called children
and siblings are able to update it, after they fill the data in
self: pointer to the current data of the grid
the array has to be alocated in the calling function!!!
we cannot check if we have enough space from here
*/
void
copyarraytogrid(struct Grid *self, double **a)
{
/* the memory has to be allocated in the calling function */
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Fill in data */
{
int i,j,k;
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = **a;
(*a)++;
}
}
/* Call sibling and child, return immediately if none */
/* we choose the order to match readfromfile() and writetofile() */
if (self->sibling!=NULL){
/* printf("Copying next sibling...\n"); */
copyarraytogrid(self->sibling,a);
}
if (self->child!=NULL) {
/* printf("Copying next child...\n"); */
copyarraytogrid(self->child,a);
}
return;
}
/* Replace the parent level in a grid with a new parent.
All we have to do is set the new parent pointer of the first level grids
and also chenge their origin to reflect the position in the new parent
Recursive function
self: pointer to the current grid
displ: displacement of the origin. org is always in the parent's
coordinates, therefore when changing parents an update may be
necessary
newparent: the newparent of the grid
*/
void setnewparent(struct Grid *self,struct Ivec displ, struct Grid *newparent)
{
self->parent = newparent;
self->org.x += displ.x;
self->org.y += displ.y;
self->org.z += displ.z;
/* tell your sibling about the change in family */
if(self->sibling)
setnewparent(self->sibling,displ,newparent);
return;
}
/*
Evaluates a real space function on a struct Grid (RECURSIVE FUNCTION)
self: pointer to Grid to be filled
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
func: the real-space function to be evaluated on the Grid
*/
void
evalgrid(struct Grid *self, struct Dvec porg,
double func(struct Dvec) )
{
/* Scale of children (if any) */
struct Dvec scl;
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* set the scale */
scl=self->scale;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*scl.x;
org.y = porg.y + self->org.y *2*scl.y;
org.z = porg.z + self->org.z *2*scl.z;
/* printf("evalgrid: origin is: %18.12lf %18.12lf %5d %18.12lf\n", */
/* org.x, porg.x, self->org.x, scl.x); */
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*scl.x;
r.y=org.y+j*scl.y;
r.z=org.z+k*scl.z;
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = func(r);
}
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
evalgrid(self->child,org,func);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
evalgrid(self->sibling,porg,func);
}
return;
}
void
evalgrid_cutoff(struct Grid *self, struct Dvec porg,
struct Dvec Rc, double Rcutoff, double func(struct Dvec) )
{
/* Scale of children (if any) */
struct Dvec scl;
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* set the scale */
scl=self->scale;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*scl.x;
org.y = porg.y + self->org.y *2*scl.y;
org.z = porg.z + self->org.z *2*scl.z;
/* printf("evalgrid: origin is: %18.12lf %18.12lf %5d %18.12lf\n", */
/* org.x, porg.x, self->org.x, scl.x); */
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*scl.x - Rc.x; /* find coord relative to Rc */
r.y=org.y+j*scl.y - Rc.y;
r.z=org.z+k*scl.z - Rc.z;
if((r.x*r.x+r.y*r.y+r.z*r.z) < (Rcutoff*Rcutoff))
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = func(r);
else
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = 0.;
}
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
evalgrid_cutoff(self->child,org,Rc,Rcutoff,func);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
evalgrid_cutoff(self->sibling,porg,Rc,Rcutoff,func);
}
return;
}
/*
Evaluates a real space function on a struct Grid (RECURSIVE FUNCTION)
Imposes Periodic Boundary Conditions (orthorombic cells ONLY)
self: pointer to Grid to be filled
scl: physical scale (along x, y and z) of the Grid to be filled
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
R: Latice vectors lengths (orthorombic cells ONLY)
func: the real-space function to be evaluated on the Grid
*/
void
evalgrid_periodic(struct Grid *self, struct Dvec porg,
struct Dvec R, double func(struct Dvec) )
{
/* Scale of children (if any) */
struct Dvec scl;
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* set the scale */
scl=self->scale;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*scl.x;
org.y = porg.y + self->org.y *2*scl.y;
org.z = porg.z + self->org.z *2*scl.z;
/* printf("evalgrid: origin is: %18.12lf %18.12lf %5d %18.12lf\n", */
/* org.x, porg.x, self->org.x, scl.x); */
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*scl.x;
r.y=org.y+j*scl.y;
r.z=org.z+k*scl.z;
/* Wrap to the nearest lattice image to the origin */
r.x-=R.x*rint(r.x/R.x);
r.y-=R.y*rint(r.y/R.y);
r.z-=R.z*rint(r.z/R.z);
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = func(r);
}
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
evalgrid_periodic(self->child,org,R,func);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
evalgrid_periodic(self->sibling,porg,R,func);
}
return;
}
/*
Evaluates a real space function on a struct Grid (RECURSIVE FUNCTION)
self: pointer to Grid to be filled
param: parameter to pass to the function that is evaluated
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
func: the real-space function to be evaluated on the Grid
has an EXTRA PARAMETER of DVEC type
*/
void
evalgrid_param(struct Grid *self, struct Dvec param, struct Dvec porg,
double func(struct Dvec, struct Dvec) )
{
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2 * self->scale.x;
org.y = porg.y + self->org.y *2 * self->scale.y;
org.z = porg.z + self->org.z *2 * self->scale.z;
/* printf("evalgrid: origin is: %18.12lf %18.12lf %5d %18.12lf\n", */
/* org.x, porg.x, self->org.x, scl.x); */
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*self->scale.x;
r.y=org.y+j*self->scale.y;
r.z=org.z+k*self->scale.z;
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = func(r,param);
}
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
evalgrid_param(self->child, param, org, func);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
evalgrid_param(self->sibling, param, porg, func);
}
return;
}
/*
Sets data below certain level to zero (RECURSIVE FUNCTION)
self: pointer to Grid to be filled
level:All levels bellow are set to zero
*/
void
setbelowtozero(struct Grid *self, int level)
{
/* Scale of children (if any) */
int i,j,k;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
if(self->level>level){
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = 0.;
}
}
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
setbelowtozero(self->child,level);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
setbelowtozero(self->sibling,level);
}
return;
}
/*
Evaluates a real space function on a struct Grid (RECURSIVE FUNCTION)
self: pointer to Grid to be filled
scl: physical scale (along x, y and z) of the Grid to be filled
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
func: the real-space function to be evaluated on the Grid
*/
void
evalgridgen(struct Grid *self, struct Dvec porg, double func(struct Dvec) )
/* evalgridgen(struct Grid *self, */
/* struct Dvec scl, struct Dvec porg, */
/* int int1, */
/* double func(struct Dvec, int) ) */
{
/* Scale of children (if any) */
struct Dvec scl;
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
struct Dvec r;
printf("Hello1\n");
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* set the scale */
scl=self->scale;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*scl.x;
org.y = porg.y + self->org.y *2*scl.y;
org.z = porg.z + self->org.z *2*scl.z;
printf("Hello2\n");
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*scl.x;
r.y=org.y+j*scl.y;
r.z=org.z+k*scl.z;
printf("The numbers are: %18.12lf %18.12lf %18.12lf\n",
r.x,r.y,r.z );
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
func(r);
/* *( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = */
/* func(r, int1); */
}
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL)
evalgridgen(self->child,org,func);
if (self->sibling!=NULL)
evalgridgen(self->sibling,porg,func);
/* if (self->child!=NULL) */
/* evalgridgen(self->child,cscl,org,int1,func); */
/* if (self->sibling!=NULL) */
/* evalgridgen(self->sibling,scl,porg,int1,func); */
return;
}
/*
Multiplies each grid point by random number given by rnd_func()
in this way the ghost should remain zero and if we want to add
for example 10% noice to each point we can multiply by random
number in [.9:1.1]
RECURSIVE FUNCTION
self: pointer to Grid to be filled
*/
void
addrndnoisetogrid(struct Grid *self,double rnd_func())
{
int i,j,k;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) *= rnd_func();
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
addrndnoisetogrid(self->child,rnd_func);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
addrndnoisetogrid(self->sibling,rnd_func);
}
return;
}
/*
Evaluates a real space function on a struct Grid (RECURSIVE FUNCTION)
self: pointer to Grid to be filled
scl: physical scale (along x, y and z) of the Grid to be filled
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
func: the real-space function to be evaluated on the Grid
*/
void
evalgridpad(struct Grid *self, struct Dvec porg,
struct Dvec top, int pad, double func(struct Dvec) )
{
/* Scale of children (if any) */
struct Dvec scl;
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k;
/*int i2,j2,k2;*/
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* set teh scale */
scl=self->scale;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*scl.x;
org.y = porg.y + self->org.y *2*scl.y;
org.z = porg.z + self->org.z *2*scl.z;
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++)
{
r.x=org.x+i*scl.x;
r.y=org.y+j*scl.y;
r.z=org.z+k*scl.z;
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = func(r);
}
/* for (i=0; i<self->dim.x; i++) */
/* for (j=0; j<self->dim.y; j++) */
/* for (k=0; k<self->dim.z; k++) */
/* { */
/* *( self->dat+(i*self->dim.y+j)*self->dim.z+k ) = 0; */
/* for (i2=-pad; i2<=pad; i2++) */
/* for (j2-pad; j2<=pad; j2++) */
/* for (k2-pad; k2<=pad; k2++) */
/* { */
/* r.x=org.x+i*scl.x+i2*top.x; */
/* r.y=org.y+j*scl.y+j2*top.y; */
/* r.z=org.z+k*scl.z+k2*top.z; */
/* *( self->dat+(i*self->dim.y+j)*self->dim.z+k ) */
/* += func(r); */
/* } */
/* } */
/* Grab data from up above to ensure consistency */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
*( self->dat+(i*self->dim.y+j)*self->dim.z+k ) =
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) );
/* Call child and sibling, return immediately if none */
if (self->child!=NULL)
evalgrid(self->child,org,func);
if (self->sibling!=NULL)
evalgrid(self->sibling,porg,func);
return;
}
/*Sums up the values coefficients recursively*/
double sumgrid(struct Grid *ingrid)
{
int ix,iy,iz;
double sum=0.;
int nnx,nny,nnz;
nnx=ingrid->dim.x;
nny=ingrid->dim.y;
nnz=ingrid->dim.z;
for (ix=0;ix<nnx;ix++)
for (iy=0;iy<nny;iy++)
for (iz=0;iz<nnz;iz++)
if ( ( (ix%2 == 1) || (iy%2 == 1) || (iz%2 == 1) ) || (!ingrid->parent) )
sum+=ingrid->dat[iz+(nnz*(iy+nny*ix))];
printf("Sum is: %d %20.16lf\n",ingrid->level,sum);
if (ingrid->sibling)
sum+=sumgrid(ingrid->sibling);
if (ingrid->child)
sum+=sumgrid(ingrid->child);
return(sum);
}
/*A function which outputs the values on the grid, including
all lower level coefficients, from the center of each grid. Can only
be used when there is one region of refinement which is right
below the grid above it*/
void
outputfromcenter(struct Grid *ingrid)
{
int i,j,k;
int counter;
double scalefact;
i=ingrid->dim.x;j=ingrid->dim.y;k=ingrid->dim.z;
scalefact=1./ingrid->scale.x;
for (counter=(int) (k/2); counter< k ; counter++)
printf(" %18.12lf %18.12lf\n",
(double) (counter- (k/2))/scalefact,
ingrid->dat[((i/2)*j*k)+(j/2)*k+counter]);
if (ingrid->child)
outputfromcenter(ingrid->child);
}
/*A function which outputs the values in a plane*/
void
outputplane(struct Grid *ingrid, int recursion)
{
int i,j,k;
int counter1,counter2;
/*double scalefact; */
i=ingrid->dim.x;j=ingrid->dim.y;k=ingrid->dim.z;
/* scalefact=1./ingrid->scale.x;*/printf("WARNING:scalefact in outputplane\n\n");
for (counter1=0; counter1< i ; counter1++)
{
printf("\n");
for (counter2=0; counter2< j ; counter2++)
printf(" %18.12lf",ingrid->dat[counter1*j*k+counter2*k+(int)(k/2) ]);
/* printf(" %18.12lf %18.12lf %18.12lf\n", */
/* (double) (counter1- (i/2))/scalefact, */
/* (double) (counter2- (j/2))/scalefact, */
/* ingrid->dat[counter1*j*k+counter2*k+(int)(k/2) ]); */
/* ingrid->dat[((i/2)*j*k)+(j/2)*k+counter1]); */
}
if (ingrid->child)
if (recursion)
outputplane(ingrid->child,recursion);
}
/* Using Teter's nuclear charge distribution*/
double nucpot_debug(struct Dvec r, double Z)
{
const double pi = M_PI;
const double c1=3.132576693428;
const double c2=-2.68355838224;
const double c3=1-c1-c2;
double d,d1,d2,d3;
double rad=sqrt(r.x*r.x+r.y*r.y+r.z*r.z);
double charge;
double tmp1, tmp2, tmp3;
d=1./(4.*Z);
d1=d/sqrt(2.); d2=d; d3=sqrt(2.)*d;
charge = c1*exp(-(rad/d1)*(rad/d1))/(d1*d1*d1)+
c2*exp(-(rad/d2)*(rad/d2))/(d2*d2*d2);
/* charge += c3*exp(-(rad/d3)*(rad/d3))/(d3*d3*d3); */
tmp1= (rad/d3)*(rad/d3);
tmp2=exp(-tmp1);
tmp2*=c3;
charge/=pow(pi,1.5);
return(charge);
}
/*****************************************************************************/
/* Grid algebra */
/*
Sum all elements of a grid (includes ghosts) (OUT, RECURSIVE FUNCTION)
self: pointer to grid hierarchies to be summed
displayeachlevel: if this flag is set to 1 we will output
the sum on each level, otherwise we
will only return the complete sum*/
double gridsum(struct Grid *self, int displayeachlevel)
{
double sum=0.;
int i;
/* does it pay to do it?? 07/10/00 i.d.
int nlx,nly,nlz;
int num;
int gnum;
nlx=self->dim.x;
nly=self->dim.y;
nlz=self->dim.z;
*/
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return(0.);
/* printf("No of gridpoints is: %d\n", */
/* gnum=self->dim.x*self->dim.y*self->dim.z); */
for (i=0; i<self->dim.x*self->dim.y*self->dim.z; i++)
sum+=(*(self->dat+i));
if (displayeachlevel)
printf("level is: %d sum is: %18.14lf\n",self->level,sum);
/* Add in contributions from children and siblings */
if (self->child)
sum+=gridsum(self->child,displayeachlevel);
if (self->sibling)
sum+=gridsum(self->sibling,displayeachlevel);
return(sum);
}
/*
Sum absolute value of all elements of a Grid (includes ghosts)
(OUT, RECURSIVE FUNCTION)
self: pointer to grid hierarchies to be summed
displayeachlevel: if this flag is set to 1 we will output
the sum on each level, otherwise we
will only return the complete sum*/
double gridsumabs(struct Grid *self, int displayeachlevel)
{
double sum=0.;
int i;
/* seems it is not used 07/10/00 i.d.
int nlx,nly,nlz;
nlx=self->dim.x;
nly=self->dim.y;
nlz=self->dim.z;
*/
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return(0.);
for (i=0; i<self->dim.x*self->dim.y*self->dim.z; i++)
sum+=fabs((*(self->dat+i)));
if (displayeachlevel)
printf("level is: %d sum is: %18.14lf\n",self->level,sum);
/* Add in contributions from children and siblings */
if (self->child)
sum+=gridsumabs(self->child,displayeachlevel);
if (self->sibling)
sum+=gridsumabs(self->sibling,displayeachlevel);
return(sum);
}
/*
Grid dot product, ignoring ghosts (OUT, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
self1, self2: pointer to grid hierarchies to be dotted together
*/
double griddot(struct Grid *self1,struct Grid *self2)
{
double dot=0.;
int i,j,k;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self1==NULL || self2==NULL) return(0.);
/* One quick consistency check */
if (
self1->dim.x != self2->dim.x ||
self1->dim.y != self2->dim.y ||
self1->dim.z != self2->dim.z
)
{
fprintf(stderr,"Grids in griddot do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Dot product from own level */
if (self1->level>0)
{
/* Must skip ghosts on lower levels */
/* There certainly must be more efficient ways to do this! */
for (i=0; i<self1->dim.x; i++)
for (j=0; j<self1->dim.y; j++)
for (k=0; k<self1->dim.z; k++)
if ( (i%2)+(j%2)+(k%2) > 0)
{
dot+=
(*( self1->dat
+ (i * self1->dim.y + j) * self1->dim.z
+ k ))
*
(*( self2->dat
+ (i * self2->dim.y + j) * self2->dim.z
+ k ));
}
}
else
{
/* On upper level, no skipping */
for (i=0; i<self1->dim.x; i++)
for (j=0; j<self1->dim.y; j++)
for (k=0; k<self1->dim.z; k++)
dot+=
(*( self1->dat
+ (i * self1->dim.y + j) * self1->dim.z
+ k ))
*
(*( self2->dat
+ (i * self2->dim.y + j) * self2->dim.z
+ k ));
}
/* Add in contributions from children and siblings */
dot+=griddot(self1->child, self2->child);
dot+=griddot(self1->sibling, self2->sibling);
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("D: "); */
/* for (level=0; level< self1->level; level++) */
/* printf(" "); */
/* printf("[%d] %lf\n",self1->level,self); */
/* } */
return(dot);
}
/*
Grid subtraction (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridsub(struct Grid *diff,struct Grid *in1,struct Grid *in2)
{
int i,limit;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (diff==NULL || in1==NULL || in2==NULL) return;
/* One quick consistency check */
if (
diff->dim.x != in1->dim.x ||
diff->dim.y != in1->dim.y ||
diff->dim.z != in1->dim.z ||
diff->dim.x != in2->dim.x ||
diff->dim.y != in2->dim.y ||
diff->dim.z != in2->dim.z
)
{
printf(" %d %d \n %d %d \n %d %d \n %d %d \n %d %d \n %d %d \n level: %d level: %d level: %d\n",
diff->dim.x,in1->dim.x,
diff->dim.y,in1->dim.y,
diff->dim.z,in1->dim.z,
diff->dim.x,in2->dim.x,
diff->dim.y,in2->dim.y,
diff->dim.z,in2->dim.z,
diff->level,in1->level,in2->level);
fprintf(stderr,"Grids in gridsub do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
limit=diff->dim.x*diff->dim.y*diff->dim.z;
/* Do subtraction of data on this level (no need to worry about ghosts!) */
for (i=0; i<limit; i++)
*(diff->dat+i)=*(in1->dat+i)-*(in2->dat+i);
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("S: "); */
/* for (level=0; level< diff->level; level++) */
/* printf(" "); */
/* printf("[%d]\n",diff->level); */
/* } */
/* Subtract children and siblings */
gridsub(diff->child, in1->child, in2->child);
gridsub(diff->sibling, in1->sibling, in2->sibling);
return;
}
/*
Grid subtraction (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
/* IPD: we can check if the grids have the same total size to avoid
SEG FAULTS, though we have to make sure all grid constructors set
nxyzwholegrid member.
Right now we are probably quite safe, since we are using only one
gridspec and if some day we need different grid hierarchies this
can prevent us from bugs */
void gridsubnew(struct Grid *diff,struct Grid *in1,struct Grid *in2)
{
int i,limit;
limit=diff->nxyzwholegrid;
if(in1->nxyzwholegrid !=limit || in2->nxyzwholegrid!=limit){
printf("Incompatible grid sizes in gridsubnew!!\n");
exit(1);
}
/* Do subtraction of data on this level (no need to worry about ghosts!) */
for (i=0; i<limit; i++)
*(diff->dat+i)=*(in1->dat+i)-*(in2->dat+i);
return;
}
/*
Grid subtraction (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
does only one level - loops ofer cousins
*/
void gridsub_level(struct Grid *diff,struct Grid *in1,struct Grid *in2)
{
int i,limit;
struct Grid *a=diff, *b=in1, *c=in2;
while (a && b && c){
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
/* One quick consistency check */
if ( a->dim.x != b->dim.x || a->dim.y != b->dim.y ||
a->dim.z != b->dim.z || a->dim.x != c->dim.x ||
a->dim.y != c->dim.y || a->dim.z != c->dim.z ) {
printf(" %d %d \n %d %d \n %d %d \n %d %d \n %d %d \n %d %d\n",
a->dim.x,b->dim.x,a->dim.y,b->dim.y,a->dim.z,b->dim.z,
a->dim.x,c->dim.x,a->dim.y,c->dim.y,a->dim.z,c->dim.z);
printf("level: %d level: %d level: %d\n",
a->level, b->level, c->level);
fprintf(stderr,"Grids in gridsub_level not consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
limit=a->nxyz;
/* Do subtraction of data on this grid */
for (i=0; i<limit; i++)
a->dat[i]= b->dat[i] - c->dat[i];
/* go to the next grid in the list */
a=a->cousin; b=b->cousin; c=c->cousin;
}
}
/* This sets a grid that has the number of times each point is repeated
over the whole grid structure (on the same level)
quotient: output grid (may be a grid consisting of just one level)
in: grid containing the whole tree (we need it in order to determine
the real origin of the grids, so that we can tell if the grids overlap
We use a loop, rather than a recursion, to save the stack
This will do the whole level */
void getquotient_new(struct Grid *quotient,struct Grid *in)
{
struct Grid *a, *b, *qa, *qb;
a = in;
qa = quotient;
/* loop over a->cousin */
while(a && qa){
b = a;
qb = qa;
/* loop over cousins and check for overlaps */
while(b){
/* check if a overlaps with b, in which case
increment the coresponding reqions of qa and qb */
/* go to the next cousin of b */
b = b->cousin;
qb = qb->cousin;
}
/* go to the next grid in the list */
a = a->cousin;
qa = qa->cousin;
}
}
/* Give the origin of a grid in absolute cooridnates
Goes up to the top of the tree and adds up the origin displacement
in the coordinate system of each parent */
struct Ivec get_abs_org(struct Grid *self)
{
struct Ivec origin;
struct Grid *p;
int scale;
origin=NULLIVEC;
p=self;
scale=2;
while(p){
origin.x=origin.x + scale*p->org.x;
origin.y=origin.y + scale*p->org.y;
origin.z=origin.z + scale*p->org.z;
p=p->parent;
scale*=2;
}
return origin;
}
int max(int x, int y)
{
if(x<y)
return y;
return x;
}
int min(int x, int y)
{
if (x>y)
return y;
return x;
}
/* checks if two rectangular grids overlap, and if yes returns
the coordinates of the overlapping region
a, b: input grids
ivera_i, overa_e - beginning and end of the ovrlap in a's coordinate
iverb_i, overb_e - beginning and end of the ovrlap in b's coordinates */
int ifoverlap(struct Grid *a, struct Grid *b,
struct Ivec *overa_b, struct Ivec *overa_e)
/* struct Ivec *overb_b, struct Ivec *overb_e) */
{
struct Ivec orga, orgb;
/* could have some consistency checks here */
if( a->scale.x-b->scale.x || a->scale.z-b->scale.z ||
a->scale.z-b->scale.z){
printf("\n\n inconsistency of scales in ifoverlap %lf %lf %lf %lf %lf!!\n", a->scale.x, b->scale.x, a->scale.z, b->scale.z, a->scale.z,b->scale.z );
exit(1);
}
/* find the absolute coordinates of the origins of a and b
(they may belong to different parents) */
orga=get_abs_org(a);
orgb=get_abs_org(b);
overa_b->x=max(0, orgb.x-orga.x);
overa_e->x=min(a->dim.x, orgb.x + b->dim.x - orga.x);
overa_b->y=max(0, orgb.y-orga.y);
overa_e->y=min(a->dim.y, orgb.y + b->dim.y - orga.y);
overa_b->z=max(0, orgb.z-orga.z);
overa_e->z=min(a->dim.z, orgb.z + b->dim.z - orga.z);
if( overa_b->x<overa_e->x && overa_b->z<overa_e->y &&
overa_b->z<overa_e->z ){
/* they do overlap;*/
/* printf("%d %d %d %d %d %d\n", */
/* overa_b->x, overa_e->x, */
/* overa_b->y, overa_e->y, */
/* overa_b->z, overa_e->z); */
return 1;
}
return 0;
}
/* Finds if b overlaps a and if so, increases the quotient in the
overlapping region of a on the grid qa */
void addquotient(struct Grid *qa, struct Grid *a, struct Grid *b)
{
int i, j, k; /* counters */
/* beginning and end of the overlapping region in coord of a & b */
struct Ivec overab, overae;
struct Ivec overbb, overbe;
if( ifoverlap(a, b, &overab, &overae) ){
/* printf("l %d: addquotient: %d %d %d %d %d %d\n",a->level,
overab.x, overae.x,
overab.y, overae.y,
overab.z, overae.z);
*/
/* now do the increments */
for(i=overab.x; i<overae.x; i++)
for(j=overab.y; j<overae.y; j++)
for(k=overab.z; k<overae.z; k++){
(*(qa->dat + (i*qa->dim.y + j)*qa->dim.z +k))++;
/* printf("%lf ",
a->dat[(i*a->dim.y + j)*a->dim.z +k]); */
}
}
}
/* this one does sets the quotient on just one grid (not a whole level */
void getquotient(struct Grid *q, struct Grid *in)
{
struct Grid *a;
int i;
a = in;
/* first zero out the quotient grid */
for (i=0; i<q->nxyz; i++)
q->dat[i]=0;
/* we must loop over all the grids ono the current level, so let's
go to the "first" one (it has to be the same always): */
/* go to the top of the tree */
while (a->parent)
a=a->parent;
/* then go down to the furst grid on the current level
WARNING: potential bug!! What if the first child tree doesn't
go to the lowest level!!!
The way to avoid this is to have a routine that traverses the
grid tree through children and siblings and gets us the next
grid of a given level. And this one is recursive
while(a=getnext_of_level(a, next, itisnext)){
addquotient(q, in, a);
*itisnext=0;
} */
while (a->level<q->level && a->child)
a=a->child;
if (a->level!=q->level){
printf("level %d not found in getquotient()!\n", q->level);
exit(2);
}
/* now loop over q->cousin to visit everybody on the current level */
while(a){
/* set the quotients */
addquotient(q, in, a);
/* go to the next grid in the list */
a = a->cousin;
}
}
/* Dot product for overlapping grids. The regions that overlap must be
counted only once. The way to do it is to find the quotients
and then divide by them when doing the dot product
This will increase the computational cost by at least factor of 2
but we can think later on doing better (e.g. keep static the overlaps,
so that they are not computed over and over, and preprocess the data
before multiply, only in the overlapping regions) */
double griddot_overlap(struct Grid *in1, struct Grid *in2)
{
struct Grid q;/* quotient - avoid overcounting on overlaps */
double dot=0.;
int i,j,k;
int pos;/* position of the data to be multiplied */
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (in1==NULL || in2==NULL) return(0.);
/* One quick consistency check */
if ( in1->dim.x != in2->dim.x ||
in1->dim.y != in2->dim.y ||
in1->dim.z != in2->dim.z){
fprintf(stderr,"Grids in griddot do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
q=*in1;/* set up the quotient grid as in1 */
if( (q.dat=(double *)malloc(q.nxyz * sizeof(double))) == NULL){
printf("Undable to allocate data in griddot_overlap()\n");
exit(1);
}
getquotient(&q, in1);
/* Dot product from own level */
if (in1->level>0) {
/* Must skip ghosts on lower levels */
/* There certainly must be more efficient ways to do this! */
for (i=0; i<in1->dim.x; i++)
for (j=0; j<in1->dim.y; j++)
for (k=0; k<in1->dim.z; k++)
if ( i%2 || j%2 || k%2){
pos=(i * in1->dim.y + j) * in1->dim.z + k;
dot+=
(*( in1->dat + pos ))
*
(*( in2->dat +pos))
/
(*( q.dat +pos));
}
}
else {
/* On he top level, no skipping */
for (i=0; i<in1->dim.x; i++)
for (j=0; j<in1->dim.y; j++)
for (k=0; k<in1->dim.z; k++){
pos=(i * in1->dim.y + j) * in1->dim.z + k;
dot+=
(*( in1->dat + pos ))
*
(*( in2->dat +pos))
/
(*( q.dat +pos));
}
}
free(q.dat);
/* Add in contributions from children and siblings */
dot+=griddot_overlap(in1->child, in2->child);
dot+=griddot_overlap(in1->sibling, in2->sibling);
return(dot);
}
/* loops over self->cousin (and the parellel structture grid) and
whenever two grids have overlapping regions adds diff on these
regions */
void addon_overlap_regions_level(struct Grid* self, struct Grid* add)
{
struct Grid *a, *b, *aa, *ab;
struct Ivec overa_b, overa_e, overb_b, overb_e;
int ia, ja, ka, ib, jb, kb;
int posa, posb;
int aob, boa;/* overlap of a&b and b&a */
/* struct Grid *p; */
a=self;
aa=add;
while(a){
b=a->cousin;/* always need different grids */
ab=aa->cousin;
while(b){
/* here find if a and b overlap */
aob=ifoverlap(a,b, &overa_b, &overa_e);
boa=ifoverlap(b,a, &overb_b, &overb_e);
if(boa+aob){/* they overlap */
if (!boa*aob) {
printf("Error in addon_overlap_regions_level()\n");
printf("if a overlaps b, then b overlaps a\n");
exit(1);
}
/*a+=ab (overlap region of a&b only)
b+=ba (overlap region of b&a only)
use while loop, because if the parallel indexing
(most symmetric in this case) */
/*
printf("overlaps %d %d %d, %d %d %d\n",
overa_b.x,overa_b.y,overa_b.z,
overb_b.x, overb_b.y, overb_b.z );
printf("overlaps %d %d %d, %d %d %d\n",
overa_e.x,overa_e.y,overa_e.z,
overb_e.x, overb_e.y, overb_e.z );
*/
ia=overa_b.x; ib=overb_b.x;
while( ia<overa_e.x && ib<overb_e.x ){
ja=overa_b.y; jb=overb_b.y;
while( ja<overa_e.y && jb<overb_e.y){
ka=overa_b.z; kb=overb_b.z;
while( ka<overa_e.z && kb<overb_e.z){
posa = (ia*a->dim.y + ja)*a->dim.z +ka;
posb = (ib*b->dim.y + jb)*b->dim.z +kb;
*(a->dat+posa) += *(ab->dat +posb);
*(b->dat+posb) += *(aa->dat +posa);
ka++;
kb++;
}
ja++;
jb++;
}
ia++;
ib++;
}
}
b=b->cousin;
ab=ab->cousin;
}
a=a->cousin;
aa=aa->cousin;
}
}
/*
Grid addition (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridadd(struct Grid *sum,struct Grid *in1,struct Grid *in2)
{
int i;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (sum==NULL || in1==NULL || in2==NULL) return;
/* One quick consistency check */
if (
sum->dim.x != in1->dim.x ||
sum->dim.y != in1->dim.y ||
sum->dim.z != in1->dim.z ||
sum->dim.x != in2->dim.x ||
sum->dim.y != in2->dim.y ||
sum->dim.z != in2->dim.z
)
{
fprintf(stderr,"Grids in gridadd do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<sum->dim.x*sum->dim.y*sum->dim.z; i++)
*(sum->dat+i)=*(in1->dat+i)+*(in2->dat+i);
/* Add children and siblings */
gridadd(sum->child, in1->child, in2->child);
gridadd(sum->sibling, in1->sibling, in2->sibling);
return;
}
/* Simple grid addition
WARNING: Must be identical hierarchies, there is no way to check this!
sum, in1, in2: pointers to output and input hierarchies */
void gridaddnew(struct Grid *sum,struct Grid *in1,struct Grid *in2)
{
int i;
int limit;
limit=sum->nxyzwholegrid;
if(in1->nxyzwholegrid !=limit || in2->nxyzwholegrid!=limit){
printf("Incompatible grid sizes in gridsubnew!!\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<limit; i++)
*(sum->dat+i)=*(in1->dat+i)+*(in2->dat+i);
return;
}
/* Adds in to out. */
void gridaccum(struct Grid *out,struct Grid *in)
{
int i;
int limit;
limit=out->nxyzwholegrid;
if(in->nxyzwholegrid !=limit){
printf("Incompatible grid sizes in gridaccum!!\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<limit; i++)
*(out->dat+i)+=(*(in->dat+i));
return;
}
/* Multiply Grid by a scalar.*/
void scalarmult(struct Grid *out,double op2, struct Grid *in)
{
int i,limit;
limit=in->dim.x*in->dim.y*in->dim.z;
for (i=0;i<limit;i++)
(*(out->dat+i))=(*(in->dat+i))*op2;
if (in->sibling)
scalarmult(out->sibling,op2,in->sibling);
if (in->child)
scalarmult(out->child,op2,in->child);
}
/* Multiply Grid by a scalar.*/
void scalarmultnew(struct Grid *out, double op2, struct Grid *in)
{
int i,limit;
if(out->nxyzwholegrid != (limit=in->nxyzwholegrid)){
printf("Incompatible grid sizes in scalarmultnew()!\n");
exit(1);
}
for (i=0;i<limit;i++)
(*(out->dat+i))=(*(in->dat+i))*op2;
}
/* Multiply Grid by a scalar.*/
/* Go recursive, because we do not know if the data is continuous */
void scalarmultself(struct Grid *self,double d)
{
int i,limit;
limit=self->dim.x*self->dim.y*self->dim.z;
for (i=0;i<limit;i++)
(*(self->dat+i))*=d;
if (self->sibling)
scalarmultself(self->sibling,d);
if (self->child)
scalarmultself(self->child,d);
}
void scalareqself(struct Grid *self,double d)
{
int i,limit;
limit=self->dim.x*self->dim.y*self->dim.z;
for (i=0;i<limit;i++)
(*(self->dat+i))=d;
if (self->sibling)
scalareqself(self->sibling,d);
if (self->child)
scalareqself(self->child,d);
}
/* Multiply Grid by a scalar and add it to out.*/
void scalarmultadd(struct Grid *out,double op2, struct Grid *in)
{
int i,limit;
limit=in->dim.x*in->dim.y*in->dim.z;
for (i=0;i<limit;i++)
(*(out->dat+i))+=(*(in->dat+i))*op2;
if (in->sibling)
scalarmultadd(out->sibling,op2,in->sibling);
if (in->child)
scalarmultadd(out->child,op2,in->child);
}
/* Multiply Grid by a scalar and subtract it from out.*/
void scalarmultsubtract(struct Grid *out,double op2, struct Grid *in)
{
int i,limit;
limit=in->dim.x*in->dim.y*in->dim.z;
for (i=0;i<limit;i++)
(*(out->dat+i))-=(*(in->dat+i))*op2;
if (in->sibling)
scalarmultsubtract(out->sibling,op2,in->sibling);
if (in->child)
scalarmultsubtract(out->child,op2,in->child);
}
/* Multiply Grid by a scalar.*/
void scalarmultcum(struct Grid *out,double op2, struct Grid *in)
{
int i,limit;
limit=in->dim.x*in->dim.y*in->dim.z;
/* printf("Before in scalarmultcum: %12.10lf %12.10lf %12.10lf\n", */
/* out->dat[0],in->dat[0],op2); */
for (i=0;i<limit;i++)
*(out->dat+i) += (*(in->dat+i))*op2;
if (in->sibling)
scalarmultcum(out->sibling,op2,in->sibling);
if (in->child)
scalarmultcum(out->child,op2,in->child);
}
/* Multiply grid by a scalar.*/
void scalarmultcumnew(struct Grid *out,double op2, struct Grid *in)
{
int i,limit;
limit=in->nxyzwholegrid;
for (i=0;i<limit;i++)
*(out->dat+i)+=(*(in->dat+i))*op2;
}
/*
Grid point multiplication (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridptmult(struct Grid *out, struct Grid *in1, struct Grid *in2)
{
int i;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (out==NULL || in1==NULL || in2==NULL) return;
/* One quick consistency check */
if (
out->dim.x != in1->dim.x || out->dim.y != in1->dim.y ||
out->dim.z != in1->dim.z || out->dim.x != in2->dim.x ||
out->dim.y != in2->dim.y || out->dim.z != in2->dim.z
)
{
fprintf(stderr,"Grids in gridpmult do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<out->dim.x*out->dim.y*out->dim.z; i++)
*(out->dat+i) = (*(in1->dat+i))*(*(in2->dat+i));
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("PM: "); */
/* for (level=0; level< out->level; level++) */
/* printf(" "); */
/* printf("[%d]\n",out->level); */
/* } */
/* Add children and siblings */
gridptmult(out->child, in1->child, in2->child);
gridptmult(out->sibling, in1->sibling, in2->sibling);
return;
}
/*
Grid point division (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridptdiv(struct Grid *out, struct Grid *in1, struct Grid *in2)
{
int i;
/* Return immediately with zero if there is nothing to do */
if (out==NULL || in1==NULL || in2==NULL) return;
/* One quick consistency check */
if ( out->dim.x != in1->dim.x || out->dim.y != in1->dim.y ||
out->dim.z != in1->dim.z || out->dim.x != in2->dim.x ||
out->dim.y != in2->dim.y || out->dim.z != in2->dim.z ) {
fprintf(stderr,"Grids in gridpmult do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Do addition of data on this level (check worry the ghosts!) */
for (i=0; i<out->dim.x*out->dim.y*out->dim.z; i++)
if( *(in2->dat+i) )
*(out->dat+i) = (*(in1->dat+i))/(*(in2->dat+i));
/* Add children and siblings */
gridptdiv(out->child, in1->child, in2->child);
gridptdiv(out->sibling, in1->sibling, in2->sibling);
return;
}
/*
IPD: Inplace point-multiply of one grid by another
Grid point multiplication (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are different, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridptmulteq(struct Grid *out,struct Grid *in)
{
int i;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (out==NULL || in==NULL) return;
/* One quick consistency check */
if (
out->dim.x != in->dim.x ||
out->dim.y != in->dim.y ||
out->dim.z != in->dim.z ||
out->dim.x != in->dim.x ||
out->dim.y != in->dim.y ||
out->dim.z != in->dim.z
)
{
fprintf(stderr,"Grids in gridpmult do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<out->dim.x*out->dim.y*out->dim.z; i++)
*(out->dat+i)*=(*(in->dat+i));
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("PM: "); */
/* for (level=0; level< out->level; level++) */
/* printf(" "); */
/* printf("[%d]\n",out->level); */
/* } */
/* Add children and siblings */
gridptmulteq(out->child, in->child);
gridptmulteq(out->sibling, in->sibling);
return;
}
/*
Grid point multiplication (IN PLACE, RECURSIVE FUNCTION)
WARNING: Must be identical hierarchies, there is no way to check this!
Probably if hierachies are proderent, SEG FAULTS will result.
diff, in1, in2: pointers to output and input hierarchies
*/
void gridptmultnew(struct Grid *prod,struct Grid *in1,struct Grid *in2)
{
int i,limit;
limit=in1->nxyzwholegrid;
for (i=0; i<limit; i++)
*(prod->dat+i)=(*(in1->dat+i))*(*(in2->dat+i));
return;
}
void gridptmulteqnew(struct Grid *out,struct Grid *in)
{
int i,limit;
limit=in->nxyzwholegrid;
for (i=0; i<limit; i++)
*(out->dat+i)*=(*(in->dat+i));
return;
}
/* Square the data on a realgrid */
void abs2(struct Grid *out,struct Grid *in)
{
int i;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (out==NULL || in==NULL) return;
/* One quick consistency check */
if (
out->dim.x != in->dim.x || out->dim.y != in->dim.y ||
out->dim.z != in->dim.z) {
fprintf(stderr,"Grids in gridpmult do not appear consistent!\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Do addition of data on this level (no need to worry about ghosts!) */
for (i=0; i<out->dim.x*out->dim.y*out->dim.z; i++)
*(out->dat+i)=(*(in->dat+i))*(*(in->dat+i));
abs2(out->child, in->child);
abs2(out->sibling, in->sibling);
return;
}
double gridcarrot(struct Grid *in1,struct Grid *in2)
{
int i;
int limit;
int ix,iy,iz;
double out=0;
/* limit=in1->dim.x*in1->dim.y*in1->dim.z; */
/* for (i=0; i<limit; i++) */
/* out+=in1->dat[i]*in2->dat[i]; */
if (in1->parent){
for (ix=0;ix<in2->dim.x;ix++)
for (iy=0;iy<in2->dim.y;iy++)
for (iz=0;iz<in2->dim.z;iz++)
if ( (ix%2 == 1) || (iy%2 == 1) || (iz%2 == 1) )
out+=(in1->dat[iz+in2->dim.z*iy+in2->dim.z*in2->dim.y*ix])
*(in2->dat[iz+in2->dim.z*iy+in2->dim.z*in2->dim.y*ix]);
}
else{
limit=in2->dim.x*in2->dim.y*in2->dim.z;
for (i=0; i<limit; i++)
out+=in1->dat[i]*in2->dat[i];
}
if (in1->sibling)
out+=gridcarrot(in1->sibling,in2->sibling);
if (in1->child)
out+=gridcarrot(in1->child,in2->child);
return(out);
}
/* This gridcarrot will only work on grids in the coefficient space */
/* representation, which obey the convention that the coefficients */
/* on the ghostpoints are 0 */
double gridcarrotsimple(struct Grid *in1,struct Grid *in2)
{
int i;
int limit;
double out=0;
limit=in1->dim.x*in1->dim.y*in1->dim.z;
for (i=0; i<limit; i++)
out+=in1->dat[i]*in2->dat[i];
if (in1->sibling)
out+=gridcarrotsimple(in1->sibling,in2->sibling);
if (in1->child)
out+=gridcarrotsimple(in1->child,in2->child);
return(out);
}
/* This gridcarrot will only work on grids in the coefficient space */
/* representation, which obey the convention that the coefficients */
/* on the ghostpoints are 0 */
double gridcarrotnew(struct Grid *in1,struct Grid *in2)
{
int i,limit;
double out=0;
limit=in1->nxyzwholegrid;
for (i=0; i<limit; i++)
out+=in1->dat[i]*in2->dat[i];
return(out);
}
void projectoutgrid(struct Grid *main, struct Grid *in1, double coeff)
{
int i;
for (i=0;i<main->nxyz;i++)
main->dat[i]-= coeff*in1->dat[i];
if (main->child)
projectoutgrid(main->child,in1->child, coeff);
if (main->sibling)
projectoutgrid(main->sibling,in1->sibling, coeff);
}
void projectoutgridnew(struct Grid *main, struct Grid *in1, double coeff)
{
int i;
for (i=0;i<main->nxyzwholegrid;i++)
main->dat[i]-= coeff*in1->dat[i];
}
/*****************************************************************************/
/* Consistency routines */
void putzerosbelow(struct Grid *ingrid, int boundary)
{
int i;
if (ingrid->level > boundary)
for (i=0;i<ingrid->nxyz;i++)
ingrid->dat[i]=0.;
if (ingrid->child)
putzerosbelow(ingrid->child,boundary);
if (ingrid->sibling)
putzerosbelow(ingrid->sibling,boundary);
}
/* Impose consistency of ghost points */
void zeroghost(struct Grid *ingrid)
{
int i,j,k;
int nlx,nly,nlz;
nlx=ingrid->dim.x;
nly=ingrid->dim.y;
nlz=ingrid->dim.z;
for (i=0; i<nlx; i+=2)
for (j=0; j<nly; j+=2)
for (k=0; k<nlz; k+=2)
*( ingrid->dat+(i*nly+j)*nlz+k ) =
0.;
}
void zeroghostrec(struct Grid *ingrid)
{
if (ingrid->level)
zeroghost(ingrid);
if (ingrid->sibling)
zeroghostrec(ingrid->sibling);
if (ingrid->child)
zeroghostrec(ingrid->child);
}
/**************************************************************/
/* Routines for copying grids */
void copyarray(double *out,double *in, int length)
{
register int i;
for (i=0;i<length;i++)
out[i]=in[i];
/*
double *pout=out, *pin=in;
for(; pout<length; pout++)
*pout=(*(pin++));
*/
}
/*Copies an array onto another, where the output
array is bigger than the input array. We therefore
have extra padding in all directions for the
output array
out: the output array
in: the input array
nxout: the dimensions of the output array
nxin: the dimensions of the input array
padx: padding in x-direction
mode: +1 if outgrid is bigger, -1 if it is smaller
*/
void copyarrayexp(double *out,double *in,
int nxout, int nyout, int nzout,
int nxin, int nyin, int nzin,
int padx, int pady, int padz,
int mode)
{
register int i,j,k,nxyin,nxyout,xrange,yrange,zrange;
register int expx,expy,expz;
nxyout=nxout*nyout;
nxyin=nxin*nyin;
if (padx%2==0)
expx=padx;
else
expx=padx+1;
if (pady%2==0)
expy=pady;
else
expy=pady+1;
if (padz%2==0)
expz=padz;
else
expz=padz+1;
xrange=nxin+expx;
yrange=nyin+expy;
zrange=nzin+expz;
if (mode > 0)
for (i=expx;i<xrange;i++)
for (j=expy;j<yrange;j++)
for (k=expz;k<zrange;k++)
{
out[i*nxyout+j*nxout+k]
=in[(i-expx)*nxyin+(j-expy)*nxin+(k-expz)];
}
else
for (i=expx;i<xrange;i++)
for (j=expy;j<yrange;j++)
for (k=expz;k<zrange;k++)
{
out[(i-expx)*nxyin+(j-expy)*nxin+(k-expz)]
=in[i*nxyout+j*nxout+k];
}
}
/*Copies an array onto another, where the input
array is bigger than the output array. We therefore
have extra padding in all directions for the
output array. Note that we follow the convention that
the difference in region size must be an even number.
out: the output array
in: the input array
nxout: the dimensions of the output array
nxin: the dimensions of the input array
padx: padding in x-direction
*/
void copyarrayred(double *out,double *in,
int nxout, int nyout, int nzout,
int nxin, int nyin, int nzin,
int padx, int pady, int padz)
{
register int i,j,k,nxyin,nxyout,xrange,yrange,zrange;
register int expx,expy,expz;
nxyout=nxout*nyout;
nxyin=nxin*nyin;
if (padx%2==0)
expx=padx;
else
expx=padx+1;
if (pady%2==0)
expy=pady;
else
expy=pady+1;
if (padz%2==0)
expz=padz;
else
expz=padz+1;
xrange=nxout+expx;
yrange=nyout+expy;
zrange=nzout+expz;
for (i=expx;i<xrange;i++)
for (j=expy;j<yrange;j++)
for (k=expz;k<zrange;k++)
out[i*nxyout+j*nxout+k]
=in[i*nxyin+j*nxin+k];
}
/*Copies a COMPLETE gridstructure onto another
out: answergrid
in: input grid */
/* IPD: actually copies only the data */
/* Must be updated! */
void copygrid(struct Grid *out, struct Grid *in)
{
int i;
static int flag=1;
if ( (i=(in->dim.x*in->dim.y*in->dim.z) ) !=
(out->dim.x*out->dim.y*out->dim.z) ){
printf("Sorry, trying to copy different size grids\n");
printf("Program will exit.\n\n");
exit(1);
}
/* IPD: add the physical dimensions out.scale=in.scale */
copyarray(out->dat,in->dat,i);
if(flag){
printf("gridtype: old in copygrid()\n");
printf("WARNING: copygrid does not check if scales are the same!!!\n");
flag=0;
}
if (in->sibling)
copygrid(out->sibling,in->sibling);
if (in->child)
copygrid(out->child,in->child);
}
/* loop over cousins */
void copygrid_level(struct Grid *out, struct Grid *in)
{
struct Grid *a, *b;
int i;
a=out;
b=in;
while(a && b){
for(i=0; i<a->nxyz; i++)
a->dat[i] = b->dat[i];
a=a->cousin;
b=b->cousin;
}
}
/*Copies a complete gridstructure onto another
out: answergrid
in: input grid */
/* IPD: actually copies only the data */
/* Maybe leave this one alone... */
void copygridnew(struct Grid *out, struct Grid *in)
{
int i,limit;
static int flag=1;
if(flag){
printf("gridtype: new in copygridnew()\n");
flag=0; /* tell us just once */
}
limit=out->nxyzwholegrid;
for (i=0;i<limit;i++)
*(out->dat+i)=(*(in->dat+i));
}
/* Reads the coefficients of a Grid from a file*/
void readfromfile(FILE *fpi,struct Grid *ingrid)
{
int i;
int limit=ingrid->dim.x*ingrid->dim.y*ingrid->dim.z;
for (i=0;i<limit;i++)
fscanf(fpi,"%lf",&ingrid->dat[i]);
if (ingrid->sibling)
readfromfile(fpi,ingrid->sibling);
if (ingrid->child)
readfromfile(fpi,ingrid->child);
}
void readfromfilebin(char * fname, double *data,int ntot)
{
int i;
int fdi; /* file descriptor of the input file */
double *datap; /* pointer to the current element */
time_t timenow=time(0);
printf("Start reading - date and time: %s", ctime(&timenow));
printf("Reading data from '%s'...", fname);
fflush(stdout);
if( (fdi=open(fname, O_RDONLY,0))==-1){
fprintf(stderr,"can't open '%s' to read\n",fname);
exit(1);
}
datap=data;
for(i=0;i<ntot;i++)
if( read(fdi, datap ,sizeof(double)) > 0 ){
datap++;
/* printf("num bytes read: %d\n",n); */
}
close(fdi);
printf("Done\n");fflush(stdout);
timenow=time(0);
printf("End reading - date and time: %s\n", ctime(&timenow));
}
/* Read data offset by 'shift' from the origin of the file */
void readfromfilebin_shift(char * fname, double *data,int ntot, long shift)
{
int i;
int fdi; /* file descriptor of the input file */
double *datap; /* pointer to the current element */
time_t timenow=time(0);
printf("Start reading - date and time: %s", ctime(&timenow));
printf("Reading data from '%s'...", fname);
fflush(stdout);
if( (fdi=open(fname, O_RDONLY,0))==-1){
fprintf(stderr,"can't open '%s' to read\n",fname);
exit(1);
}
/* move to the origin of the data */
if( lseek(fdi, shift*sizeof(double), 0) < 0){
printf("Error shifting in lseek(), Exiting\n");
exit(1);
}
datap=data;
for(i=0;i<ntot;i++)
if( read(fdi, datap ,sizeof(double)) > 0 ){
datap++;
/* printf("num bytes read: %d\n",n); */
}
close(fdi);
printf("Done\n");fflush(stdout);
timenow=time(0);
printf("End reading - date and time: %s\n", ctime(&timenow));
}
/* Writes the coefficients of a Grid to a file*/
void writetofile(FILE *fpi,struct Grid *ingrid)
{
int i;
int limit=ingrid->dim.x*ingrid->dim.y*ingrid->dim.z;
/* printf(" Printing %d * %d * %d = %d numbers from %d\n", */
/* ingrid->dim.x,ingrid->dim.y, ingrid->dim.z, limit, ingrid->dat);*/
for (i=0;i<limit;i++)
fprintf(fpi,"%20.15lf\n",ingrid->dat[i]);
if (ingrid->sibling)
writetofile(fpi,ingrid->sibling);
if (ingrid->child)
writetofile(fpi,ingrid->child);
}
/* Writetofile in binary format*/
/* Probably should add an extra argument to distinguish between
creating and appending files, in which case can be used recursively too
*/
void writetofilebin(char *fname, double *data, int totdat)
{
#ifndef bgrid
printf("writetofilebin() is only tested for bgrids!!!");
exit(1);
#endif
#define PERMS 0666 /* RW for owner group others */
int fdo; /* output file descriptor */
int b2write=totdat*sizeof(double);
int bwritten;
time_t timenow=time(0);
printf("Start writing - date and time: %s\n", ctime(&timenow));
if( (fdo=creat(fname, PERMS))==-1 ){
printf("Error opening elec_wfs to write\n");
fprintf(stderr,"Can't open %s to write\n",fname);
exit(1);
}
if ( (bwritten=
write(fdo,(char *)data,b2write))!=b2write){
printf("Error writing: %d bytes written\n",bwritten);
}
close(fdo);
timenow=time(0);
printf("End writing - date and time: %s\n", ctime(&timenow));
}
/*
Reads in gridspec entries from a file, appending a terminating "-1"
fp: input stream
spec[]: array in which to store results
----
May be it's worth to change topdims from global to local (grid data)
*/
void readgridspec(FILE *fp,struct Gridspec spec[])
{
int i=0;
/*
fscanf(fp,"%lf %lf %lf\n",&topdims.x,&topdims.y,&topdims.z);
printf("top level scale = {%lf, %lf, %lf} bohr\n",
topdims.x,topdims.y,topdims.z);
*/
/* We'll read the top-level scale from the DFT++ lattice vectors.
fscanf(fp,"%lf %lf %lf\n",
&spec[0].scale.x,&spec[0].scale.y,&spec[0].scale.z);
printf("top level scale = {%lf, %lf, %lf} bohr\n",
spec[0].scale.x, spec[0].scale.y, spec[0].scale.z);
*/
while( fscanf(fp,"%d %d %d %d %d %d %d\n",
&spec[i].level,
&spec[i].org.x,&spec[i].org.y,&spec[i].org.z,
&spec[i].dim.x,&spec[i].dim.y,&spec[i].dim.z) != EOF ){
i++;
if (i==NgridMx-1){
fprintf(stderr,"Grid description more complex than NgridMx.\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
}
spec[i].level=-1;
return;
}
void expandgridspec2x(struct Gridspec *spec, struct Gridspec *out)
{
int i=0;
/* set the scale on 0th level */
out[0].scale.x=spec[0].scale.x/2.;
out[0].scale.y=spec[0].scale.y/2.;
out[0].scale.z=spec[0].scale.z/2.;
while(spec[i].level != -1){
out[i].level=spec[i].level;
out[i].org.x=spec[i].org.x*2;
out[i].org.y=spec[i].org.y*2;
out[i].org.z=spec[i].org.z*2;
out[i].dim.x=spec[i].dim.x*2;
out[i].dim.y=spec[i].dim.y*2;
out[i].dim.z=spec[i].dim.z*2;
i++;
}
out[i].level=-1;
return;
}
/* this one removes the lowes level, since we can't get better resolution
from what we have initially
this is smaller grid, hense the _s in the name :) */
void expandgridspec2x_s(struct Gridspec *out,struct Gridspec *spec)
{
int i=0, ii=0;
/* set the scale on 0th level */
out[0].scale.x=spec[0].scale.x/2.;
out[0].scale.y=spec[0].scale.y/2.;
out[0].scale.z=spec[0].scale.z/2.;
while(spec[i].level != -1){
/* check if there is another level of resolution */
if(spec[i+1].level > spec[i].level){
out[ii].level=spec[i].level;
out[ii].org.x=spec[i].org.x*2;
out[ii].org.y=spec[i].org.y*2;
out[ii].org.z=spec[i].org.z*2;
out[ii].dim.x=spec[i].dim.x*2;
out[ii].dim.y=spec[i].dim.y*2;
out[ii].dim.z=spec[i].dim.z*2;
i++;
ii++;
} else
i++; /* don't create bottom level for out */
}
out[ii].level=-1;
return;
}
/*
Reads in ionspec entries from a file
fp: input stream
ionloc[]: array in which to store results
*/
void readionloc(FILE *fp,struct Ionspec spec[])
{
int i=0;
while( fscanf(fp,"%lf %lf %lf %lf\n",
&spec[i].Z,
&spec[i].ionloc.x,
&spec[i].ionloc.y,
&spec[i].ionloc.z) != EOF ){
i++;
if (i==IonMx-1){
fprintf(stderr,"Grid description more complex than IonMx.\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
}
spec[i].Z=-1;
return;
}
/*
Makes and allocates a struct grid hierarchy according to a gridspec
(RECURSIVE FUNCTION)
spec[]: an array of gridspec entries giving level, origin and size
info
parent: pointer parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
struct Grid *mkgrid_basic(struct Gridspec *spec,struct Grid *parent)
{
struct Grid *self;
int i;
static int flag=1;
if(flag){
printf("gridtype: old in mkgrid()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* ipd: it is important to have the top level know how big is the whole
grid, so that we can copy it in contiguous memory if we need
The siblings on the top lavel (usually we have only one top level)
will get wrong number. However we won't use those */
self->nxyzwholegrid=0; i=0;
if (parent == NULL){ /* we are the rop level */
/* Now set the boundary conditions of the top level to periodic
and those of the lower levels to nonperiodic */
self->ifperiodic=do_periodic;
/* compute the total number of data */
while ( spec[i].level >= 0 ) {
self->nxyzwholegrid+=(spec[i].dim.x*spec[i].dim.y*spec[i].dim.z);
i++;
}
} else /* we are not the top level */
self->ifperiodic=non_periodic;
self->parent=parent;
/* Fill in data about own Grid (specified by spec array) */
self->level=spec[0].level;
/* We make toplevel scale equal to global variable topdims,
others scale as 1/(2^level) */
if (self->level==0){
/* This should NOT!! be global!!! */
/*
self->scale.x=topdims.x;
self->scale.y=topdims.y;
self->scale.z=topdims.z;
*/
self->scale.x=spec[0].scale.x;
self->scale.y=spec[0].scale.y;
self->scale.z=spec[0].scale.z;
/* printf("level: %d scale=(%lf %lf %lf)bohr\n", self->level, */
/* self->scale.x, self->scale.y, self->scale.z); */
}
else{
self->scale.x=self->parent->scale.x/2;
self->scale.y=self->parent->scale.y/2;
self->scale.z=self->parent->scale.z/2;
}
self->org.x=spec[0].org.x;
self->org.y=spec[0].org.y;
self->org.z=spec[0].org.z;
self->dim.x=spec[0].dim.x;
self->dim.y=spec[0].dim.y;
self->dim.z=spec[0].dim.z;
self->nxyz=self->dim.x*self->dim.y*self->dim.z;
if ( (self->dat = (double *)
malloc(self->dim.x*self->dim.y*self->dim.z*sizeof(double)))
== NULL ) {
printf("malloc failed in mkgrid (2)\n");
printf("level: %d dimensions are: %d %d %d\n",
self->level, self->dim.x,self->dim.y,self->dim.z);
printf("Exiting.\n");
exit(1);
}
/* Now go to next element of spec */
/* Check for level skipping */
if (spec[1].level>spec[0].level+1){
fprintf(stderr,"Level %d can't give birth to level %d ",
spec[0].level,spec[1].level);
fprintf(stderr,"without level %d in between!\n",spec[0].level+1);
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (spec[1].level==spec[0].level+1)
self->child=mkgrid_basic(spec+1,self);
else
self->child=NULL;
/* Now find sibling, if any! */
for (i=1; spec[i].level>spec[0].level; i++) ;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (spec[i].level==spec[0].level)
self->sibling=mkgrid_basic(spec+i,parent);
else
self->sibling=NULL;
/* ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/*
Makes and allocates a struct grid hierarchy according to a gridspec
(RECURSIVE FUNCTION)
spec[]: an array of gridspec entries giving level, origin and size
info
parent: pointer parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
struct Grid *mkgridnew(struct Gridspec *spec,struct Grid *parent)
{
struct Grid *self;
int i;
static double *mem;
static int flag=1;
if(flag){
printf("gridtype: new in mkgridnew()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* it is important to have the top level know how big is the whole
grid, so that we can copy it in contimuous memory if we need */
self->nxyzwholegrid=0; i=0;
if (parent == NULL){ /* we are the top level*/
/* set periodic boundary conditions*/
self->ifperiodic=do_periodic;
/* compute the total number of data */
while ( spec[i].level >= 0 ) {
self->nxyzwholegrid+=(spec[i].dim.x*spec[i].dim.y*spec[i].dim.z);
i++;
}
} else /* we are not the top level */
self->ifperiodic=non_periodic;
self->parent=parent;
/* Fill in data about own grid (specified by spec array) */
self->level=spec[0].level;
/*Toplevel scale = global variable topdims, others scale as 1/(2^level) */
if (self->level==0) {
/* IPD: NO globals please!!! */
/*
self->scale.x=topdims.x;
self->scale.y=topdims.y;
self->scale.z=topdims.z;
*/
self->scale.x=spec[0].scale.x;
self->scale.y=spec[0].scale.y;
self->scale.z=spec[0].scale.z;
/* printf("level: %d scale=(%lf %lf %lf)bohr\n", self->level, */
/* self->scale.x, self->scale.y, self->scale.z); */
}
else {
self->scale.x=self->parent->scale.x/2;
self->scale.y=self->parent->scale.y/2;
self->scale.z=self->parent->scale.z/2;
}
self->org.x=spec[0].org.x;
self->org.y=spec[0].org.y;
self->org.z=spec[0].org.z;
self->dim.x=spec[0].dim.x;
self->dim.y=spec[0].dim.y;
self->dim.z=spec[0].dim.z;
self->nxyz=self->dim.x*self->dim.y*self->dim.z;
if (parent == NULL) {
if ( (self->dat=
(double *) malloc(self->nxyzwholegrid*sizeof(double)))
== NULL ){
fprintf(stderr,"malloc failed in mkgridnew (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
mem=self->dat;
}
else
self->dat=mem;
mem+=self->nxyz;
/* Now go to next element of spec */
/* Check for level skipping */
if (spec[1].level>spec[0].level+1) {
fprintf(stderr,"Level %d can't give birth to level %d without level %d in between!\n",
spec[0].level,spec[1].level,spec[0].level+1);
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (spec[1].level==spec[0].level+1)
/* self->child=mkgridnew(spec+1,self); */
self->child=mkgridnew(&spec[1],self);
else
self->child=NULL;
/* Now find sibling, if any! */
for (i=1; spec[i].level>spec[0].level; i++);
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (spec[i].level==spec[0].level)
/* self->sibling=mkgridnew(spec+i,parent); */
self->sibling=mkgridnew(&spec[i],parent);
else
self->sibling=NULL;
/* ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/*
Makes and allocates a struct grid hierarchy according to a gridspec
(RECURSIVE FUNCTION)
does NOT allocate memory for the data, sets the pointer to preallocated
memory.
spec[]: an array of gridspec entries giving level, origin and size
info
parent: pointer parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
ppdata: pointer to pointer to the data (we need to change the pointer)
*/
struct Grid *mkbgrid(struct Gridspec *spec,struct Grid *parent,
double **ppdata)
{
struct Grid *self;
int i;
static int flag=1;
if(flag){
printf("gridtype: bgrid in mkbgrid()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* it is important to have the top level know how big is the whole
grid, so that we can copy it in contimuous memory if we need */
self->nxyzwholegrid=0; i=0;
if (parent == NULL){ /* we are the toplevel*/
/* set periodic boundary conditions */
self->ifperiodic=do_periodic;
/* now compute the total number of data */
while ( spec[i].level >= 0 ) {
self->nxyzwholegrid+=(spec[i].dim.x*spec[i].dim.y*spec[i].dim.z);
i++;
}
} else
self->ifperiodic=non_periodic;
self->parent=parent;
/* Fill in data about own Grid (specified by spec array) */
self->level=spec[0].level;
/* We make toplevel scale equal to global variable topdims,
others scale as 1/(2^level) */
if (self->level==0){
/* IPD: get rid of the globals */
/*
self->scale.x=topdims.x;
self->scale.y=topdims.y;
self->scale.z=topdims.z;
*/
self->scale.x=spec[0].scale.x;
self->scale.y=spec[0].scale.y;
self->scale.z=spec[0].scale.z;
/* printf("level: %d scale=(%lf %lf %lf)bohr\n", self->level, */
/* self->scale.x, self->scale.y, self->scale.z); */
}
else{
self->scale.x=self->parent->scale.x/2;
self->scale.y=self->parent->scale.y/2;
self->scale.z=self->parent->scale.z/2;
}
self->org.x=spec[0].org.x;
self->org.y=spec[0].org.y;
self->org.z=spec[0].org.z;
self->dim.x=spec[0].dim.x;
self->dim.y=spec[0].dim.y;
self->dim.z=spec[0].dim.z;
self->nxyz=self->dim.x*self->dim.y*self->dim.z;
/*
if ( (self->dat=
(double *)
malloc(self->dim.x*self->dim.y*self->dim.z*sizeof(double)))
== NULL ) {
fprintf(stderr,"malloc failed in mkgrid (2)\n");
printf("dimensions are: %d %d %d\n",
self->dim.x,self->dim.y,self->dim.z);
fprintf(stderr,"Exiting.\n");
exit(1);
}
*/
/* set the pointer to the place preallocated by the bundle*/
self->dat = *ppdata;
/* increment the pointer to know where to start next time */
*ppdata += (self->dim.x*self->dim.y*self->dim.z);
/* Now go to next element of spec */
/* Check for level skipping */
if (spec[1].level>spec[0].level+1){
fprintf(stderr,"Level %d can't give birth to level %d ",
spec[0].level,spec[1].level);
fprintf(stderr,"without level %d in between!\n",spec[0].level+1);
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (spec[1].level==spec[0].level+1)
self->child=mkbgrid(spec+1,self,ppdata);
else
self->child=NULL;
/* Now find sibling, if any! */
for (i=1; spec[i].level>spec[0].level; i++) ;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (spec[i].level==spec[0].level)
self->sibling=mkbgrid(spec+i,parent,ppdata);
else
self->sibling=NULL;
/* ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/*
Makes and allocates a struct grid hierarchy according to a grid
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
struct Grid *mkgridfromgrid(struct Grid *ingrid, struct Grid *parent)
{
struct Grid *self;
static int flag=1;
if(flag){
printf("gridtype: old in mkgridfromgrid()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgridfromgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
self->parent=parent;
/* Fill in data about own grid (specified by ingrid) */
self->level=ingrid->level;
self->ifperiodic=ingrid->ifperiodic;
self->nxyz=ingrid->nxyz;
self->nxyzwholegrid=ingrid->nxyzwholegrid;
self->scale.x=ingrid->scale.x;
self->scale.y=ingrid->scale.y;
self->scale.z=ingrid->scale.z;
self->org.x=ingrid->org.x;
self->org.y=ingrid->org.y;
self->org.z=ingrid->org.z;
self->dim.x=ingrid->dim.x;
self->dim.y=ingrid->dim.y;
self->dim.z=ingrid->dim.z;
if ( (self->dat=
(double *)
malloc(self->dim.x*self->dim.y*self->dim.z*sizeof(double)))
== NULL ){
fprintf(stderr,"malloc failed in mkgridfromgrid (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (ingrid->child)
self->child=mkgridfromgrid(ingrid->child,self);
else
self->child=NULL;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (ingrid->sibling)
self->sibling=mkgridfromgrid(ingrid->sibling,parent);
else
self->sibling=NULL;
/*ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/*
Makes and allocates a struct grid hierarchy according to a grid
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
struct Grid *mkgridfromgridnew(struct Grid *ingrid, struct Grid *parent)
{
struct Grid *self;
static double *mem;
static int flag=1;
if(flag){
printf("gridtype: new in mkgridfromgridnew()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL) {
fprintf(stderr,"malloc failed in mkgridfromgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
self->parent=parent;
/* Fill in data about own grid (specified by spec array) */
self->level=ingrid->level;
self->ifperiodic=ingrid->ifperiodic;
self->nxyz=ingrid->nxyz;
self->nxyzwholegrid=ingrid->nxyzwholegrid;
self->scale.x=ingrid->scale.x;
self->scale.y=ingrid->scale.y;
self->scale.z=ingrid->scale.z;
self->org.x=ingrid->org.x;
self->org.y=ingrid->org.y;
self->org.z=ingrid->org.z;
self->dim.x=ingrid->dim.x;
self->dim.y=ingrid->dim.y;
self->dim.z=ingrid->dim.z;
/* IPD: if the toplevel has siblings it will allocate new memory
for each of them and the memory cost will be very high probably
we can add extra static flag in the if() statement */
if (self->level == 0) {
if ( (self->dat=
(double *)
malloc(self->nxyzwholegrid*sizeof(double)))
== NULL ) {
fprintf(stderr,"malloc failed in mkgridfromgridnew (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
mem=self->dat;
}
else
self->dat=mem;
mem+=self->nxyz;
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (ingrid->child)
self->child=mkgridfromgridnew(ingrid->child,self);
else
self->child=NULL;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (ingrid->sibling)
self->sibling=mkgridfromgridnew(ingrid->sibling,parent);
else
self->sibling=NULL;
/*ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/*
Makes and allocates a struct grid hierarchy according to a grid from bundle
(RECURSIVE FUNCTION)
Does not allocate the data, just sets the pointers to it
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
ppdata: pointer to pointer to the preallocated data
return value: pointer to allocated struct grid
*/
struct Grid *mkbgridfromgrid(struct Grid *ingrid, struct Grid *parent,
double **ppdata)
{
struct Grid *self;
static int flag=1;
if(flag){
printf("gridtype: bgrid in mkbgridfromgrid()\n");
flag=0; /* tell us just once */
}
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgridfromgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
self->parent=parent;
/* Fill in data about own grid (specified by ingrid) */
self->level=ingrid->level;
self->ifperiodic=ingrid->ifperiodic;
self->nxyzwholegrid=ingrid->nxyzwholegrid;
self->nxyz=ingrid->nxyz;
self->scale.x=ingrid->scale.x;
self->scale.y=ingrid->scale.y;
self->scale.z=ingrid->scale.z;
self->org.x=ingrid->org.x;
self->org.y=ingrid->org.y;
self->org.z=ingrid->org.z;
self->dim.x=ingrid->dim.x;
self->dim.y=ingrid->dim.y;
self->dim.z=ingrid->dim.z;
/*
if ( (self->dat=
(double *)
malloc(self->dim.x*self->dim.y*self->dim.z*sizeof(double)))
== NULL ){
fprintf(stderr,"malloc failed in mkgrid (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
*/
/* set the pointer to the place preallocated by the bundle*/
self->dat = *ppdata;
/* increment the pointer to know where to start next time */
*ppdata += (self->dim.x*self->dim.y*self->dim.z);
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (ingrid->child)
self->child=mkbgridfromgrid(ingrid->child,self,ppdata);
else
self->child=NULL;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (ingrid->sibling)
self->sibling=mkbgridfromgrid(ingrid->sibling,parent,ppdata);
else
self->sibling=NULL;
/* ipd: now make cousin point to the sibling */
self->cousin=self->sibling;
return(self);
}
/* this should find the next grid in the grid tree of certain level
recursive. It must traverse the treee in the same way as the function
that falls it
Recursive function
next: pointer to the pointer to the next grid (output)
we must change where it points and since the routine is recursive
double pointer is neessary
current: the one we are looking at (*next points to the next of current)
current is never changed
loop: this one we use to navigate over the grid tree
getnext: flag that tells us when to return the one we find
it should be set to zero when we call the function */
void getnext_of_level(struct Grid **next, struct Grid *current,
struct Grid *loop,
int *getnext)
{
if(loop==NULL) return;
if(*getnext && loop->level==current->level){/* we found it */
*next=loop;
return;
}
else{ /* no luck so far */
getnext_of_level(next,current, loop->child, getnext);
getnext_of_level(next,current, loop->sibling, getnext);
}
/* when we arrive to ourselves, next found is the one we need */
if(loop==current) *getnext=1;
}
/* goes recursively over the grid structure and sets the cousin pointers */
void setcousins(struct Grid *self, struct Grid **next)
{
/* struct Grid **next; */
struct Grid *loop;
int itisnext;
if(self==NULL) return;
*next=NULL;/* no cousin to start with */
if(self->sibling)/* i have a sibling, let the cousin point to it */
self->cousin=self->sibling;
else{ /* find the next grid in the tree with my level */
/* first get to the top of the tree */
loop=self;
while(loop->parent)
loop=loop->parent;
itisnext=0;
/* now find who is next */
getnext_of_level(next, self, loop, &itisnext);
self->cousin=*next;
}
/* now go to the shildren and the siblings - we must traverse the */
/* tree the same way as getnext */
setcousins(self->child, next);
setcousins(self->sibling, next);
}
/* ipd: now we must set the cousins too, but we can't do it when creating
the grid recursively because they do not exist yet
The solution is to have a wraping routine, that will call this one,
and set the cousins. PRobably a good thing is to rename this one
and use mkgrid() as a name for the wrapper */
struct Grid *mkgrid(struct Gridspec *spec, struct Grid *parent)
{
struct Grid *self;
struct Grid *next;/* this is a hack because of the double pointer */
/* no time now to think what and when is getting allocated/deallocated */
self=mkgrid_basic(spec, parent);
setcousins(self, &next);
return (self);
}
/*
Makes and allocates an expanded struct grid hierarchy according to
an input grid and specified expansion parameters
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
padx: extra padding on both sides in x-direction of outgrid
return value: pointer to allocated struct grid
IPD: We seem not to use this function anymore, but just in case we need
it we have to set ifperiodic=non_periodic, since this grid is expanded
therefore it has pieces from the neighbouring cells around
*/
struct Grid *mkexpgridfromgrid(struct Grid *ingrid, struct Grid *parent,
int padx, int pady, int padz)
{
struct Grid *self;
int expx, expy, expz;
static int flag=1;
/* NOW WE WILL CHECK IF THE FUNCTION IS USED OR NOT
REMOVE THE TWO LINES BELOW IF YOU NEED IT */
printf("TEST if mkexpgridfromgrid() is used at all...\nEXIT!!!\n");
exit(1);
if(flag){
printf("gridtype: old in mkexpgridfromgrid()\n");
flag=0; /* tell us just once */
}
if (padx%2==0)
expx=padx;
else
expx=padx+1;
if (pady%2==0)
expy=pady;
else
expy=pady+1;
if (padz%2==0)
expz=padz;
else
expz=padz+1;
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkexpgridfromgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
self->parent=parent;
/* Fill in data about own grid (specified by spec array) */
self->level=ingrid->level;
self->ifperiodic=non_periodic; /*see the comments to the function*/
self->scale.x=ingrid->scale.x;
self->scale.y=ingrid->scale.y;
self->scale.z=ingrid->scale.z;
if (self->level==0) {
self->org.x=ingrid->org.x;
self->org.y=ingrid->org.y;
self->org.z=ingrid->org.z;
}
else if (self->level==1) {
self->org.x=ingrid->org.x-expx/2;
self->org.y=ingrid->org.y-expy/2;
self->org.z=ingrid->org.z-expz/2;
}
else /*if (self->level>1) */ {
self->org.x=ingrid->org.x+expx/2;
self->org.y=ingrid->org.y+expy/2;
self->org.z=ingrid->org.z+expz/2;
}
if (self->level==0) {
self->dim.x=ingrid->dim.x;
self->dim.y=ingrid->dim.y;
self->dim.z=ingrid->dim.z;
}
else {
self->dim.x=ingrid->dim.x+2*expx;
self->dim.y=ingrid->dim.y+2*expy;
self->dim.z=ingrid->dim.z+2*expz;
}
if ( (self->dat=
(double *)
malloc(self->dim.x*self->dim.y*self->dim.z*sizeof(double)))
== NULL ) {
fprintf(stderr,"malloc failed in mkexpgridfromgrid (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* If any children, next one is it (other children are "siblings" of
each other! If no children, make sure pointer is NULL */
if (ingrid->child)
self->child=mkexpgridfromgrid(ingrid->child,self,padx,pady,padz);
else
self->child=NULL;
/* Check if we found one, and make it if we did; otherwise, make
sure pointer is NULL */
if (ingrid->sibling)
self->sibling=mkexpgridfromgrid(ingrid->sibling,
parent,padx,pady,padz);
else
self->sibling=NULL;
return(self);
}
/* creates grid and allocates a struct grid hierarchy according to
input, but contains only the level input->level level
Loop: avoid filling up the stack with recursion
this would call */
struct Grid * mkgridfromgrid_level(struct Grid* ingrid)
{
struct Grid *self;
static int flag=1;
if(flag){
printf("gridtype: old in mkgridfromgrid_level()\n");
flag=0; /* tell us just once */
}
if(ingrid==NULL) return NULL;
/* Allocate space for own structure */
if ( (self=(struct Grid *) malloc(sizeof(struct Grid))) == NULL){
fprintf(stderr,"malloc failed in mkgridfromgrid (1)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
self->parent=NULL;
self->child=NULL;
/* Fill in data about own grid (specified by ingrid) */
self->level=ingrid->level;
self->ifperiodic=ingrid->ifperiodic;
self->nxyz=ingrid->nxyz;
self->nxyzwholegrid=ingrid->nxyzwholegrid;
self->scale=ingrid->scale;
self->org=ingrid->org;
self->dim.x=ingrid->dim.x;
self->dim.y=ingrid->dim.y;
self->dim.z=ingrid->dim.z;
if ( (self->dat= (double *) malloc(self->nxyz*sizeof(double))) == NULL ){
fprintf(stderr,"malloc failed in mkgridfromgrid (2)\n");
fprintf(stderr,"Exiting.\n");
exit(1);
}
/* Check if there are siblings */
if (ingrid->sibling){
self->sibling=mkgridfromgrid_level(ingrid->sibling);
self->cousin=self->sibling;
} else if (ingrid->cousin){
self->sibling=NULL;
self->cousin=mkgridfromgrid_level(ingrid->cousin);
} else
self->sibling=self->cousin=NULL;
return(self);
}
/* this kils one level grid (the navigation is along the cousins) */
void killgrid_level(struct Grid *ingrid){
static int flag=1;
if(flag){
/* printf("gridtype: level in killgrid_level()\n"); */
flag=0; /* tell us just once */
}
if(ingrid==NULL) return;
/* Kill all cousins */
if (ingrid->cousin)
killgrid_level(ingrid->cousin);
/* Free up data space */
if (ingrid->dat)
free(ingrid->dat);
/* Free up space for own structure */
free(ingrid);
}
/*
Deallocates a struct grid hierarchy according to a grid
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
void killgrid(struct Grid *ingrid)
{
static int flag=1;
if(flag){
printf("gridtype: old in killgrid()\n");
flag=0; /* tell us just once */
}
/* Kill all children */
if (ingrid->child)
killgrid(ingrid->child);
/* Kill all siblings */
if (ingrid->sibling)
killgrid(ingrid->sibling);
/* Free up data space */
if (ingrid->dat)
free(ingrid->dat);
/* Free up space for own structure */
free(ingrid);
}
/*
Makes and allocates a struct grid hierarchy according to a grid
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
void killgridnew(struct Grid *ingrid)
{
static int flag=1;
if(flag){
printf("gridtype: new in killgridnew\n");
flag=0; /* tell us just once */
}
/* Kill all children */
if (ingrid->child)
killgridnew(ingrid->child);
/* Kill all siblings */
if (ingrid->sibling)
killgridnew(ingrid->sibling);
/* Free up date space */
if ( (ingrid->parent) == NULL)
free(ingrid->dat);
/* Free up space for own structure */
free(ingrid);
}
/*
Deallocates a struct grid hierarchy according to a grid
(RECURSIVE FUNCTION)
ingrid[]: the grid according to which structure the
new grid will be contructed
parent: pointer to parent (calling) grid
For ROOT call is just NULL
return value: pointer to allocated struct grid
*/
void killbgrid(struct Grid *ingrid)
{
static int flag=1;
if(flag){
printf("gridtype: bgrid in killbgrid()\n");
flag=0; /* tell us just once */
}
/* Kill all children */
if (ingrid->child)
killbgrid(ingrid->child);
/* Kill all siblings */
if (ingrid->sibling)
killbgrid(ingrid->sibling);
/* now we do not free the data space here, but in the bundle */
/*
if (ingrid->dat)
free(ingrid->dat);
*/
/* Free up space for own structure */
free(ingrid);
}
/*
Pretty print of a 3d array (OUT)
fp: data stream
out: array to be printed
nx, ny, nz: dimensions of array
*/
void print3d(FILE *fp,double *out,int nx,int ny,int nz)
{
int i,j,k;
for (i=0; i<nx; i++) {
fprintf(fp,"--- %3d\n",i);
fprintf(fp," ");
for (k=0; k<nz; k++)
fprintf(fp," %5d ",k);
fprintf(fp,"\n");
for (j=0; j<ny; j++){
fprintf(fp,"%3d ",j);
for (k=0; k<nz; k++)
fprintf(fp,"%8.1le ",*(out+(i*ny+j)*nz+k));
fprintf(fp,"\n");
}
fprintf(fp,"\n");
}
}
/*
Prints out a real-space vector as a function of distance from an input point
(RECURSIVE FUNCTION)
fp: file-pointer for the output
self: pointer to Grid to be filled
scl: physical scale (along x, y and z) of the Grid to be printed
porg: physical origin of parent (calling Grid)
For ROOT call, these are just the coordinates of the first
element of top Grid.
*/
void
radialprintgrid(FILE *fp,struct Grid *self, struct Dvec porg)
{
/* Origin of self (note that self->org is in the _parents_ coordinates */
struct Dvec org;
int i,j,k,dis;
struct Dvec r;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Origin of self (note that self->org is in the _parents_ coordinates */
org.x = porg.x + self->org.x *2*self->scale.x;
org.y = porg.y + self->org.y *2*self->scale.y;
org.z = porg.z + self->org.z *2*self->scale.z;
/* printf("evalgrid: origin is: %18.12lf %18.12lf %5d %18.12lf\n", */
/* org.x, porg.x, self->org.x, scl.x); */
/* Fill in data */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++){
r.x=org.x+i*self->scale.x;
r.y=org.y+j*self->scale.y;
r.z=org.z+k*self->scale.z;
dis=(i*self->dim.y+j)*self->dim.z+k;
fprintf(fp,"%d %lf %e\n",dis, sqrt(r.x*r.x + r.y*r.y + r.z*r.z),
self->dat[dis]);
}
return;/* only the top level */
/* Call child and sibling, return immediately if none */
if (self->child!=NULL) {
/* printf("Evaluating next child...\n"); */
radialprintgrid(fp, self->child, org);
}
if (self->sibling!=NULL){
/* printf("Evaluating next sibling...\n"); */
radialprintgrid(fp, self->sibling, org);
}
return;
}
/*
Prints out hierarchical structure and data of a struct grid
(RECURSIVE FUNCTION)
fp: output stream
self: pointer to grid to be analyzed
*/
void printgrid(FILE *fp,struct Grid *self)
{
/* Module below nicely formats level tree */
int level;
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Print array locator */
fprintf(fp,"P: ");
for (level=0; level< self->level; level++)
fprintf(fp," ");
fprintf(fp,"[%d]\n",self->level);
/* Print dimensions of array */
fprintf(fp,"(%dx%dx%d)\n",self->dim.x,self->dim.y,self->dim.z);
/* Output the 3d array */
print3d(fp,self->dat,self->dim.x,self->dim.y,self->dim.z);
/* Do child and sibling (return immediately if none) */
printgrid(fp, self->child);
printgrid(fp, self->sibling);
return;
}
/*
Write hierarchical grid to a named file
filename: name of file
self: pointer to grid to be printed
*/
void writegrid(char *filename,struct Grid *self)
{
FILE *fp;
if ( (fp=fopen(filename,"w")) == NULL ) {
fprintf(stderr,"Can't open file \"%s\" for output.\n",filename);
fprintf(stderr,"Exiting.\n");
exit(1);
}
printgrid(fp,self);
fclose(fp);
}
/*
Prints out hierarchical structure of a struct grid (RECURSIVE FUNCTION)
fp: output stream
self: pointer to grid to be analyzed
*/
void printgridstruct(FILE *fp,struct Grid *self)
{
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Module below nicely formats level tree */
{
int level;
fprintf(fp,"(%3d x%3d x%3d ) <%+3d %+3d %+3d >: ",
self->dim.x,self->dim.y,self->dim.z,
self->org.x,self->org.y,self->org.z
);
for (level=0; level< self->level; level++)
fprintf(fp," ");
fprintf(fp,"[%d]\n",self->level);
}
/* Do child and sibling (return immediately if none) */
printgridstruct(fp, self->child);
printgridstruct(fp, self->sibling);
return;
}
/*
Outputs hierarchical structure of a struct grid (RECURSIVE FUNCTION)
on the screen
self: pointer to grid to be outputted
*/
void outputgridstruct(struct Grid *ingrid)
{
int nlx,nly,nlz;
int i,j,k;
nlx=ingrid->dim.x;nly=ingrid->dim.y;nlz=ingrid->dim.z;
i= (nlx/2);
j= (nly/2);
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (ingrid==NULL) return;
/* for (k=0;k<nlz;k++) */
/* printf("%14.9lf %14.9lf %14.9lf %14.9lf\n", */
/* ingrid->dat[k+20], */
/* ingrid->dat[k+40], */
/* ingrid->dat[k+60], */
/* ingrid->dat[k+100] ); */
for (k=0;k<nlz;k++)
printf("%14.9lf %14.9lf %14.9lf %14.9lf\n",
ingrid->dat[(i*nly+j)*nlz+k],
ingrid->dat[((i+1)*nly+j)*nlz+k],
ingrid->dat[(i*nly+j+1)*nlz+k],
ingrid->dat[((i+1)*nly+j+1)*nlz+k] );
printf("\n\n");
}
/*
Outputs hierarchical structure of a struct grid (RECURSIVE FUNCTION)
on the screen
self: pointer to grid to be outputted
*/
void outputgridstructy(struct Grid *ingrid)
{
int nlx,nly,nlz;
int i,j,k;
nlx=ingrid->dim.x;nly=ingrid->dim.y;nlz=ingrid->dim.z;
i= (nlx/2);
j= (nly/2);
k= (nlz/2);
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (ingrid==NULL) return;
/* for (k=0;k<nlz;k++) */
/* printf("%14.9lf %14.9lf %14.9lf %14.9lf\n", */
/* ingrid->dat[k+20], */
/* ingrid->dat[k+40], */
/* ingrid->dat[k+60], */
/* ingrid->dat[k+100] ); */
for (j=0;j<nly;j++)
printf("%14.9lf %14.9lf %14.9lf %14.9lf\n",
ingrid->dat[(i*nly+j)*nlz+k],
ingrid->dat[((i+1)*nly+j)*nlz+k],
ingrid->dat[(i*nly+j+1)*nlz+k],
ingrid->dat[((i+1)*nly+j+1)*nlz+k] );
printf("\n\n");
}
/*
Outputs hierarchical structure of a struct grid (RECURSIVE FUNCTION)
on the screen
self: pointer to grid to be outputted
*/
void outputgridstructx(struct Grid *ingrid)
{
int nlx,nly,nlz;
int i,j,k;
nlx=ingrid->dim.x;nly=ingrid->dim.y;nlz=ingrid->dim.z;
i= (nlx/2);
j= (nly/2);
k= (nlz/2);
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (ingrid==NULL) return;
/* for (k=0;k<nlz;k++) */
/* printf("%14.9lf %14.9lf %14.9lf %14.9lf\n", */
/* ingrid->dat[k+20], */
/* ingrid->dat[k+40], */
/* ingrid->dat[k+60], */
/* ingrid->dat[k+100] ); */
for (i=0;i<nlx;i++)
printf("%14.9lf %14.9lf %14.9lf %14.9lf\n",
ingrid->dat[(i*nly+j)*nlz+k],
ingrid->dat[((i+1)*nly+j)*nlz+k],
ingrid->dat[(i*nly+j+1)*nlz+k],
ingrid->dat[((i+1)*nly+j+1)*nlz+k] );
printf("\n\n");
}
/*
Outputs structure of a memory block where
we specify parameters in the function call
so as to output is as if it was a gridstruct
nlx: linear dimension of grid
i: coordinates along which we want to ouput coefficients
direction: direction along which we want to output coeffs
*/
void outputmem(double indat[], int nlx, int nly, int nlz,
int i, int j, int k,
int direction)
{
if (indat==NULL) return;
printf("%d %d %d\n",nlx,nly,nlz);
printf("%d %d %d\n",i,j,k);
if (direction==1)
for (i=0;i<nlx;i++)
printf("%d %20.16lf\n",i,indat[(i*nly+j)*nlz+k]);
if (direction==2)
for (j=0;j<nly;j++)
printf("%d %20.16lf\n",j,indat[(i*nly+j)*nlz+k]);
if (direction==3)
for (k=0;k<nlz;k++)
printf("%d %20.16lf\n",k,indat[(i*nly+j)*nlz+k]);
printf("\n\n");
}
/*
Go through struct grid hierarchy and find largest data set dimensions
(OUTPUT, RECURSIVE FUNCTION)
self: pointer to grid to be analyzed
mx: pointer to Ivec containing maximum size upon return
For ROOT call, set to (0,0,0)
(DON'T USE NULLIVEC! That would change NULLIVEC!)
*/
void getgridsizemx(struct Grid *self,struct Ivec *mx)
{
/* Return immediately if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Do child and sibling first (return immediately if none) */
getgridsizemx(self->child, mx);
getgridsizemx(self->sibling, mx);
mx->x=(mx->x > self->dim.x ? mx->x : self->dim.x);
mx->y=(mx->y > self->dim.y ? mx->y : self->dim.y);
mx->z=(mx->z > self->dim.z ? mx->z : self->dim.z);
return;
}
/*
Sum all ghostpoint elements of a grid (OUT, RECURSIVE FUNCTION),
to see if they are actually all zero
self: pointer to grid hierarchies to be summed
*/
double gridckghosts(struct Grid *self,int ghost)
{
double sum=0.;
int i,j,k;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return(0.);
/* Conditions exist only on lower grids */
if (self->level>0)
for (i=0; i<self->dim.x; i+=2)
for (j=0; j<self->dim.y; j+=2)
for (k=0; k<self->dim.z; k+=2)
if (ghost==0)
sum+=pow(
*( self->dat+(i*self->dim.y+j)*self->dim.z+k )
,2);
else {
sum+=pow(
*( self->dat+(i*self->dim.y+j)*self->dim.z+k )
-
*( self->parent->dat +
( (self->org.x+i/2) * self->parent->dim.y +
(self->org.y+j/2) ) * self->parent->dim.z +
(self->org.z+k/2) )
,2);
}
/* Add in contributions from children and siblings */
sum+=gridckghosts(self->child, ghost);
sum+=gridckghosts(self->sibling, ghost);
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("CkG: "); */
/* for (level=0; level< self1->level; level++) */
/* printf(" "); */
/* printf("[%d] %lf\n",self1->level,self); */
/* } */
return(sum);
}
/*
FIll in grid with ones on ghost points (OUT, RECURSIVE FUNCTION)
self: pointer to grid hierarchies to be thus filled
*/
void gridghost(struct Grid *self)
{
int i,j,k;
/* Return immediately with zero if there is nothing to do */
/* No excutables BEFORE this statement, please! */
if (self==NULL) return;
/* Fill in own level */
for (i=0; i<self->dim.x; i++)
for (j=0; j<self->dim.y; j++)
for (k=0; k<self->dim.z; k++)
(*( self->dat
+ (i * self->dim.y + j) * self->dim.z
+ k )) =
(
( ((i%2)+(j%2)+(k%2) == 0) && (self->level > 0) ) ? 1 : 0
);
/* Do children and siblings */
gridghost(self->child);
gridghost(self->sibling);
/* Print statement(s) for debugging */
/* { */
/* int level; */
/* printf("D: "); */
/* for (level=0; level< self1->level; level++) */
/* printf(" "); */
/* printf("[%d] %lf\n",self1->level,self); */
/* } */
return;
}
/*Will update the values on the grid below according
to the values on this grid*/
/* IPD: Actually looks like it adjusts the values on this grid
* according to the values above
*/
void adjustdown(struct Grid *in)
{
int nnx_low,nny_low,nnz_low;
int ix,iy,iz;/*more loop indeces*/
int nnx,nny,nnz;
int anx,any,anz;
if (in->parent){
nnx=in->parent->dim.x;
nny=in->parent->dim.y;
nnz=in->parent->dim.z;
nnx_low=in->dim.x;
nny_low=in->dim.y;
nnz_low=in->dim.z;
anx=in->org.x;
any=in->org.y;
anz=in->org.z;
for (ix=0;ix<nnx_low;ix+=2)
for (iy=0;iy<nny_low;iy+=2)
for (iz=0;iz<nnz_low;iz+=2){
in->dat[iz+nnz_low*iy+nnz_low*nny_low*ix]
=in->parent->dat[(iz/2+anz)+nnz*(iy/2+any)+nnz*nny*(ix/2+anx)];
}
}
if (in->child)
adjustdown(in->child);
if (in->sibling)
adjustdown(in->sibling);
}
/* Checks if two grids are symmetric partners w/ respect of symop
* compute everything in the current level scale
*/
int
if_partners(struct Grid *grid1, struct Grid *grid2,int* symop,struct Ivec Rsym)
{
/* centers of the grids */
struct Ivec center1;
struct Ivec center2;
/* first check if they are NULL grids, in which case
return sym partners found, so that it doesn't look further */
if (grid1==NULL || grid2==NULL){
if(grid1==NULL && grid2==NULL);/* both are NULL - just return */
/* only one of them is null */
printf("the grid structure and the symmetry are inconsistent\n");
exit(1);
return -1;
}
/* check that their parents have the same structure
be careful what to check - levels, sizes, but not origins...
if( *grid1 != *grid2 || *(grid1->parent)!=*(grid2->parent) ){
fprintf(stderr,"Different grid structures in if_partners()!\n");
exit(1);
}
compute the centers of the grids w/ respect to the center of
symmetry in the current level scale */
center1.x = 2*grid1->org.x + grid1->dim.x/2 - Rsym.x;
center1.y = 2*grid1->org.y + grid1->dim.y/2 - Rsym.y;
center1.z = 2*grid1->org.z + grid1->dim.z/2 - Rsym.z;
center2.x = 2*grid2->org.x + grid2->dim.x/2 - Rsym.x;
center2.y = 2*grid2->org.y + grid2->dim.y/2 - Rsym.y;
center2.z = 2*grid2->org.z + grid2->dim.z/2 - Rsym.z;
/* MAY BE THE ABOVE EQUATIONS SHOULD BE MULTIPLIED BY 2
in order to work for semihalf integers?
can implement it ion the sym group class -
Rsym has two components: Ivec and ratio, so that, the real
Isym is in fact Ivec/ratio. However since it works only for rational
numbers we can easy implement the checks within this framework */
/* printf("Rsym=(%d, %d, %d)\n",Rsym.x, Rsym.y, Rsym.z); */
/* printf("C1 =(%d, %d, %d)\n",center1.x, center1.y, center1.z); */
/* printf("C2 =(%d, %d, %d)\n",center2.x, center2.y, center2.z); */
center1.x -=
symop[0]*center2.x + symop[1]*center2.y + symop[2]*center2.z;
center1.y -=
symop[3]*center2.x + symop[4]*center2.y + symop[5]*center2.z;
center1.z -=
symop[6]*center2.x + symop[7]*center2.y + symop[8]*center2.z;
/* printf("C1-C2=(%d, %d, %d)\n",center1.x, center1.y, center1.z); */
/* now check if they are partners in fact */
/* PAY ATTENTION TO WRAP IN CASE OF SYMMETRIC LEVE OR PARENT */
if(grid1->ifperiodic){
/* printf("periodic GRID\n"); */
if( (center1.x % grid1->dim.x) == 0 &&
(center1.y % grid1->dim.y) == 0 &&
(center1.z % grid1->dim.z) == 0)
return 1;
}
else if(grid1->parent)
if(grid1->parent->ifperiodic){
/* printf("periodic PARENT\n"); */
if( (center1.x % (2*grid1->parent->dim.x)) == 0 &&
(center1.y % (2*grid1->parent->dim.y)) == 0 &&
(center1.z % (2*grid1->parent->dim.z)) == 0)
return 1;
}
else{ /* nonperiodic parent and grid */
/* printf("NON-periodic PARENT and GRID\n"); */
if(center1.x==0 && center1.y==0 && center1.z==0)
return 1;
}
else { /* nonperiodic top level */
/* printf("NON-periodic TOP\n"); */
if(center1.x==0 && center1.y==0 && center1.z==0)
return 1;
}
return 0;
}
/* Checks if two grids are symmetric partners w/ respect of symop
* compute everything in TWICE the current level scale
*/
int
if_partners_new(struct Grid *grid1, struct Grid *grid2,int* symop,
struct Dvec Rsym)
{
/* centers of the grids */
struct Ivec center1;
struct Ivec center2;
/* first check if they are NULL grids, in which case */
/* return sym partners found, so that it doesn't look further */
if (grid1==NULL || grid2==NULL){
if(grid1==NULL && grid2==NULL)
;/* both are NULL - just return */
/* only one of them is null */
printf("The grid structure and the symmetry are inconsistent\n");
printf("Two symmetric partners have different levels of resolution\n");
exit(1);
return -1;
}
/* compute the centers of the grids w/ respect to the center of
symmetry in TWICE the current level scale, so that it will work
even if R is semihalf integer */
center1.x = 4*grid1->org.x + grid1->dim.x - (int)(2*Rsym.x);
center1.y = 4*grid1->org.y + grid1->dim.y - (int)(2*Rsym.y);
center1.z = 4*grid1->org.z + grid1->dim.z - (int)(2*Rsym.z);
center2.x = 4*grid2->org.x + grid2->dim.x - (int)(2*Rsym.x);
center2.y = 4*grid2->org.y + grid2->dim.y - (int)(2*Rsym.y);
center2.z = 4*grid2->org.z + grid2->dim.z - (int)(2*Rsym.z);
/* Rsym has two components: Ivec and ratio, so that, the real
Isym is in fact Ivec/ratio. However since it works only for rational
numbers we can easy implement the checks within this framework */
/* printf("Rsym=(%d, %d, %d)\n",Rsym.x, Rsym.y, Rsym.z); */
/* printf("C1 =(%d, %d, %d)\n",center1.x, center1.y, center1.z); */
/* printf("C2 =(%d, %d, %d)\n",center2.x, center2.y, center2.z); */
center1.x -=
symop[0]*center2.x + symop[1]*center2.y + symop[2]*center2.z;
center1.y -=
symop[3]*center2.x + symop[4]*center2.y + symop[5]*center2.z;
center1.z -=
symop[6]*center2.x + symop[7]*center2.y + symop[8]*center2.z;
/* printf("C1-C2=(%d, %d, %d)\n",center1.x, center1.y, center1.z); */
/* now check if they are partners in fact */
/* PAY ATTENTION TO WRAP IN CASE OF SYMMETRIC LEVEL OR PARENT */
if(grid1->ifperiodic){
/* printf("periodic GRID\n"); */
if( (center1.x % (2*grid1->dim.x) ) == 0 &&
(center1.y % (2*grid1->dim.y) ) == 0 &&
(center1.z % (2*grid1->dim.z) ) == 0)
return 1;
}
else if(grid1->parent)
if(grid1->parent->ifperiodic){
/* printf("periodic PARENT\n"); */
if( (center1.x % (4*grid1->parent->dim.x)) == 0 &&
(center1.y % (4*grid1->parent->dim.y)) == 0 &&
(center1.z % (4*grid1->parent->dim.z)) == 0)
return 1;
}
else{ /* nonperiodic parent and grid */
/* printf("NON-periodic PARENT and GRID\n"); */
if(center1.x==0 && center1.y==0 && center1.z==0)
return 1;
}
else { /* nonperiodic top level */
/* printf("NON-periodic TOP\n");*/
if(center1.x==0 && center1.y==0 && center1.z==0)
return 1;
}
return 0;
}
/* Finds the sympartner w/ respect to symop of grid1 among the siblings
* of grid2. Recursive function to loop over the siblings
*/
struct Grid*
findsympartner(struct Grid* grid1, struct Grid* grid2, int* symop,
struct Ivec Rsym)
{
int flag;
/* check if grid1 and grid2 are symmetric partners */
if (flag=if_partners(grid1,grid2,symop,Rsym)){/* 2 is partner or null */
if (flag==-1) /* at least one grid is null */
return NULL;
/* printf("partners found\n"); */
return grid2;
}
else /* go and check if the sibling of grid2 is partner */
return findsympartner(grid1,grid2->sibling,symop,Rsym);
}
/* The symmetric points are related by rout-R=S(rin-R),
* where R is the center of symmetry and S is the symmetry matrix
* we calculate the coordinate of the symmetric image as
* rout=S(rin) + R-S(R)
* if we relate everything w/ respect of the center of the parent grid
!!! prtobably w/ respect ro R...
* rin = in->org+ijk, rout = out->org+iijjkk
* and normally R=parent->dim/2 * 2 (larger scale)
* then iijjkk=S(ijk)+shift
* and shift = S(2*in->org - R) + R - out->org*2
*** MAY BE WE CAN SPECIFY THE CENTER OF SYMMETRY along with SYMOP!!
* Another tricky part is how we handle the boundaries of the grid if
* the symmetry transformation maps existing grid points to nonexisting
* grid points. Another way to look at it is that some expansion
* coefficients map to expansion coefficients that are zero
* A consistent solution would be to set such coefficients to zero.
* This problem only arises in the grid boundaries, of nonperiodic grid,
* therefore we can skip them now and later 1) adjustdown() for ghost points
* consistency, 2) transform to coeff space and zero the nonghostpoint coeff.
* Since the interpolets are cardinal functions on a given level, the
* transformation to coeff space will not touch coeff on a current level.
* Then it won't touch the level above because it is done from top to bottom.
* If the lower levels start far enough from the edges (4-5 pts) they will
* not be touched as well and the described algorithm does what it claims to
* (sets some of the expansion coefeicients to zero)
*/
void
symcopy(struct Grid* out,const struct Grid* in, int* symop, struct Ivec Rsym)
{
struct Ivec R;
int shift[3]={0,0,0};
int ox, oy, oz; /* origin of the output grid in the current scale */
int px, py, pz; /* period in x, y, z direction */
int i,j,k; /* data in in grid */
int ii,jj,kk; /* data in out grid */
int flag;
/* printf("symcopy() in->level %d to out->level %d\n", in->level,out->level); */
/* now Rsym is always in the current level scale */
R.x=Rsym.x;
R.y=Rsym.y;
R.z=Rsym.z;
ox=2*out->org.x;
oy=2*out->org.y;
oz=2*out->org.z;
shift[0] =
symop[0]*(2*in->org.x-R.x)
+ symop[1]*(2*in->org.y-R.y)
+ symop[2]*(2*in->org.z-R.z)
+ R.x;
shift[1] =
symop[3]*(2*in->org.x-R.x)
+ symop[4]*(2*in->org.y-R.y)
+ symop[5]*(2*in->org.z-R.z)
+ R.y;
shift[2] =
symop[6]*(2*in->org.x-R.x)
+ symop[7]*(2*in->org.y-R.y)
+ symop[8]*(2*in->org.z-R.z)
+ R.z;
/* printf("Rsym=(%d, %d, %d) ", R.x, R.y, R.z); */
/* printf("Shift = (%d, %d, %d)\n", shift[0], shift[1], shift[2]); */
/* if the level or its parent are periodic S(2*in->org - R) */
/* can go beyond the cell and we have to wrap it back */
if(in->ifperiodic){
/* printf("periodic grid\n"); */
flag=0;
}
else
if(in->parent)
if(in->parent->ifperiodic){
/* printf("periodic parent\n"); */
flag=1;
}
else{
/* printf("NON-periodic grid and parent\n"); */
flag=2;
}
else{
/* printf("NON-periodic top level\n"); */
flag=2;
}
if (flag==2){ /* neither the grid nor the parent is pariodic */
shift[0]-=ox;
shift[1]-=oy;
shift[2]-=oz;
/* loop over the internal points of "in" */
for (i=1; i<in->dim.x; i++)
for (j=1; j<in->dim.y; j++)
for (k=1; k<in->dim.z; k++){
/* get the position of the symmetric point */
ii = symop[0]*i + symop[1]*j + symop[2]*k + shift[0];
jj = symop[3]*i + symop[4]*j + symop[5]*k + shift[1];
kk = symop[6]*i + symop[7]*j + symop[8]*k + shift[2];
/* copy the data */
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z+k );
}
/* now the boundaries:
for nonperiodic level do nothing. adjustdown() will take care
for the ghost points and then we'll zero nonghost points
in the coeff space. At the end transform back to real space */
}
else { /* we have to wrap around */
/* find the period */
switch(flag){
case 1: /* periodic top level */
px=2*out->parent->dim.x;
py=2*out->parent->dim.y;
pz=2*out->parent->dim.z;
break;
case 0:
px=out->dim.x;
py=out->dim.y;
pz=out->dim.z;
break;
default:
printf("symcopy(): never get here!!!\n");
exit(1);
}
/* printf("Shift = (%d, %d, %d)\n", shift[0], shift[1], shift[2]); */
/* printf("o = (%d, %d, %d)\n", ox, oy, oz); */
/* loop over the internal points of "in" */
for (i=1; i<in->dim.x; i++)
for (j=1; j<in->dim.y; j++)
for (k=1; k<in->dim.z; k++){
/* get the position of the symmetric point */
ii = ( (symop[0]*i + symop[1]*j + symop[2]*k + shift[0])
% px + px ) % px - ox;
jj = ( (symop[3]*i + symop[4]*j + symop[5]*k + shift[1])
% py + py ) % py - oy;
kk = ( (symop[6]*i + symop[7]*j + symop[8]*k + shift[2])
% pz + pz ) % pz -oz;
/* copy the data */
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z+k );
}
/* only if the grid is periodic take care of the boundary wrapping */
if(out->ifperiodic){
/* do the xy plane (k=0) */
for (i=0;i<in->dim.x;i++)
for (j=0;j<in->dim.y;j++){
ii = (symop[0]*i + symop[1]*j + shift[0] + px) % px -ox;
jj = (symop[3]*i + symop[4]*j + shift[1] + py) % py -oy;
kk = (symop[6]*i + symop[7]*j + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z );
}
/* now the yz plane (i=0) */
for (j=0;j<in->dim.y;j++)
for (k=1; k<in->dim.z;k++){/* already did i=0 j=0 k=0 */
ii = (symop[1]*j + symop[2]*k + shift[0] + px) % px -ox;
jj = (symop[4]*j + symop[5]*k + shift[1] + py) % py -oy;
kk = (symop[7]*j + symop[8]*k + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + j*in->dim.z+k );
}
/* xz plane (j=0) */
for (i=1;i<in->dim.x;i++)
for (k=1;k<in->dim.y;k++){
ii = (symop[0]*i + symop[2]*k + shift[0] + px) % px -ox;
jj = (symop[3]*i + symop[5]*k + shift[1] + py) % py -oy;
kk = (symop[6]*i + symop[8]*k + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + i*in->dim.y*in->dim.z+k );
}
}/* done with the wrapping */
}/* done with periodic case */
}
/* MUST VERIFY!!! */
void
symcopy_new(struct Grid* out,const struct Grid* in, int* symop, struct Ivec Rsym)
{
struct Ivec R;
int shift[3]={0,0,0};
int ox, oy, oz; /* origin of the output grid in the current scale */
int px, py, pz; /* period in x, y, z direction */
int i,j,k; /* data in in grid */
int ii,jj,kk; /* data in out grid */
int iii, jjj, kkk; /* data in out grid - faster algorithm */
int flag;
double *datain;
return;
/* printf("symcopy() in->level %d to out->level %d\n", in->level,out->level); */
/* now Rsym is always in the current level scale */
R.x=Rsym.x;
R.y=Rsym.y;
R.z=Rsym.z;
ox=2*out->org.x;
oy=2*out->org.y;
oz=2*out->org.z;
shift[0] =
symop[0]*(2*in->org.x-R.x)
+ symop[1]*(2*in->org.y-R.y)
+ symop[2]*(2*in->org.z-R.z)
+ R.x;
shift[1] =
symop[3]*(2*in->org.x-R.x)
+ symop[4]*(2*in->org.y-R.y)
+ symop[5]*(2*in->org.z-R.z)
+ R.y;
shift[2] =
symop[6]*(2*in->org.x-R.x)
+ symop[7]*(2*in->org.y-R.y)
+ symop[8]*(2*in->org.z-R.z)
+ R.z;
/* printf("Rsym=(%d, %d, %d) ", R.x, R.y, R.z); */
/* printf("Shift = (%d, %d, %d)\n", shift[0], shift[1], shift[2]); */
/* if the level or its parent are periodic S(2*in->org - R) */
/* can go beyond the cell and we have to wrap it back */
if(in->ifperiodic){
/* printf("periodic grid\n"); */
flag=0;
}
else
if(in->parent)
if(in->parent->ifperiodic){
/* printf("periodic parent\n"); */
flag=1;
}
else{
/* printf("NON-periodic grid and parent\n"); */
flag=2;
}
else{
/* printf("NON-periodic top level\n"); */
flag=2;
}
if (flag==2){ /* neither the grid nor the parent is pariodic */
shift[0]-=ox;
shift[1]-=oy;
shift[2]-=oz;
/* loop over the internal points of "in" */
for (i=1; i<in->dim.x; i++){
ii = shift[0] + symop[0]*i;
jj = shift[1] + symop[3]*i;
kk = shift[2] + symop[6]*i;
for (j=1; j<in->dim.y; j++){
ii += symop[1]; iii=ii;
jj += symop[4]; jjj=jj;
kk += symop[7]; kkk=kk;
/* datain = in->dat + (i*in->dim.y+j)*in->dim.z; */
for (k=1; k<in->dim.z; k++){
/* get the position of the symmetric point */
/*
ii = shift[0] + symop[0]*i + symop[1]*j + symop[2]*k;
jj = shift[1] + symop[3]*i + symop[4]*j + symop[5]*k;
kk = shift[2] + symop[6]*i + symop[7]*j + symop[8]*k;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( indat + (i*in->dim.y+j)*in->dim.z );
*/
iii += symop[2];
jjj += symop[5];
kkk += symop[8];
/* copy the data */
*( out->dat + (iii*out->dim.y+jjj)*out->dim.z+kkk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z + k);
/*+= *( datain++); */
}
}
}
/* now the boundaries:
for nonperiodic level do nothing. adjustdown() will take care
for the ghost points and then we'll zero nonghost points
in the coeff space. At the end transform back to real space */
}
else { /* we have to wrap around */
/* find the period */
switch(flag){
case 1: /* periodic top level */
px=2*out->parent->dim.x;
py=2*out->parent->dim.y;
pz=2*out->parent->dim.z;
break;
case 0:
px=out->dim.x;
py=out->dim.y;
pz=out->dim.z;
break;
default:
printf("symcopy(): never get here!!!\n");
exit(1);
}
/* printf("Shift = (%d, %d, %d)\n", shift[0], shift[1], shift[2]); */
/* printf("o = (%d, %d, %d)\n", ox, oy, oz); */
/* loop over the internal points of "in" */
for (i=1; i<in->dim.x; i++)
for (j=1; j<in->dim.y; j++)
for (k=1; k<in->dim.z; k++){
/* get the position of the symmetric point */
ii = ( (symop[0]*i + symop[1]*j + symop[2]*k + shift[0])
% px + px ) % px - ox;
jj = ( (symop[3]*i + symop[4]*j + symop[5]*k + shift[1])
% py + py ) % py - oy;
kk = ( (symop[6]*i + symop[7]*j + symop[8]*k + shift[2])
% pz + pz ) % pz -oz;
/* copy the data */
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z+k );
}
/* only if the grid is periodic take care of the boundary wrapping */
if(out->ifperiodic){
/* do the xy plane (k=0) */
for (i=0;i<in->dim.x;i++)
for (j=0;j<in->dim.y;j++){
ii = (symop[0]*i + symop[1]*j + shift[0] + px) % px -ox;
jj = (symop[3]*i + symop[4]*j + shift[1] + py) % py -oy;
kk = (symop[6]*i + symop[7]*j + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + (i*in->dim.y+j)*in->dim.z );
}
/* now the yz plane (i=0) */
for (j=0;j<in->dim.y;j++)
for (k=1; k<in->dim.z;k++){/* already did i=0 j=0 k=0 */
ii = (symop[1]*j + symop[2]*k + shift[0] + px) % px -ox;
jj = (symop[4]*j + symop[5]*k + shift[1] + py) % py -oy;
kk = (symop[7]*j + symop[8]*k + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + j*in->dim.z+k );
}
/* xz plane (j=0) */
for (i=1;i<in->dim.x;i++)
for (k=1;k<in->dim.y;k++){
ii = (symop[0]*i + symop[2]*k + shift[0] + px) % px -ox;
jj = (symop[3]*i + symop[5]*k + shift[1] + py) % py -oy;
kk = (symop[6]*i + symop[8]*k + shift[2] + pz) % pz -oz;
*( out->dat + (ii*out->dim.y+jj)*out->dim.z+kk )
+= *( in->dat + i*in->dim.y*in->dim.z+k );
}
}/* done with the wrapping */
}/* done with periodic case */
}
/* Symmetrize a grid with respect to a specific symmetry operation
* Accumulates the result in output grid. Recursive routine.
* symop : the symmetry operator (3x3 integer matrix)
* Rsym : the center of the symmetry in the scale of the current level
* Needs two additional routines to identify if two grids are symmetric
* partners and to implement the symmetrization on the current grid level
* we must zero the out grid before the first call!!!
* If the current level is nonperiodic we should pass to its children as a
* center of symmetry its center, otherwise (periodic level) the
* center of symmetry
*/
void symmetrize_accum(struct Grid* out, struct Grid* in,
int* symop, struct Ivec Rsym)
{
struct Grid* partner;
/* by default the children are symmetric w/ respect to the */
/* center of the current level (scaled to their resolution) */
struct Ivec Rsymc=out->dim;
/* nothing above please!!! */
if (out==NULL) return; /* nothing to do */
if(in==NULL){
/* we should never fall in this case - just for debugging */
printf("symmetrize(): never come here\n");
return;/* exit(1); */
}
/* may be some checks for in-out consistency here ... */
/* first symmetryze the current level */
symcopy(out,in,symop,Rsym);
/* first do the children if you have any */
if (out->child){
/* printf("\n------\nsymmetrize the children: level %d\n", */
/* out->child->level); */
/* pass to the child Rsym*2 (to acount for the scale) */
if(out->ifperiodic){
Rsymc.x=Rsym.x*2;
Rsymc.y=Rsym.y*2;
Rsymc.z=Rsym.z*2;
}
/* go to out->child and find its symmetric partner */
/* among the siblings of in->child */
partner=findsympartner(out->child,in->child,symop,Rsymc);
/* now we have the partner of out->child, so do it */
symmetrize_accum(out->child,partner,symop,Rsymc);
}
/* curently "in" points to the partner of out->child */
/* we need to get to the first child of "in" */
/* now go to your sibling if you have one */
if (out->sibling){
/* printf("\n-------\nsymmetrize the siblings: level %d\n", */
/* out->sibling->level); */
/* find its partner among "in" and its siblings */
if (in->parent){
/* find the symmetric partner among all the children of in->parent */
/* starting from the first */
partner=findsympartner(out->sibling,in->parent->child,symop,Rsym);
/* symmetrize it */
symmetrize_accum(out->sibling,partner,symop,Rsym);
}
}
}
void symmetrize_accum_new(struct Grid* out, struct Grid* in,
int* symop, struct Ivec Rsym)
{
struct Grid* partner;
/* by default the children are symmetric w/ respect to the */
/* center of the current level (scaled to their resolution) */
struct Ivec Rsymc=out->dim;
/* nothing above please!!! */
if (out==NULL) return; /* nothing to do */
if(in==NULL){
/* we should never fall in this case - just for debugging */
printf("symmetrize(): never come here\n");
return;/* exit(1); */
}
/* may be some checks for in-out consistency here ... */
/* first symmetryze the current level */
symcopy_new(out,in,symop,Rsym);
/* first do the children if you have any */
if (out->child){
/* printf("\n------\nsymmetrize the children: level %d\n", */
/* out->child->level); */
/* pass to the child Rsym*2 (to acount for the scale) */
if(out->ifperiodic){
Rsymc.x=Rsym.x*2;
Rsymc.y=Rsym.y*2;
Rsymc.z=Rsym.z*2;
}
/* go to out->child and find its symmetric partner */
/* among the siblings of in->child */
partner=findsympartner(out->child,in->child,symop,Rsymc);
/* now we have the partner of out->child, so do it */
symmetrize_accum_new(out->child,partner,symop,Rsymc);
}
/* curently "in" points to the partner of out->child */
/* we need to get to the first child of "in" */
/* now go to your sibling if you have one */
if (out->sibling){
/* printf("\n-------\nsymmetrize the siblings: level %d\n", */
/* out->sibling->level); */
/* find its partner among "in" and its siblings */
if (in->parent){
/* find the symmetric partner among all the children of in->parent */
/* starting from the first */
partner=findsympartner(out->sibling,in->parent->child,symop,Rsym);
/* symmetrize it */
symmetrize_accum_new(out->sibling,partner,symop,Rsym);
}
}
}
/* Recursive function that sets to zero all the coefficeints on the edges
* of a grid. This is necessary to restore te symmetry of a problem, which
* we broke by designing the grid to have even number of basis finctions
* in each direction. Sometimes the edge points have partners, which do
* not exist in our grid, i.e. we assume those coefficients to be zero,
* by construction of the grid.
*/
void setsymzero(struct Grid *self)
{
/* there is no way to check real/coeff space - do it outside */
int i,j,k;
int dimx,dimy,dimz;
double *pplaneorg;
if(self==NULL) return;
dimx=self->dim.x;
dimy=self->dim.y;
dimz=self->dim.z;
/* On a periodic level do nothing - everything is alright */
if(!self->ifperiodic){
if(self->level==0)
printf("Nonperiodic top level!!! BUG in setsymzero?\n");
/* first do xy plane (k=0) */
for (i=0;i <dimx; i++)
for( j=0; j<dimy; j++)
if(i%2!=0 || j%2!=0) /* nonghost point */
*(self->dat + (i*dimy+j)*dimz )=0.;
/* now the yz plane (i=0) */
for(j=0; j<dimy; j++){
pplaneorg=self->dat+j*dimz;
for (k=1; k<dimz; k++)
if(j%2!=0 || k%2!=0)
*(pplaneorg + k)=0.;
}
/* finally the zx plane (j=0) */
for(i=1; i<dimx; i++){
pplaneorg=self->dat+i*dimy*dimz;
for (k=1; k<dimz; k++)
if (i%2!=0 || k%2!=0)
*(pplaneorg + k)=0.;
}
}
/* go to the children */
setsymzero(self->child);
/* go to the siblings */
setsymzero(self->sibling);
}
void applysym_coeff(struct Grid *gridout, struct Grid *gridin,
int * symop, struct Ivec Rsym)
{
/* zero the output grid */
evalgrid(gridout, NULLDVEC, zero);
symmetrize_accum(gridout, gridin, symop, Rsym);
/* make sure the boundaries in the lower levels are consistent */
adjustdown(gridout);
}
/* This interpolates cubic box to cubic box with double resolution
in each direction */
void interpolate_box_2_2x_box(struct Grid *dense, struct Grid *sparse)
{
int si, sj, sk;/* indices for sparse */
int sdx, sdy, sdz;/* dimensions of sparse */
int di, dj, dk;/* indices for dense */
int ddx, ddy, ddz; /* dimensions for dense */
int ri, rj, rk; /* residues from dindex%2 */
if( dense==NULL && sparse==NULL)
return;/* nothing to do */
if( dense==NULL && sparse==NULL ) {/* only one is NULL - NO WAY ! */
printf("Grids of nonidentical structure\n");
printf("interpolate_box_2_2x_box() has only one NULL grid\n");
exit(1);
}
if( ( (ddx=dense->dim.x) != 2*(sdx=sparse->dim.x) )||
( (ddy=dense->dim.y) != 2*(sdy=sparse->dim.y) )||
( (ddz=dense->dim.z) != 2*(sdz=sparse->dim.z) ) ){
printf("Grids of nonidentical structure\n");
printf("interpolate_box_2_2x_box() dense.dim != 2x sparse.dim\n");
exit(1);
}
if( (dense->org.x != 2*sparse->org.x)||
(dense->org.y != 2*sparse->org.y)||
(dense->org.z != 2*sparse->org.z) ){
printf("Grids of nonidentical structure\n");
printf("interpolate_box_2_2x_box() dense.org != 2x sparse.org\n");
exit(1);
}
for(di=0; di<ddx; di++){
si=di/2;
ri=di%2;
for(dj=0; dj<ddy; dj++){
sj=dj/2;
rj=dj%2;
for(dk=0; dk<ddz; dk++){
sk=dk/2;/* ints */
rk=dk%2;/* residues */
*(dense->dat + (di*ddy+dj)*ddz+dk ) =
.125*(
*(sparse->dat + (si*sdy + sj)*sdz + sk )+
*(sparse->dat + (si*sdy + sj)*sdz + sk + rk )+
*(sparse->dat + (si*sdy + sj+rj)*sdz + sk )+
*(sparse->dat + ((si+ri)*sdy + sj)*sdz + sk )+
*(sparse->dat + (si*sdy + sj+rj)*sdz + sk +rk )+
*(sparse->dat + ((si+ri)*sdy + sj)*sdz + sk +rk)+
*(sparse->dat + ((si+ri)*sdy + sj+rj)*sdz + sk )+
*(sparse->dat + ((si+ri)*sdy + sj+rj)*sdz + sk +rk)
);
}
}
}
}
/* updates the data on a coarser level to be consistent with the data
on a finer level of resolution */
void updateparent(struct Grid *self)
{
int dimx,dimy, dimz;
int pdimx,pdimy, pdimz;
int i, j, k;/* current indices */
int ip, jp, kp;/* parent indices */
if(self==NULL || self->parent==NULL)
return;
dimx=self->dim.x;
dimy=self->dim.y;
dimz=self->dim.z;
pdimx=self->parent->dim.x;
pdimy=self->parent->dim.y;
pdimz=self->parent->dim.z;
ip=self->org.x;
/* here is the actual update */
for(i=0; i<dimx; i+=2){
jp=self->org.y;
for(j=0; j<dimy; j+=2){
kp=self->org.z;
for(k=0; k<dimz; k+=2) {
*(self->parent->dat + (ip*pdimy+jp)*pdimz+kp )=
*(self->dat + (i*dimy+j)*dimz+k );
kp++;
}
jp++;
}
ip++;
}
return;
}
/*This maps recursive grid to grid w/ double resolution
Interpolation seems reasonable at first sight, but then we have
multiresolution analysis, which is a-priori better. Therefore we
do interpolation only if we do not have the data from better resolution
First interpolates and then update the points on the coarser levels
which overrides the initial interpolation whenever it has taken place
This should be done in real space, where the ghost points are the same
as the coarser level, otherwise the ghost points are zero
and in the updating process we will destroy the upperm level
We do not perform any checks at this point - rather we'll have them
in the functions that are called
*/
void map_rg_2_2x_rg(struct Grid *dense, struct Grid *sparse)
{
interpolate_box_2_2x_box(dense, sparse);
if(dense->child)
map_rg_2_2x_rg(dense->child, sparse->child);
if(dense->sibling)
map_rg_2_2x_rg(dense->sibling, sparse->sibling);
updateparent(dense);
return ;
}
/* This interpolates cubic box to cubic box with double resolution
in each direction */
void map_2x_box_2_box( struct Grid *sparse, struct Grid *dense)
{
int si, sj, sk;/* indices for sparse */
int sdx, sdy, sdz;/* dimensions of sparse */
int di, dj, dk;/* indices for dense */
int ddx, ddy, ddz; /* dimensions for dense */
if( dense==NULL && sparse==NULL)
return;/* nothing to do */
if( dense==NULL || sparse==NULL ) {/* only one is NULL - NO WAY ! */
printf("Grids of nonidentical structure\n");
printf("interpolate_2x_box_2_box() has only one NULL grid\n");
exit(1);
}
if( ( (ddx=dense->dim.x) != 2*(sdx=sparse->dim.x) )||
( (ddy=dense->dim.y) != 2*(sdy=sparse->dim.y) )||
( (ddz=dense->dim.z) != 2*(sdz=sparse->dim.z) ) ){
printf("Grids of nonidentical structure\n");
printf("interpolate_2x_box_2_box() dense.dim != 2x sparse.dim\n");
exit(1);
}
if( (dense->org.x != 2*sparse->org.x)||
(dense->org.y != 2*sparse->org.y)||
(dense->org.z != 2*sparse->org.z) ){
printf("Grids of nonidentical structure\n");
printf("interpolate_2x_box_2_box() dense.org != 2x sparse.org\n");
exit(1);
}
for(si=0; si<sdx; si++){
di=2*si;
for(sj=0; sj<sdy; sj++){
dj=2*sj;
for(sk=0; sk<sdz; sk++){
dk=2*sk;
*( sparse->dat + (si*sdy + sj)*sdz + sk ) =
*( dense->dat + (di*ddy+dj)*ddz + dk );
}
}
}
}
void map_2x_rg_2_rg(struct Grid *sparse, struct Grid *dense)
{
map_2x_box_2_box(sparse, dense);
if(sparse->child)
map_2x_rg_2_rg(sparse->child, dense->child);
if(sparse->sibling)
map_2x_rg_2_rg(sparse->sibling, dense->sibling);
return ;
}
syntax highlighted by Code2HTML, v. 0.9.1