Esempio n. 1
0
void compute() {
	const int M = 256;
	const int N = 256;
	
	cmatrix h_naught(M, N, true, complex(0.0f, 0.0f));
	
	for (int row = 0; row < M; row++) {
		for (int col = 0; col < N; col++) {
			int n = col;
			int m = row;
			
			matrix3x1 K = Pi_2 * matrix3x1((float)n / N, 0, (float)m / M);
			
			complex h_0 = height_naught(K);
			
			h_naught.set(row, col, h_0);
		}
	}
	
	
	cmatrix h_tilde(M, N, true, complex(0, 0));
	cmatrix c_heights(M, N, true, complex(0, 0));
	fftwf_plan plan = fftwf_plan_dft_2d(M, N, (fftwf_complex *)h_tilde.getData(), 
		(fftwf_complex *)c_heights.getData(), FFTW_BACKWARD, FFTW_ESTIMATE);
	
	matrix heights(M, N, true, 0.0f);
		
	const int Frames = 1;
	for (int p = 0; p < Frames; p++) {
		float t = (float)p / Frames;
		
		for (int row = 0; row < M; row++) {
			for (int col = 0; col < N; col++) {
				h_tilde.set(row, col, Htilde(h_naught, row, col, t));
			}
		}
		
		// complex2complex FFT2D
		fftwf_execute(plan);
		
		// extract the real component
		for (int row = 0; row < M; row++) {
			for (int col = 0; col < N; col++) {
				heights.set(row, col, c_heights.get(row, col).r / 20.0f);
			}
		}
		
		// save the results
		{
			std::stringstream ss;
			ss << "ocean_" << std::setw(2) << std::setfill('0') << p << ".mat";
			std::ofstream file(ss.str().c_str());
			file << std::setprecision(10);
			math::matrix_writeAsText(file, heights);
		}
	}
	fftwf_destroy_plan(plan);
}
Esempio n. 2
0
	void FBMReference::diagonalizeBlock( const unsigned int block, const TNT::Array2D<double> &hessian,
										 const std::vector<Vec3> &positions, TNT::Array1D<double> &eval, TNT::Array2D<double> &evec ) {

		const unsigned int ConservedDegreesOfFreedom = 6;

		printf( "Diagonalizing Block: %d\n", block );

		// 1. Determine the starting and ending index for the block
		//    This means that the upper left corner of the block will be at (startatom, startatom)
		//    And the lower right corner will be at (endatom, endatom)
		const int startatom = 3 * blockSizes[block];
		int endatom = 3 * particleCount - 1 ;

		if( block != ( blockSizes.size() - 1 ) ) {
			endatom = 3 * blockSizes[block + 1] - 1;
		}

		const int size = endatom - startatom + 1;

		// 2. Get the block Hessian Hii
		//    Right now I'm just doing a copy from the big Hessian
		//    There's probably a more efficient way but for now I just want things to work..
		TNT::Array2D<double> h_tilde( size, size, 0.0 );
		for( int j = startatom; j <= endatom; j++ ) {
			for( int k = startatom; k <= endatom; k++ ) {
				h_tilde[k - startatom][j - startatom] = hessian[k][j];
			}
		}

		// 3. Diagonalize the block Hessian only, and get eigenvectors
		TNT::Array1D<double> di( size, 0.0 );
		TNT::Array2D<double> Qi( size, size, 0.0 );
		diagonalizeSymmetricMatrix( h_tilde, di, Qi );

		// sort eigenvalues by absolute magnitude
		std::vector<EigenvalueColumn> sortedPairs = sortEigenvalues( di );

		// find geometric dof
		TNT::Array2D<double> Qi_gdof( size, size, 0.0 );

		Vec3 pos_center( 0.0, 0.0, 0.0 );
		double totalmass = 0.0;

		for( int j = startatom; j <= endatom; j += 3 ) {
			double mass = mParticleMass[ j / 3 ];
			pos_center += positions[j / 3] * mass;
			totalmass += mass;
		}

		double norm = sqrt( totalmass );

		// actual center
		pos_center *= 1.0 / totalmass;

		// create geometric dof vectors
		// iterating over rows and filling in values for 6 vectors as we go
		for( int j = 0; j < size; j += 3 ) {
			double atom_index = ( startatom + j ) / 3;
			double mass = mParticleMass[atom_index];
			double factor = sqrt( mass ) / norm;

			// translational
			Qi_gdof[j][0]   = factor;
			Qi_gdof[j + 1][1] = factor;
			Qi_gdof[j + 2][2] = factor;

			// rotational
			// cross product of rotation axis and vector to center of molecule
			// x-axis (b1=1) ja3-ka2
			// y-axis (b2=1) ka1-ia3
			// z-axis (b3=1) ia2-ja1
			Vec3 diff = positions[atom_index] - pos_center;
			// x
			Qi_gdof[j + 1][3] =  diff[2] * factor;
			Qi_gdof[j + 2][3] = -diff[1] * factor;

			// y
			Qi_gdof[j][4]   = -diff[2] * factor;
			Qi_gdof[j + 2][4] =  diff[0] * factor;

			// z
			Qi_gdof[j][5]   =  diff[1] * factor;
			Qi_gdof[j + 1][5] = -diff[0] * factor;
		}

		// normalize first rotational vector
		double rotnorm = 0.0;
		for( int j = 0; j < size; j++ ) {
			rotnorm += Qi_gdof[j][3] * Qi_gdof[j][3];
		}

		rotnorm = 1.0 / sqrt( rotnorm );

		for( int j = 0; j < size; j++ ) {
			Qi_gdof[j][3] = Qi_gdof[j][3] * rotnorm;
		}

		// orthogonalize rotational vectors 2 and 3
		for( int j = 4; j < ConservedDegreesOfFreedom; j++ ) { // <-- vector we're orthogonalizing
			for( int k = 3; k < j; k++ ) { // <-- vectors we're orthognalizing against
				double dot_prod = 0.0;
				for( int l = 0; l < size; l++ ) {
					dot_prod += Qi_gdof[l][k] * Qi_gdof[l][j];
				}
				for( int l = 0; l < size; l++ ) {
					Qi_gdof[l][j] = Qi_gdof[l][j] - Qi_gdof[l][k] * dot_prod;
				}
			}

			// normalize residual vector
			double rotnorm = 0.0;
			for( int l = 0; l < size; l++ ) {
				rotnorm += Qi_gdof[l][j] * Qi_gdof[l][j];
			}

			rotnorm = 1.0 / sqrt( rotnorm );

			for( int l = 0; l < size; l++ ) {
				Qi_gdof[l][j] = Qi_gdof[l][j] * rotnorm;
			}
		}

		// orthogonalize original eigenvectors against gdof
		// number of evec that survive orthogonalization
		int curr_evec = ConservedDegreesOfFreedom;
		for( int j = 0; j < size; j++ ) { // <-- vector we're orthogonalizing
			// to match ProtoMol we only include size instead of size + cdof vectors
			// Note: for every vector that is skipped due to a low norm,
			// we add an additional vector to replace it, so we could actually
			// use all size original eigenvectors
			if( curr_evec == size ) {
				break;
			}

			// orthogonalize original eigenvectors in order from smallest magnitude
			// eigenvalue to biggest
			int col = sortedPairs.at( j ).second;

			// copy original vector to Qi_gdof -- updated in place
			for( int l = 0; l < size; l++ ) {
				Qi_gdof[l][curr_evec] = Qi[l][col];
			}

			// get dot products with previous vectors
			for( int k = 0; k < curr_evec; k++ ) { // <-- vector orthog against
				// dot product between original vector and previously
				// orthogonalized vectors
				double dot_prod = 0.0;
				for( int l = 0; l < size; l++ ) {
					dot_prod += Qi_gdof[l][k] * Qi[l][col];
				}

				// subtract from current vector -- update in place
				for( int l = 0; l < size; l++ ) {
					Qi_gdof[l][curr_evec] = Qi_gdof[l][curr_evec] - Qi_gdof[l][k] * dot_prod;
				}
			}

			//normalize residual vector
			double norm = 0.0;
			for( int l = 0; l < size; l++ ) {
				norm += Qi_gdof[l][curr_evec] * Qi_gdof[l][curr_evec];
			}

			// if norm less than 1/20th of original
			// continue on to next vector
			// we don't update curr_evec so this vector
			// will be overwritten
			if( norm < 0.05 ) {
				continue;
			}

			// scale vector
			norm = sqrt( norm );
			for( int l = 0; l < size; l++ ) {
				Qi_gdof[l][curr_evec] = Qi_gdof[l][curr_evec] / norm;
			}

			curr_evec++;
		}

		// 4. Copy eigenpairs to big array
		//    This is necessary because we have to sort them, and determine
		//    the cutoff eigenvalue for everybody.
		// we assume curr_evec <= size
		for( int j = 0; j < curr_evec; j++ ) {
			int col = sortedPairs.at( j ).second;
			eval[startatom + j] = di[col];

			// orthogonalized eigenvectors already sorted by eigenvalue
			for( int k = 0; k < size; k++ ) {
				evec[startatom + k][startatom + j] = Qi_gdof[k][j];
			}
		}
	}