void main(int argc, char *argv[]){ int t; char fname1[100], fname2[100]; int m = sprintf(fname1,"phi"); int n = sprintf(fname2,"velocities"); MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numtasks); MPI_Comm_rank(MPI_COMM_WORLD,&taskid); numworkers = numtasks - 1; allocate_memory_phasefields(MESHX); #ifdef FLUID allocate_memory_FluidVariables(MESHX,pmesh); #endif if(taskid == MASTER) { initialize_phasefields(); #ifdef FLUID initialize_velocities(MESHX); #endif mpi_distribute(MESHX); for (t = 0; t <= phi_timesteps; t++){ #ifdef FLUID gauss_siedel(); #endif if (t%save_phi == 0) { receivefrmworker(phi_old); receivefrmworker(u_old); receivefrmworker(v_old); write2file( t, MESHX, phi_old, fname1); write2file1( t, MESHX, u_old, v_old, fname2); } } }else { mpi_distribute(MESHX); for (t = 0; t <= phi_timesteps; t++){ mpiexchange(taskid, phi_old, MESHX); mpiexchange(taskid, mu_old, MESHX); boundary_mpi(taskid, phi_old, MESHX); boundary_mpi(taskid, mu_old, MESHX); laplacian(phi_old, lap_phi, MESHX); laplacian(mu_old, lap_mu, MESHX); #ifdef FLUID computeH(u_old,v_old,Hx,Hy); RHS_fn(Hx,Hy,rhs_fn,MESHX, pmesh); LHS_fn(MESHX, pmesh); boundary_pressure(taskid); gauss_siedel(); ns_solver(start, end, phi_old); update_velocities(MESHX); #endif solverloop(); phi_update(); if (t%save_phi == 0) { sendtomaster(taskid, phi_old); } } } }
//*****************************************************************************// void phi_solver(){ laplacian(phi_old, lap_phi); laplacian(mu_old, lap_mu); concentration(); #ifdef ISO isotropic_solverloop(); #endif #ifdef ANISO anisotropic_solverloop(); #endif phi_boundary(phi_new); phi_boundary(mu_new); phi_update(); }
void Bitmap::laplacian_filter(){ //laplacian mask, center is negative Mask laplacian(Laplacian); const int delta =1; BYTE* image = new BYTE[widthBytes*ih.biHeight]; for (int i = delta; i < ih.biHeight-delta; ++i) { for (int j = delta; j < ih.biWidth-delta; ++j) { int rr,gg,bb; // cout<<(int)laplacian.involution(imageData,widthBytes,1,i,j)<<' '<<(int)laplacian.involution(imageData,widthBytes,2,i,j)<<' '<<(int)laplacian.involution(imageData,widthBytes,3,i,j)<<endl; rr=imageData[i*widthBytes+j*3+0]-(int)laplacian.involution(imageData,widthBytes,1,i,j); gg=imageData[i*widthBytes+j*3+1]-(int)laplacian.involution(imageData,widthBytes,2,i,j); bb=imageData[i*widthBytes+j*3+2]-(int)laplacian.involution(imageData,widthBytes,3,i,j); if (rr>255) image[i*widthBytes+j*3+0]=255; else if (rr<0) image[i*widthBytes+j*3+0]=0; else image[i*widthBytes+j*3+0]=rr; if (gg>255) image[i*widthBytes+j*3+1]=255; else if (gg<0) image[i*widthBytes+j*3+1]=0; else image[i*widthBytes+j*3+1]=gg; if (bb>255) image[i*widthBytes+j*3+2]=255; else if (bb<0) image[i*widthBytes+j*3+2]=0; else image[i*widthBytes+j*3+2]=bb; } } delete[] imageData; imageData = image; }
template <int dim, typename T> void update(grid<dim,T>& oldGrid, int steps) { int rank=0; #ifdef MPI_VERSION rank = MPI::COMM_WORLD.Get_rank(); #endif ghostswap(oldGrid); grid<dim,T> newGrid(oldGrid); T r = 1.0; T u = 1.0; T K = 1.0; T M = 1.0; T dt = 0.01; T kT = 0.01; T dV = 1.0; for (int step=0; step<steps; step++) { if (rank==0) print_progress(step, steps); for (int i=0; i<nodes(oldGrid); i++) { T phi = oldGrid(i); T noise = gaussian(0.0,sqrt(2.0*kT/(dt*dV))); newGrid(i) = phi-dt*M*(-r*phi+u*pow(phi,3)-K*laplacian(oldGrid,i)+noise); } swap(oldGrid,newGrid); ghostswap(oldGrid); } }
template <int dim> void update(MMSP::grid<dim,vector<double> >& grid, int steps) { MMSP::grid<dim,vector<double> > update(grid); double dt = 0.01; for (int step=0; step<steps; step++) { for (int i=0; i<nodes(grid); i++) { // compute laplacians vector<double> lap = laplacian(grid,i); // compute sums of squares double sum = 0.0; for (int j=0; j<fields(grid); j++) { double phi = grid(i)[j]; sum += phi*phi; } // compute update values for (int j=0; j<fields(grid); j++) { double phi = grid(i)[j]; // particles have zero mobility if (j==0) update(i)[j] = phi; else update(i)[j] = phi-dt*(-phi-pow(phi,3)+2.0*(phi*sum-lap[j])); } } swap(grid,update); ghostswap(grid); } }
template <int dim> void update(MMSP::grid<dim,sparse<double> >& grid, int steps) { double dt = 0.01; double epsilon = 1.0e-8; for (int step=0; step<steps; step++) { // update grid must be overwritten each time MMSP::grid<dim,sparse<double> > update(grid); for (int i=0; i<nodes(grid); i++) { vector<int> x = position(grid,i); // determine nonzero fields within // the neighborhood of this node sparse<bool> neighbors; for (int j=0; j<dim; j++) for (int k=-1; k<=1; k++) { x[j] += k; for (int h=0; h<length(grid(x)); h++) { int index = MMSP::index(grid(x),h); set(neighbors,index) = 1; } x[j] -= k; } // if there is only one nonzero field, // then it remains the same if (length(neighbors)<2) update(i) = grid(i); else { // compute laplacians sparse<double> lap = laplacian(grid,i); // compute sums of squares double sum = 0.0; for (int j=0; j<length(grid(i)); j++) { double phi = MMSP::value(grid(i),j); sum += phi*phi; } // compute update values for (int j=0; j<length(neighbors); j++) { int index = MMSP::index(neighbors,j); double phi = grid(i)[index]; // particles have zero mobility if (index==0) set(update(i),index) = phi; else { double value = phi-dt*(-phi-pow(phi,3)+2.0*(phi*sum-lap[index])); if (value>epsilon) set(update(i),index) = value; } } } } swap(grid,update); ghostswap(grid); } }
static void perform_one_iteration(float *x, float *dat, int *mask, int nmask, int w, int h, float tstep) { for (int p = 0; p < nmask; p++) { int i = mask[2*p+0]; int j = mask[2*p+1]; int idx = j*w + i; x[idx] += tstep * (laplacian(x, w, h, i, j) - dat[idx]); } }
void computeH(double *u, double *v,double *hx, double *hy){ int i,j,z,x; double du_dx,du_dy,dv_dx,dv_dy,du_dt,dv_dt; double lap_u[MESHX2], lap_v[MESHX2]; V_str(MESHX); laplacian(u_str,lap_u, MESHX); laplacian(v_str,lap_v, MESHX); for(i=1; i<MESHX-1; i++){ for(j=1; j<MESHX-1; j++){ z = i*MESHX +j; du_dx = 0.5*inv_deltax*(u_str[z+1] - u_str[z-1]); du_dy = 0.5*inv_deltax*(u_str[z+MESHX] - u_str[z-MESHX]); dv_dx = 0.5*inv_deltax*(v_str[z+1] - v_str[z-1]); dv_dy = 0.5*inv_deltax*(v_str[z+MESHX] - v_str[z-MESHX]); hx[z] = inv_Re*lap_u[z] - (u_old[z]*du_dx + v_old[z]*du_dy); hy[z] = inv_Re*lap_v[z] - (u_old[z]*dv_dx + v_old[z]*dv_dy); } } }
void main() { long i, j, index, index_left, index_back, t; double div_flux; initialize(phi, mu, V); boundary( phi, mu, V); write2file(phi, mu, V, 0); for (t=0; t < ntimesteps; t++) { if (t%5==0) { printf("Iteration=%ld\n", t); } Gauss_siedel(phi, mu, V); //Finding the update in phi laplacian(phi, lap_phi); for (i=0; i < (MESHX); i++) { for (j=0; j < (MESHY); j++) { index = i*MESHY + j; deltaphi[index] = (deltat/(tau*epsilon)) *(2.0*(gamma*epsilon)*lap_phi[index] - 18.0*(gamma/epsilon)*(phi[index]*(1.0-phi[index])*(1.0-2.0*phi[index])) + (mu[index]-mu_eq)*6.0*(phi[index]*(1.0-phi[index]))); } } //Ending update of phi //Finding update in mu calculate_Ddcdmu(phi, mu, Ddcdmu); calculate_flux(phi, mu, V, grad_flux, Ddcdmu); for (i=1; i < (MESHX-1); i++) { for (j=1; j < (MESHY-1); j++) { index = i*MESHY + j; index_left = index - 1; index_back = index - MESHY; div_flux = (grad_flux[index][Y] - grad_flux[index_left][Y])*inv_deltay2; div_flux += (grad_flux[index][X] - grad_flux[index_back][X])*inv_deltax2; deltamu[index] = (deltat*div_flux - dc_dphi(phi[index], mu[index])*(deltaphi[index]))/dc_dmu(phi[index],mu[index]); } } //update in mu update(phi, mu); if(t%saveT==0) { write2file(phi, mu, V, t); } } }
/* * This routine is in charge of the Temperature equation. Virtually all * of the terms can be enabled or disabled by parameters read in through the * configuration file. This equation has the form: * * dT/dt = div(uT) + w hat z + del^2 T */ void calcTemp() { complex PRECISION * forces = T->force1; if(tDiff) { laplacian(T->spectral, forces, 0, 1.0); } else { memset(forces, 0, spectralCount * sizeof(complex PRECISION)); } if(tempAdvection) { //advect the background profile (as long as it is enabled) if(tempBackground) { plusEq(forces, u->vec->z->spectral); } //advect the perturbations p_vector flux = temp1; multiply(u->vec->x->spatial, T->spatial, flux->x->spatial); multiply(u->vec->y->spatial, T->spatial, flux->y->spatial); multiply(u->vec->z->spatial, T->spatial, flux->z->spatial); fftForward(flux->x); fftForward(flux->y); fftForward(flux->z); p_field advect = temp2->x; divergence(flux, advect); minusEq(forces, advect->spectral); } //Apply hyper diffusion to the boundaries if(sanitize) { killBoundaries(T->spatial, forces, 1, 100); } }
ImagePyramid<T> laplacian_pyramid(const ImagePyramid<T>& gaussians) { auto LoG = ImagePyramid<T>{}; LoG.reset(gaussians.num_octaves(), gaussians.num_scales_per_octave(), gaussians.scale_initial(), gaussians.scale_geometric_factor()); for (auto o = 0; o < LoG.num_octaves(); ++o) { LoG.octave_scaling_factor(o) = gaussians.octave_scaling_factor(o); for (auto s = 0; s < LoG.num_scales_per_octave(); ++s) { LoG(s,o) = laplacian(gaussians(s,o)); for (auto it = LoG(s, o).begin(); it != LoG(s,o).end(); ++it) *it *= pow(gaussians.scale_relative_to_octave(s), 2); } } return LoG; }
template <int dim> void update(MMSP::grid<dim,double>& grid, int steps) { MMSP::grid<dim,double> update(grid); double r = 1.0; double u = 1.0; double K = 1.0; double M = 1.0; double dt = 0.01; double kT = 0.01; double dV = 1.0; for (int step=0; step<steps; step++) { for (int i=0; i<nodes(grid); i++) { double phi = grid(i); double noise = gaussian(0.0,sqrt(2.0*kT/(dt*dV))); update(i) = phi-dt*M*(-r*phi+u*pow(phi,3)-K*laplacian(grid,i)+noise); } swap(grid,update); ghostswap(grid); } }
unsigned long update_old(MMSP::grid<dim, sparse<float> >& grid, int steps, int nthreads) { #if (!defined MPI_VERSION) && ((defined CCNI) || (defined BGQ)) std::cerr<<"Error: MPI is required for CCNI."<<std::endl; exit(1); #endif unsigned long timer=0; int rank=0; #ifdef MPI_VERSION rank=MPI::COMM_WORLD.Get_rank(); #endif const float dt = 0.01; const float width = 10.0; const float gamma = 1.0; const float eps = 4.0 / acos(-1.0) * sqrt(0.5 * gamma * width); const float w = 4.0 * gamma / width; const float mu = 1.0; const float epsilon = 1.0e-8; #ifndef SILENT static int iterations = 1; #ifdef DEBUG if (iterations==1 && rank==0) printf("CFL condition Co=%2.2f.\n", mu*eps*eps*dt/(dx(grid, 0)*dx(grid,0))); #endif #endif #ifndef SILENT if (rank==0) print_progress(0, steps, iterations); #endif for (int step = 0; step < steps; step++) { // update grid must be overwritten each time MMSP::grid<dim, sparse<float> > update(grid); ghostswap(grid); unsigned long comp_time=rdtsc(); for (int i = 0; i < nodes(grid); i++) { vector<int> x = position(grid, i); // determine nonzero fields within // the neighborhood of this node // (2 adjacent voxels along each cardinal direction) sparse<int> s; for (int j = 0; j < dim; j++) for (int k = -1; k <= 1; k++) { x[j] += k; for (int h = 0; h < length(grid(x)); h++) { int index = MMSP::index(grid(x), h); set(s, index) = 1; } x[j] -= k; } float S = float(length(s)); // if only one field is nonzero, // then copy this node to update if (S < 2.0) update(i) = grid(i); else { // compute laplacian of each field sparse<float> lap = laplacian(grid, i); // compute variational derivatives sparse<float> dFdp; for (int h = 0; h < length(s); h++) { int hindex = MMSP::index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = MMSP::index(s, j); // Update dFdp_h and dFdp_j, so the inner loop can be over j>h instead of j≠h set(dFdp, hindex) += 0.5 * eps * eps * lap[jindex] + w * grid(i)[jindex]; set(dFdp, jindex) += 0.5 * eps * eps * lap[hindex] + w * grid(i)[hindex]; } } // compute time derivatives sparse<float> dpdt; for (int h = 0; h < length(s); h++) { int hindex = MMSP::index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = MMSP::index(s, j); set(dpdt, hindex) -= mu * (dFdp[hindex] - dFdp[jindex]); set(dpdt, jindex) -= mu * (dFdp[jindex] - dFdp[hindex]); } } // compute update values float sum = 0.0; for (int h = 0; h < length(s); h++) { int index = MMSP::index(s, h); float value = grid(i)[index] + dt * (2.0 / S) * dpdt[index]; // Extraneous factor of 2? if (value > 1.0) value = 1.0; if (value < 0.0) value = 0.0; if (value > epsilon) set(update(i), index) = value; sum += update(i)[index]; } // project onto Gibbs simplex (enforce Σφ=1) float rsum = 0.0; if (fabs(sum) > 0.0) rsum = 1.0 / sum; for (int h = 0; h < length(update(i)); h++) { int index = MMSP::index(update(i), h); set(update(i), index) *= rsum; } } } // Loop over nodes(grid) swap(grid, update); comp_time=rdtsc()-comp_time; timer+=comp_time; #ifndef SILENT if (rank==0) print_progress(step+1, steps, iterations); #endif } // Loop over steps ghostswap(grid); #ifndef SILENT ++iterations; #endif return timer; }
void* update_threads_helper( void * s ) { update_thread_para<dim>* ss = ( update_thread_para<dim>* ) s ; const float dt = 0.01; const float width = 10.0; const float gamma = 1.0; const float eps = 4.0 / acos(-1.0) * sqrt(0.5 * gamma * width); const float w = 4.0 * gamma / width; const float mu = 1.0; const float epsilon = 1.0e-8; for (unsigned int i = ss->nstart; i < ss->nend; i++) { vector<int> x = position((*ss->grid), i); // determine nonzero fields within // the neighborhood of this node // (2 adjacent voxels along each cardinal direction) sparse<int> s; for (int j = 0; j < dim; j++) for (int k = -1; k <= 1; k++) { x[j] += k; for (int h = 0; h < length((*ss->grid)(x)); h++) { int index = MMSP::index((*ss->grid)(x), h); set(s, index) = 1; } x[j] -= k; } float S = float(length(s)); // if only one field is nonzero, // then copy this node to update if (S < 2.0) (*ss->update)(i) = (*ss->grid)(i); else { // compute laplacian of each field sparse<float> lap = laplacian((*ss->grid), i); // compute variational derivatives sparse<float> dFdp; for (int h = 0; h < length(s); h++) { int hindex = MMSP::index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = MMSP::index(s, j); // Update dFdp_h and dFdp_j, so the inner loop can be over j>h instead of j≠h set(dFdp, hindex) += 0.5 * eps * eps * lap[jindex] + w * (*ss->grid)(i)[jindex]; set(dFdp, jindex) += 0.5 * eps * eps * lap[hindex] + w * (*ss->grid)(i)[hindex]; } } // compute time derivatives sparse<float> dpdt; for (int h = 0; h < length(s); h++) { int hindex = MMSP::index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = MMSP::index(s, j); set(dpdt, hindex) -= mu * (dFdp[hindex] - dFdp[jindex]); set(dpdt, jindex) -= mu * (dFdp[jindex] - dFdp[hindex]); } } // compute update values float sum = 0.0; for (int h = 0; h < length(s); h++) { int index = MMSP::index(s, h); float value = (*ss->grid)(i)[index] + dt * (2.0 / S) * dpdt[index]; // Extraneous factor of 2? if (value > 1.0) value = 1.0; if (value < 0.0) value = 0.0; if (value > epsilon) set((*ss->update)(i), index) = value; sum += (*ss->update)(i)[index]; } // project onto Gibbs simplex (enforce Σφ=1) float rsum = 0.0; if (fabs(sum) > 0.0) rsum = 1.0 / sum; for (int h = 0; h < length((*ss->update)(i)); h++) { int index = MMSP::index((*ss->update)(i), h); set((*ss->update)(i), index) *= rsum; } } } // Loop over nodes(grid) pthread_exit(0); return NULL; }
int main(void) { std::string filePath = "CNN-DocTermCountMatrix.txt"; Matrix& X_Ori = loadMatrix(filePath); int NSample = min(20, X_Ori.getRowDimension()); Matrix& X = X_Ori.getSubMatrix(0, NSample - 1, 0, X_Ori.getColumnDimension() - 1); // disp(X.getSubMatrix(0, 10, 0, 100)); println(sprintf("%d samples loaded", X.getRowDimension())); GraphOptions& options = *new GraphOptions(); options.graphType = "nn"; std::string type = options.graphType; double NN = options.graphParam; fprintf("Graph type: %s with NN: %d\n", type.c_str(), (int)NN); // Parameter setting for text data options.kernelType = "cosine"; options.graphDistanceFunction = "cosine"; // Parameter setting for image data /*options.kernelType = "rbf"; options.graphDistanceFunction = "euclidean";*/ options.graphNormalize = true; options.graphWeightType = "heat"; bool show = true && !false; // Test adjacency function - pass tic(); std::string DISTANCEFUNCTION = options.graphDistanceFunction; Matrix& A = adjacency(X, type, NN, DISTANCEFUNCTION); fprintf("Elapsed time: %.2f seconds.\n", toc()); std::string adjacencyFilePath = "adjacency.txt"; saveMatrix(adjacencyFilePath, A); if (show) disp(A.getSubMatrix(0, 4, 0, 4)); // Test laplacian function - pass tic(); Matrix& L = laplacian(X, type, options); fprintf("Elapsed time: %.2f seconds.\n", toc()); std::string LaplacianFilePath = "Laplacian.txt"; saveMatrix(LaplacianFilePath, L); if (show) disp(L.getSubMatrix(0, 4, 0, 4)); // Test local learning regularization - pass NN = options.graphParam; std::string DISTFUNC = options.graphDistanceFunction; std::string KernelType = options.kernelType; double KernelParam = options.kernelParam; double lambda = 0.001; tic(); Matrix& LLR_text = calcLLR(X, NN, DISTFUNC, KernelType, KernelParam, lambda); fprintf("Elapsed time: %.2f seconds.\n", toc()); std::string LLRFilePath = "localLearningRegularization.txt"; saveMatrix(LLRFilePath, LLR_text); if (show) display(LLR_text.getSubMatrix(0, 4, 0, 4)); return EXIT_SUCCESS; }
inline fvMatrixHolder< Type > laplacian( const dimensioned< GType >& ds, GeometricFieldHolder< Type, fvPatchField, volMesh >& field, const word& name ) { return fvMatrixHolder< Type >( laplacian( ds, field(), name ), Deps( &field ) ); }
template <int dim> void update(grid<dim, sparse<phi_type> >& oldGrid, int steps) { int rank=0; #ifdef MPI_VERSION rank=MPI::COMM_WORLD.Get_rank(); #endif const phi_type dt = 0.01; const phi_type width = 14.5; const phi_type epsilon = 1.0e-8; const double mu_hi = 1.00; const double mu_lo = 0.01; const double mu_x = 0.6422; const double mu_s = 0.0175; std::ofstream vfile; if (rank==0) vfile.open("v.log",std::ofstream::out | std::ofstream::app); for (int step = 0; step < steps; step++) { if (rank==0) print_progress(step, steps); // newGrid grid must be overwritten each time ghostswap(oldGrid); grid<dim, sparse<phi_type> > newGrid(oldGrid); for (int d=0; d<dim; d++) { if (x0(oldGrid, d) == g0(oldGrid,d)) { b0(oldGrid,d) = Dirichlet; b0(newGrid,d) = Dirichlet; } else if (x1(oldGrid,d) == g1(oldGrid,d)) { b1(oldGrid,d) = Dirichlet; b1(newGrid,d) = Dirichlet; } } for (int i = 0; i < nodes(oldGrid); i++) { vector<int> x = position(oldGrid, i); // determine nonzero fields within // the neighborhood of this node // (2 adjacent voxels along each cardinal direction) sparse<int> s; for (int j = 0; j < dim; j++) for (int k = -1; k <= 1; k++) { x[j] += k; for (int h = 0; h < length(oldGrid(x)); h++) { int pindex = index(oldGrid(x), h); set(s, pindex) = 1; } x[j] -= k; } phi_type S = phi_type(length(s)); // if only one field is nonzero, // then copy this node to newGrid if (S < 2.0) newGrid(i) = oldGrid(i); else { // compute laplacian of each field sparse<phi_type> lap = laplacian(oldGrid, i); // compute variational derivatives sparse<phi_type> dFdp; for (int h = 0; h < length(s); h++) { int hindex = index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = index(s, j); phi_type gamma = energy(hindex, jindex); phi_type eps = 4.0 / acos(-1.0) * sqrt(0.5 * gamma * width); phi_type w = 4.0 * gamma / width; // Update dFdp_h and dFdp_j, so the inner loop can be over j>h instead of j≠h set(dFdp, hindex) += 0.5 * eps * eps * lap[jindex] + w * oldGrid(i)[jindex]; set(dFdp, jindex) += 0.5 * eps * eps * lap[hindex] + w * oldGrid(i)[hindex]; } } // compute time derivatives sparse<phi_type> dpdt; phi_type mu = mobility(mu_lo, mu_hi, mu_x, mu_s, oldGrid(x).getMagPhi()); for (int h = 0; h < length(s); h++) { int hindex = index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = index(s, j); set(dpdt, hindex) -= mu * (dFdp[hindex] - dFdp[jindex]); set(dpdt, jindex) -= mu * (dFdp[jindex] - dFdp[hindex]); } } // compute update values phi_type sum = 0.0; for (int h = 0; h < length(s); h++) { int pindex = index(s, h); phi_type value = oldGrid(i)[pindex] + dt * (2.0 / S) * dpdt[pindex]; // Extraneous factor of 2? if (value > 1.0) value = 1.0; if (value < 0.0) value = 0.0; if (value > epsilon) set(newGrid(i), pindex) = value; sum += newGrid(i)[pindex]; } // project onto Gibbs simplex (enforce Σφ=1) phi_type rsum = 0.0; if (fabs(sum) > 0.0) rsum = 1.0 / sum; for (int h = 0; h < length(newGrid(i)); h++) { int pindex = index(newGrid(i), h); set(newGrid(i), pindex) *= rsum; } } } // Loop over nodes(oldGrid) if ((step+1) % 10 == 0) { // Scan along just above the mid-line for the grain boundary. // When found, determine its angle. vector<int> x(dim, 0); const int offset = 2; const phi_type vert_mag = 1.0/std::sqrt(3.0); const phi_type edge_mag = 1.0/std::sqrt(2.0); const phi_type bulk_mag = 1.0; const phi_type edge_contour = edge_mag + 0.125*(bulk_mag - edge_mag); const phi_type vert_contour = vert_mag + 0.125*(edge_mag - vert_mag); x[0] = x0(newGrid,0); x[1] = (g1(newGrid,1) - g0(newGrid,1))/2; while (x[0]<x1(newGrid) && x[1]>=y0(newGrid) && x[1]<y1(newGrid) && newGrid(x).getMagPhi()>vert_contour) x[0]++; if (x[0] == x1(newGrid)) x[0] = g0(newGrid,0); int v0 = x[0]; #ifdef MPI_VERSION MPI::COMM_WORLD.Allreduce(&x[0], &v0, 1, MPI_INT, MPI_MAX); #endif x[1] += offset; while (x[0]>= x0(newGrid) && x[0]<x1(newGrid) && x[1]>=y0(newGrid) && x[1]<y1(newGrid) && newGrid(x).getMagPhi()>edge_contour) x[0]++; if (x[0] == x1(newGrid)) x[0] = g0(newGrid,0); int v1 = x[0]; #ifdef MPI_VERSION MPI::COMM_WORLD.Allreduce(&x[0], &v1, 1, MPI_INT, MPI_MAX); #endif x[1] += offset; while (x[0]>= x0(newGrid) && x[0]<x1(newGrid) && x[1]>=y0(newGrid) && x[1]<y1(newGrid) && newGrid(x).getMagPhi()>edge_contour) x[0]++; if (x[0] == x1(newGrid)) x[0] = g0(newGrid,0); int v2 = x[0]; #ifdef MPI_VERSION MPI::COMM_WORLD.Allreduce(&x[0], &v2, 1, MPI_INT, MPI_MAX); #endif // Second-order right-sided difference to approximate slope double diffX = 3.0*v0 - 4.0*v1 + 1.0*v2; double theta = 180.0/M_PI * std::atan2(2.0*offset*dx(newGrid,1), dx(newGrid,0)*diffX); if (rank==0) vfile << dx(newGrid,0)*v0 << '\t' << dx(newGrid,0)*v1 << '\t' << dx(newGrid,0)*v2 << '\t' << diffX << '\t' << theta << '\n'; } swap(oldGrid, newGrid); } // Loop over steps ghostswap(oldGrid); if (rank==0) vfile.close(); }
/* * This routine is in charge of the magnetic induction equation. Virtually all * of the terms can be enabled or disabled by parameters read in through the * configuration file. This equation has the form: * * dB/dt = curl(u cross B) + Pm/Pr*del^2 B + F_B * * Again we have an incompressible field, so after evaluating the force in * vector notation, we decompose it into poloidal and toroidal scalar fields for * the time integration. */ void calcMag() { int i,j,k; int index; debug("Calculating Magnetic forces\n"); if(magDiff) { laplacian(B->vec->x->spectral, rhs->x->spectral, 0, Pr/Pm); laplacian(B->vec->y->spectral, rhs->y->spectral, 0, Pr/Pm); laplacian(B->vec->z->spectral, rhs->z->spectral, 0, Pr/Pm); } else { //make sure we don't start with garbage memset(rhs->x->spectral, 0, spectralCount * sizeof(complex PRECISION)); memset(rhs->y->spectral, 0, spectralCount * sizeof(complex PRECISION)); memset(rhs->z->spectral, 0, spectralCount * sizeof(complex PRECISION)); } //Apply hyper diffusion to the boundaries. Again, this does not currently //work! if(sanitize) { killBoundaries(B->vec->x->spatial, rhs->x->spectral, 1, 100*Pr/Pm); killBoundaries(B->vec->y->spatial, rhs->y->spectral, 1, 100*Pr/Pm); killBoundaries(B->vec->z->spatial, rhs->z->spectral, 1, 100*Pr/Pm); } //static forcing is currently only in the x direction and a function of y and z if(magStaticForcing) { complex PRECISION * xfield = rhs->x->spectral; complex PRECISION * ffield = magForceField->spectral; index = 0; for(i = 0; i < spectralCount; i++) { xfield[i] += ffield[i]; } } //If we are doing the kinematic problem then the velocity field is //specified ahead of time. Note, this conflicts with the momentum equation //being enabled. If both momentum equation and kinematic are enabled, then //we will still be doing all the work of both, but right here we will erase //any work previously done on the momentum equation, at least insofar as //the magnetic field is concerned. if(kinematic) { fillTimeField(u->vec, KINEMATIC); } //This is really the induction term, not advection, though it does contain //advection effects within it. if(magAdvect) { p_vector uxb = temp1; p_vector cuxb = temp2; crossProduct(u->vec, B->vec, uxb); fftForward(uxb->x); fftForward(uxb->y); fftForward(uxb->z); curl(uxb, cuxb); plusEq(rhs->x->spectral, cuxb->x->spectral); plusEq(rhs->y->spectral, cuxb->y->spectral); plusEq(rhs->z->spectral, cuxb->z->spectral); } if(magTimeForcing) { fillTimeField(temp1, MAGNETIC); plusEq(rhs->x->spectral, temp1->x->spectral); plusEq(rhs->y->spectral, temp1->y->spectral); plusEq(rhs->z->spectral, temp1->z->spectral); } //The 1 means we store the result in the force vectors. decomposeSolenoidal(B->sol, rhs, 1); debug("Magnetic forces done\n"); }
template <int dim> void update(MMSP::grid<dim,sparse<double> >& grid, int steps) { double dt = 0.01; double width = 8.0; for (int step=0; step<steps; step++) { print_progress(step, steps); // update grid must be overwritten each time MMSP::grid<dim,sparse<double> > update(grid); #ifndef MPI_VERSION #pragma omp parallel for #endif for (int n=0; n<nodes(grid); n++) { vector<int> x = position(grid,n); // compute laplacian of each field sparse<double> lapPhi = laplacian(grid,n); double S = double(length(lapPhi)); // if only one field is nonzero, // then copy this node to update if (S<2.0) update(x) = grid(n); else { // compute variational derivatives sparse<double> dFdp; for (int h=0; h<length(lapPhi); h++) { int hindex = MMSP::index(lapPhi,h); double phii = grid(n)[hindex]; for (int j=h+1; j<length(lapPhi); j++) { int jindex = MMSP::index(lapPhi,j); double phij = grid(n)[jindex]; double gamma = energy(hindex,jindex); double eps = 4.0/acos(-1.0)*sqrt(0.5*gamma*width); double w = 4.0*gamma/width; set(dFdp,hindex) += 0.5*eps*eps*lapPhi[jindex]+w*phij; set(dFdp,jindex) += 0.5*eps*eps*lapPhi[hindex]+w*phii; for (int k=j+1; k<length(lapPhi); k++) { int kindex = MMSP::index(lapPhi,k); double phik = grid(n)[kindex]; set(dFdp,hindex) += 3.0*phij*phik; set(dFdp,jindex) += 3.0*phii*phik; set(dFdp,kindex) += 3.0*phii*phij; } } } // compute time derivatives sparse<double> dpdt; for (int h=0; h<length(lapPhi); h++) { int hindex = MMSP::index(lapPhi,h); for (int j=h+1; j<length(lapPhi); j++) { int jindex = MMSP::index(lapPhi,j); double mu = mobility(hindex,jindex); set(dpdt,hindex) -= mu*(dFdp[hindex]-dFdp[jindex]); set(dpdt,jindex) -= mu*(dFdp[jindex]-dFdp[hindex]); } } // compute update values double sum = 0.0; for (int h=0; h<length(dpdt); h++) { int index = MMSP::index(dpdt,h); double value = grid(n)[index]+dt*(2.0/S)*dpdt[index]; if (value>1.0) value = 1.0; if (value<0.0) value = 0.0; if (value>machine_epsilon) set(update(x),index) = value; sum += update(x)[index]; } // project onto Gibbs simplex double rsum = (fabs(sum)>machine_epsilon)?1.0/sum:0.0; for (int h=0; h<length(update(x)); h++) { int index = MMSP::index(update(x),h); set(update(x),index) *= rsum; } } } swap(grid,update); ghostswap(grid); } MMSP::sparse<double> mass; for (int n=0; n<nodes(grid); n++) for (int l=0; l<length(grid(n)); l++) { int index = grid(n).index(l); set(mass,index) += grid(n)[index]; } for (int l=0; l<length(mass); l++) std::cout<<mass.value(l)<<'\t'; std::cout<<std::endl; }
int main(int argc, char *argv[]) { int ix, iz, it, itau; int nx, nz, ntau, nt, pad; float dt, dtau, dx, dz, dt2, idz2, idx2; float tau0, tau; float ***dd, ***mm, **vv, **v0; float **u0, **u1, **u2, **ud, **tmp; sf_axis ax, az, atau; sf_file tgather, cgather, vel; sf_init(argc, argv); tgather=sf_input("in"); cgather=sf_output("out"); vel=sf_input("velocity"); az=sf_iaxa(tgather, 1); ax=sf_iaxa(tgather, 2); atau=sf_iaxa(tgather, 3); nz=sf_n(az); dz=sf_d(az); nx=sf_n(ax); dx=sf_d(ax); ntau=sf_n(atau); dtau=sf_d(atau); tau0=sf_o(atau); if(!sf_getfloat("dt", &dt)) dt=0.001; if(!sf_getint("pad", &pad)) pad=30; padnx=nx+2*pad; padnz=nz+2*pad; idz2=1.0/(dz*dz); idx2=1.0/(dx*dx); c11=4.0*idz2/3.0; c12=-idz2/12.0; c21=4.0*idx2/3.0; c22=-idx2/12.0; c0=-2.0*(c11+c12+c21+c22); dd=sf_floatalloc3(nz, nx, ntau); mm=sf_floatalloc3(nz, nx, ntau); vv=sf_floatalloc2(nz, nx); v0=sf_floatalloc2(padnz, padnx); padvv=sf_floatalloc2(padnz, padnx); u0=sf_floatalloc2(padnz, padnx); u1=sf_floatalloc2(padnz, padnx); u2=sf_floatalloc2(padnz, padnx); ud=sf_floatalloc2(padnz, padnx); sf_floatread(dd[0][0], ntau*nx*nz, tgather); sf_floatread(vv[0], nx*nz, vel); dt2=dt*dt; for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) padvv[ix+pad][iz+pad]=vv[ix][iz]*vv[ix][iz]*dt2; for(iz=0; iz<pad; iz++) for(ix=pad; ix<nx+pad; ix++){ padvv[ix][iz]=padvv[ix][pad]; padvv[ix][pad+nz+iz]=padvv[ix][pad+nz-1]; } for(ix=0; ix<pad; ix++) for(iz=0; iz<padnz; iz++){ padvv[ix][iz]=padvv[pad][iz]; padvv[ix+pad+nx][iz]=padvv[pad+nx-1][iz]; } for(itau=0; itau<ntau; itau++){ sf_warning("itau=%d/%d", itau+1, ntau); zero2(u0, padnz, padnx); zero2(u1, padnz, padnx); zero2(u2, padnz, padnx); zero2(ud, padnz, padnx); zero2(v0, padnz, padnx); tau=tau0+itau*dtau; // tau=0 if(tau==0.){ for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) mm[itau][ix][iz]=dd[itau][ix][iz]; continue; } // calculate v0 (derivative with respect to tau) if(itau==0){ for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+pad][iz+pad]=(dd[1][ix][iz]-dd[0][ix][iz])/dtau; } } } else if (itau==ntau-1){ for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+pad][iz+pad]=(dd[ntau-1][ix][iz]-dd[ntau-2][ix][iz])/dtau; } } } else { #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+pad][iz+pad]=(dd[itau+1][ix][iz]-dd[itau-1][ix][iz])/dtau/2.0; } } } // calculate u1 #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) u1[ix+pad][iz+pad]=dd[itau][ix][iz]; // tau>0 if(tau>0.){ laplacian(u1, ud); #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<padnx; ix++){ for(iz=0; iz<padnz; iz++){ u0[ix][iz]=u1[ix][iz]+ud[ix][iz]/2.0-v0[ix][iz]*dt; } } nt=tau/dt+0.5; for(it=1; it<nt; it++){ sf_warning("it=%d/%d;", it+1, nt); tmp=u2; u2=u1; u1=u0; u0=tmp; laplacian(u1, ud); #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<padnx; ix++){ for(iz=0; iz<padnz; iz++){ u0[ix][iz]=2*u1[ix][iz]-u2[ix][iz]+ud[ix][iz]; } } } //end of it #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ mm[itau][ix][iz]=u0[ix+pad][iz+pad]; } } } // tau<0 if(tau<0.){ laplacian(u1, ud); #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<padnx; ix++){ for(iz=0; iz<padnz; iz++){ u2[ix][iz]=u1[ix][iz]+dt*v0[ix][iz]+ud[ix][iz]/2.0; } } nt=-tau/dt+0.5; for(it=1; it<nt; it++){ sf_warning("it=%d/%d;", it+1, nt); tmp=u0; u0=u1; u1=u2; u2=tmp; laplacian(u1, ud); #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<padnx; ix++){ for(iz=0; iz<padnz; iz++){ u2[ix][iz]=2*u1[ix][iz]-u0[ix][iz]+ud[ix][iz]; } } }//end of it #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ mm[itau][ix][iz]=u2[ix+pad][iz+pad]; } } } } //end of itau sf_floatwrite(mm[0][0], ntau*nx*nz, cgather); exit(0); }
int main(int argc, char* argv[]) { int it,i1,i2; /* index variables */ int nt,n12,ft,jt; float dt,d1,d2,dt2; float *ww,**vv,**rr; float **u0,**u1,**u2,**ud; sf_file Fw,Fv,Fr,Fo; /* I/O files */ /* initialize Madagascar */ sf_init(argc,argv); /* initialize OpenMP support */ omp_init(); /* setup I/O files */ Fr = sf_input ("in"); /* source position */ Fo = sf_output("out"); /* output wavefield */ Fw = sf_input ("wav"); /* source wavelet */ Fv = sf_input ("v"); /* velocity */ /* Read/Write axes */ if (!sf_histint(Fr,"n1",&n1)) sf_error("No n1= in inp"); if (!sf_histint(Fr,"n2",&n2)) sf_error("No n2= in inp"); if (!sf_histfloat(Fr,"d1",&d1)) sf_error("No d1= in inp"); if (!sf_histfloat(Fr,"d2",&d2)) sf_error("No d2= in inp"); if (!sf_histint(Fw,"n1",&nt)) sf_error("No n1= in wav"); if (!sf_histfloat(Fw,"d1",&dt)) sf_error("No d1= in wav"); n12 = n1*n2; if (!sf_getint("ft",&ft)) ft=0; /* first recorded time */ if (!sf_getint("jt",&jt)) jt=1; /* time interval */ sf_putint(Fo,"n3",(nt-ft)/jt); sf_putfloat(Fo,"d3",jt*dt); sf_putfloat(Fo,"o3",ft*dt); dt2 = dt*dt; /* set Laplacian coefficients */ d1 = 1.0/(d1*d1); d2 = 1.0/(d2*d2); c11 = 4.0*d1/3.0; c12= -d1/12.0; c21 = 4.0*d2/3.0; c22= -d2/12.0; c0 = -2.0 * (c11+c12+c21+c22); /* read wavelet, velocity & source position */ ww=sf_floatalloc(nt); sf_floatread(ww ,nt ,Fw); vv=sf_floatalloc2(n1,n2); sf_floatread(vv[0],n12,Fv); rr=sf_floatalloc2(n1,n2); sf_floatread(rr[0],n12,Fr); /* allocate temporary arrays */ u0=sf_floatalloc2(n1,n2); u1=sf_floatalloc2(n1,n2); u2=sf_floatalloc2(n1,n2); ud=sf_floatalloc2(n1,n2); for (i2=0; i2<n2; i2++) { for (i1=0; i1<n1; i1++) { u0[i2][i1]=0.0; u1[i2][i1]=0.0; u2[i2][i1]=0.0; ud[i2][i1]=0.0; vv[i2][i1] *= vv[i2][i1]*dt2; } } /* Time loop */ for (it=0; it<nt; it++) { laplacian(u1,ud); #ifdef _OPENMP #pragma omp parallel for \ private(i2,i1) \ shared(ud,vv,ww,it,rr,u2,u1,u0) #endif for (i2=0; i2<n2; i2++) { for (i1=0; i1<n1; i1++) { /* scale by velocity */ ud[i2][i1] *= vv[i2][i1]; /* inject wavelet */ ud[i2][i1] += ww[it] * rr[i2][i1]; /* time step */ u2[i2][i1] = 2*u1[i2][i1] - u0[i2][i1] + ud[i2][i1]; u0[i2][i1] = u1[i2][i1]; u1[i2][i1] = u2[i2][i1]; } } /* write wavefield to output */ if (it >= ft && 0 == (it-ft)%jt) { sf_warning("%d;",it+1); sf_floatwrite(u1[0],n12,Fo); } } sf_warning("."); exit (0); }
int main(int argc, char *argv[]) { int step, ie, iside, i, j, k; double mflops, tmax, nelt_tot = 0.0; char Class; logical ifmortar = false, verified; double t2, trecs[t_last+1]; char *t_names[t_last+1]; //-------------------------------------------------------------------- // Initialize NUMA control //-------------------------------------------------------------------- numa_initialize_env(NUMA_MIGRATE_EXISTING); //--------------------------------------------------------------------- // Read input file (if it exists), else take // defaults from parameters //--------------------------------------------------------------------- FILE *fp; if ((fp = fopen("timer.flag", "r")) != NULL) { timeron = true; t_names[t_total] = "total"; t_names[t_init] = "init"; t_names[t_convect] = "convect"; t_names[t_transfb_c] = "transfb_c"; t_names[t_diffusion] = "diffusion"; t_names[t_transf] = "transf"; t_names[t_transfb] = "transfb"; t_names[t_adaptation] = "adaptation"; t_names[t_transf2] = "transf+b"; t_names[t_add2] = "add2"; fclose(fp); } else { timeron = false; } printf("\n\n NAS Parallel Benchmarks (NPB3.3-OMP-C) - UA Benchmark\n\n"); if ((fp = fopen("inputua.data", "r")) != NULL) { int result; printf(" Reading from input file inputua.data\n"); result = fscanf(fp, "%d", &fre); while (fgetc(fp) != '\n'); result = fscanf(fp, "%d", &niter); while (fgetc(fp) != '\n'); result = fscanf(fp, "%d", &nmxh); while (fgetc(fp) != '\n'); result = fscanf(fp, "%lf", &alpha); Class = 'U'; fclose(fp); } else { printf(" No input file inputua.data. Using compiled defaults\n"); fre = FRE_DEFAULT; niter = NITER_DEFAULT; nmxh = NMXH_DEFAULT; alpha = ALPHA_DEFAULT; Class = CLASS_DEFAULT; } dlmin = pow(0.5, REFINE_MAX); dtime = 0.04*dlmin; printf(" Levels of refinement: %8d\n", REFINE_MAX); printf(" Adaptation frequency: %8d\n", fre); printf(" Time steps: %8d dt: %15.6E\n", niter, dtime); printf(" CG iterations: %8d\n", nmxh); printf(" Heat source radius: %8.4f\n", alpha); printf(" Number of available threads: %8d\n", omp_get_max_threads()); printf("\n"); top_constants(); for (i = 1; i <= t_last; i++) { timer_clear(i); } if (timeron) timer_start(t_init); // set up initial mesh (single element) and solution (all zero) create_initial_grid(); r_init_omp((double *)ta1, ntot, 0.0); nr_init_omp((int *)sje, 4*6*nelt, -1); init_locks(); // compute tables of coefficients and weights coef(); geom1(); // compute the discrete laplacian operators setdef(); // prepare for the preconditioner setpcmo_pre(); // refine initial mesh and do some preliminary work time = 0.0; mortar(); prepwork(); adaptation(&ifmortar, 0); if (timeron) timer_stop(t_init); timer_clear(1); time = 0.0; for (step = 0; step <= niter; step++) { if (step == 1) { // reset the solution and start the timer, keep track of total no elms r_init((double *)ta1, ntot, 0.0); time = 0.0; nelt_tot = 0.0; for (i = 1; i <= t_last; i++) { if (i != t_init) timer_clear(i); } timer_start(1); } // advance the convection step convect(ifmortar); if (timeron) timer_start(t_transf2); // prepare the intital guess for cg transf(tmort, (double *)ta1); // compute residual for diffusion term based on intital guess // compute the left hand side of equation, lapacian t #pragma omp parallel default(shared) private(ie,k,j,i) { #pragma omp for for (ie = 0; ie < nelt; ie++) { laplacian(ta2[ie], ta1[ie], size_e[ie]); } // compute the residual #pragma omp for for (ie = 0; ie < nelt; ie++) { for (k = 0; k < LX1; k++) { for (j = 0; j < LX1; j++) { for (i = 0; i < LX1; i++) { trhs[ie][k][j][i] = trhs[ie][k][j][i] - ta2[ie][k][j][i]; } } } } } //end parallel // get the residual on mortar transfb(rmor, (double *)trhs); if (timeron) timer_stop(t_transf2); // apply boundary condition: zero out the residual on domain boundaries // apply boundary conidtion to trhs #pragma omp parallel for default(shared) private(ie,iside) for (ie = 0; ie < nelt; ie++) { for (iside = 0; iside < NSIDES; iside++) { if (cbc[ie][iside] == 0) { facev(trhs[ie], iside, 0.0); } } } // apply boundary condition to rmor col2(rmor, tmmor, nmor); // call the conjugate gradient iterative solver diffusion(ifmortar); // add convection and diffusion if (timeron) timer_start(t_add2); add2((double *)ta1, (double *)t, ntot); if (timeron) timer_stop(t_add2); // perform mesh adaptation time = time + dtime; if ((step != 0) && (step/fre*fre == step)) { if (step != niter) { adaptation(&ifmortar, step); } } else { ifmortar = false; } nelt_tot = nelt_tot + (double)(nelt); } timer_stop(1); tmax = timer_read(1); verify(&Class, &verified); // compute millions of collocation points advanced per second. // diffusion: nmxh advancements, convection: 1 advancement mflops = nelt_tot*(double)(LX1*LX1*LX1*(nmxh+1))/(tmax*1.e6); print_results("UA", Class, REFINE_MAX, 0, 0, niter, tmax, mflops, " coll. point advanced", verified, NPBVERSION, COMPILETIME, CS1, CS2, CS3, CS4, CS5, CS6, "(none)"); //--------------------------------------------------------------------- // More timers //--------------------------------------------------------------------- if (timeron) { for (i = 1; i <= t_last; i++) { trecs[i] = timer_read(i); } if (tmax == 0.0) tmax = 1.0; printf(" SECTION Time (secs)\n"); for (i = 1; i <= t_last; i++) { printf(" %-10s:%9.3f (%6.2f%%)\n", t_names[i], trecs[i], trecs[i]*100./tmax); if (i == t_transfb_c) { t2 = trecs[t_convect] - trecs[t_transfb_c]; printf(" --> %11s:%9.3f (%6.2f%%)\n", "sub-convect", t2, t2*100./tmax); } else if (i == t_transfb) { t2 = trecs[t_diffusion] - trecs[t_transf] - trecs[t_transfb]; printf(" --> %11s:%9.3f (%6.2f%%)\n", "sub-diffuse", t2, t2*100./tmax); } } } //-------------------------------------------------------------------- // Teardown NUMA control //-------------------------------------------------------------------- numa_shutdown(); return 0; }
inline fvMatrixHolder< Type > laplacian( const GeometricFieldHolder< GType, fvPatchField, volMesh >& field1, GeometricFieldHolder< Type, fvPatchField, volMesh >& field2 ) { return fvMatrixHolder< Type >( laplacian( field1(), field2() ), Deps( &field1, &field2 ) ); }
int main(int argc, char* argv[]) { int i, j, k, it; //FILE *fp; //int fd; real mean; struct timeval tim; double start, end; if (argc != 5) { printf("Usage: %s <nx> <ny> <ns> <nt>\n", argv[0]); exit(1); } srand(17); parse_arg(nx, argv[1]); parse_arg(ny, argv[2]); parse_arg(ns, argv[3]); parse_arg(nt, argv[4]); real alpha = real_rand(); real beta = real_rand(); printf("alpha = %f, beta = %f\n", alpha, beta); unsigned int szarray = (unsigned int)nx * ny * ns; unsigned int szarrayb = szarray * sizeof(real); real* w0 = (real*)malloc(szarrayb); real* w1 = (real*)malloc(szarrayb); if (!w0 || !w1) { printf("Error allocating memory for arrays: %p, %p\n", w0, w1); exit(1); } for (i = 0; i < szarray; i++) { w0[i] = real_rand(); w1[i] = real_rand(); } // 1) Perform an empty offload, that should strip // the initialization time from further offloads. acc_init(acc_device_default); gettimeofday(&tim, NULL); start = tim.tv_sec + (tim.tv_usec/1000000.0); // 2) Allocate data on device, but do not copy anything. #pragma acc data create (w0[0:szarray], w1[0:szarray]) { // 3) Transfer data from host to device and leave it there, // i.e. do not allocate deivce memory buffers. #pragma acc update device(w0[0:szarray], w1[0:szarray]) // 4) Perform data processing iterations, keeping all data // on device. { for (it = 0; it < nt; it++) { laplacian(nx, ny, ns, alpha, beta, w0, w1); real* w = w0; w0 = w1; w1 = w; } } // 5) Transfer output data back from device to host. #pragma acc update host (w0[0:szarray]) } gettimeofday(&tim, NULL); end = tim.tv_sec + (tim.tv_usec/1000000.0); #if 0 fd = creat(argv[5], 00666); fd = open(argv[5], O_WRONLY); write(fd, w0, szarrayb); close(fd); fp = fopen(argv[5], "w"); fprintf(fp, "%d %d %d\n", ns, ny, nx); for(k = 0; k < ns; k++){ for (j = 0; j < ny; j++) { for (i = 0; i < nx; i++) { fprintf(fp, "%d %d %d %f\n", k, j, i, w0[k*nx*ny + j*nx + i]); } } } fclose(fp); #endif mean = 0.0f; for (i = 0; i < szarray; i++) mean += w0[i]; printf("Final mean = %f\n", mean/szarray); printf("Time for computing: %.2f s\n",end-start); free(w0); free(w1); return 0; }
/* * This routine is in charge of the momentum equation. Virtually all * of the terms can be enabled or disabled by parameters read in through the * configuration file. This equation has the form: * * du/dt = div(alpha BB - uu - P) + (Ra T + B^2 / beta) hat z + Pr del^2 u + F_u * * Since the velocity field is incompressible, the pressure term doesn't matter * and is eliminated by taking the curl of the right-hand side. This is then * decomposed into poloidal and toroidal components, which are then used in the * time integration. */ void calcMomentum() { debug("Calculating momentum forces\n"); int i,j,k; int index; if(viscosity) { //First argument is the field we take the laplacian of. //Second argument is where the result is stored. //The 0 in the third argument means we overwrite the destination array //Pr is the coefficient for this diffusion term. laplacian(u->vec->x->spectral, rhs->x->spectral, 0, Pr); laplacian(u->vec->y->spectral, rhs->y->spectral, 0, Pr); laplacian(u->vec->z->spectral, rhs->z->spectral, 0, Pr); } else { //make sure we don't start with garbage memset(rhs->x->spectral, 0, spectralCount * sizeof(complex PRECISION)); memset(rhs->y->spectral, 0, spectralCount * sizeof(complex PRECISION)); memset(rhs->z->spectral, 0, spectralCount * sizeof(complex PRECISION)); } //Apply hyper diffusion to the boundaries //This does not currently work and is disabled by default! if(sanitize) { killBoundaries(u->vec->x->spatial, rhs->x->spectral, 1, 100*Pr); killBoundaries(u->vec->y->spatial, rhs->y->spectral, 1, 100*Pr); killBoundaries(u->vec->z->spatial, rhs->z->spectral, 1, 100*Pr); } //static forcing is read in from a file and currently only in the u //direction as a function of y and z (to remove nonlinear advection) if(momStaticForcing) { complex PRECISION * xfield = rhs->x->spectral; complex PRECISION * ffield = forceField->spectral; index = 0; for(i = 0; i < spectralCount; i++) { xfield[i] += ffield[i]; } } // if(momTimeForcing) { //Evaluate the force function at the current time. fillTimeField(temp1, MOMENTUM); plusEq(rhs->x->spectral, temp1->x->spectral); plusEq(rhs->y->spectral, temp1->y->spectral); plusEq(rhs->z->spectral, temp1->z->spectral); } if(momAdvection) { p_field tense = temp1->x; //Note here, because I already forgot once. a 2 as the third //parameter makes things behave as a -= operation! multiply(u->vec->x->spatial, u->vec->x->spatial, tense->spatial); fftForward(tense); partialX(tense->spectral, rhs->x->spectral, 2); multiply(u->vec->y->spatial, u->vec->y->spatial, tense->spatial); fftForward(tense); partialY(tense->spectral, rhs->y->spectral, 2); multiply(u->vec->z->spatial, u->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, rhs->z->spectral, 2); multiply(u->vec->x->spatial, u->vec->y->spatial, tense->spatial); fftForward(tense); partialY(tense->spectral, rhs->x->spectral, 2); partialX(tense->spectral, rhs->y->spectral, 2); multiply(u->vec->x->spatial, u->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, rhs->x->spectral, 2); partialX(tense->spectral, rhs->z->spectral, 2); multiply(u->vec->y->spatial, u->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, rhs->y->spectral, 2); partialY(tense->spectral, rhs->z->spectral, 2); } if(lorentz) { p_field tense = temp1->x; p_vector lor = temp2; //The third parameter as a 0 means we overwrite the destination array. //The third parameter as a 1 means it behaves as a += operation. multiply(B->vec->x->spatial, B->vec->x->spatial, tense->spatial); fftForward(tense); partialX(tense->spectral, lor->x->spectral, 0); multiply(B->vec->y->spatial, B->vec->y->spatial, tense->spatial); fftForward(tense); partialY(tense->spectral, lor->y->spectral, 0); multiply(B->vec->z->spatial, B->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, lor->z->spectral, 0); multiply(B->vec->x->spatial, B->vec->y->spatial, tense->spatial); fftForward(tense); partialY(tense->spectral, lor->x->spectral, 1); partialX(tense->spectral, lor->y->spectral, 1); multiply(B->vec->x->spatial, B->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, lor->x->spectral, 1); partialX(tense->spectral, lor->z->spectral, 1); multiply(B->vec->y->spatial, B->vec->z->spatial, tense->spatial); fftForward(tense); partialZ(tense->spectral, lor->y->spectral, 1); partialY(tense->spectral, lor->z->spectral, 1); //TODO: Find a routine to change to include this factor complex PRECISION * px = lor->x->spectral; complex PRECISION * py = lor->y->spectral; complex PRECISION * pz = lor->z->spectral; int i; for(i = 0; i < spectralCount; i++) { px[i] *= alpha; py[i] *= alpha; pz[i] *= alpha; } plusEq(rhs->x->spectral, px); plusEq(rhs->y->spectral, py); plusEq(rhs->z->spectral, pz); } if(magBuoy) { p_field B2 = temp1->x; dotProduct(B->vec,B->vec,B2); fftForward(B2); for(i = 0; i < spectralCount; i++) { B2->spectral[i] *= magBuoyScale; } plusEq(rhs->z->spectral, B2->spectral); } if(buoyancy) { complex PRECISION * zfield = rhs->z->spectral; complex PRECISION * tfield = T->spectral; PRECISION factor = Ra * Pr; index = 0; for(i = 0; i < spectralCount; i++) { zfield[i] += factor * tfield[i]; } } //curl it so we can avoid dealing with the pressure term curl(rhs, temp1); //The third parameter as a 1 means we store the result in the force //arrays for u->sol. decomposeCurlSolenoidal(u->sol, temp1, 1); debug("Momentum forces done\n"); }
template <int dim> void update(grid<dim, sparse<phi_type> >& oldGrid, int steps) { #if (!defined MPI_VERSION) && (defined BGQ) std::cerr<<"Error: Blue Gene requires MPI."<<std::endl; exit(-1); #endif int rank=0; #ifdef MPI_VERSION rank = MPI::COMM_WORLD.Get_rank(); #endif const phi_type dt = 0.01; const phi_type width = 14.5; const phi_type epsilon = 1.0e-8; for (int step = 0; step < steps; step++) { if (rank==0) print_progress(step, steps); // newGrid must be overwritten each time ghostswap(oldGrid); grid<dim, sparse<phi_type> > newGrid(oldGrid); for (int i = 0; i < nodes(oldGrid); i++) { vector<int> x = position(oldGrid, i); // determine nonzero fields within // the neighborhood of this node // (2 adjacent voxels along each cardinal direction) sparse<int> s; for (int j = 0; j < dim; j++) for (int k = -1; k <= 1; k++) { x[j] += k; for (int h = 0; h < length(oldGrid(x)); h++) { int sindex = index(oldGrid(x), h); set(s, sindex) = 1; } x[j] -= k; } phi_type S = phi_type(length(s)); // if only one field is nonzero, // then copy this node to newGrid if (S < 2.0) newGrid(i) = oldGrid(i); else { // compute laplacian of each field sparse<phi_type> lap = laplacian(oldGrid, i); // compute variational derivatives sparse<phi_type> dFdp; for (int h = 0; h < length(s); h++) { int hindex = index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = index(s, j); phi_type gamma = energy(hindex, jindex); phi_type eps = 4.0 / acos(-1.0) * sqrt(0.5 * gamma * width); phi_type w = 4.0 * gamma / width; // Update dFdp_h and dFdp_j, so the inner loop can be over j>h instead of j≠h set(dFdp, hindex) += 0.5 * eps * eps * lap[jindex] + w * oldGrid(i)[jindex]; set(dFdp, jindex) += 0.5 * eps * eps * lap[hindex] + w * oldGrid(i)[hindex]; } } // compute time derivatives sparse<phi_type> dpdt; for (int h = 0; h < length(s); h++) { int hindex = index(s, h); for (int j = h + 1; j < length(s); j++) { int jindex = index(s, j); phi_type mu = mobility(hindex, jindex); set(dpdt, hindex) -= mu * (dFdp[hindex] - dFdp[jindex]); set(dpdt, jindex) -= mu * (dFdp[jindex] - dFdp[hindex]); } } // compute new values phi_type sum = 0.0; for (int h = 0; h < length(s); h++) { int sindex = index(s, h); phi_type value = oldGrid(i)[sindex] + dt * (2.0 / S) * dpdt[sindex]; // Extraneous factor of 2? if (value > 1.0) value = 1.0; if (value < 0.0) value = 0.0; if (value > epsilon) set(newGrid(i), sindex) = value; sum += newGrid(i)[sindex]; } // project onto Gibbs simplex (enforce Σφ=1) phi_type rsum = 0.0; if (fabs(sum) > 0.0) rsum = 1.0 / sum; for (int h = 0; h < length(newGrid(i)); h++) { int sindex = index(newGrid(i), h); set(newGrid(i), sindex) *= rsum; } } } // Loop over nodes(oldGrid) swap(oldGrid, newGrid); } // Loop over steps ghostswap(oldGrid); }
int main(int argc, char* argv[]) { bool adj, snap; /* adjoint flag */ int ix, iz, it; /* index variables */ int nt, nx, nz, n0, jt, n12, padx, padz, n2; float dt, dx, dz, dt2, idz2, idx2; float **dd, **mm, **vv; float **u0, **u1, **u2, **tmp; /* temporary arrays */ sf_file in, out, vel, wave; /* I/O files */ /* initialize Madagascar */ sf_init(argc,argv); /* initialize OpenMP support */ #ifdef _OPENMP omp_init(); #endif if(!sf_getbool("adj", &adj)) adj=true; /* adjoint flag, 0: modeling, 1: migration */ if(!sf_getbool("snap", &snap)) snap=false; /* wavefield snapshot flag */ if(!sf_getint("n0", &n0)) n0=0; /* surface */ if(!sf_getint("jt", &jt)) jt=50; /* time interval of wavefield snapshot */ /* setup I/O files */ in=sf_input("in"); out=sf_output("out"); vel=sf_input("velocity"); /* velocity model */ /* Dimensions */ if(!sf_histint(vel, "n1", &nz)) sf_error("No n1= in velocity"); if(!sf_histint(vel, "n2", &nx)) sf_error("No n2= in velocity"); if(!sf_histfloat(vel, "d1", &dz)) sf_error("No d1= in velocity"); if(!sf_histfloat(vel, "d2", &dx)) sf_error("No d2= in velocity"); if(adj){ /* migration */ if(!sf_histint(in, "n1", &nt)) sf_error("No n1= in data"); if(!sf_histfloat(in, "d1", &dt)) sf_error("No d1= in data"); if(!sf_histint(in, "n2", &n2) || n2!=nx) sf_error("Need n2=%d in data", nx); sf_putint(out, "n1", nz); sf_putfloat(out, "d1", dz); sf_putfloat(out, "o1", 0.0); sf_putstring(out, "label1", "Depth"); sf_putstring(out, "unit1", "km"); sf_putstring(out, "label2", "Lateral"); sf_putstring(out, "unit2", "km"); }else{ /* modeling */ if(!sf_getint("nt", &nt)) sf_error("Need nt="); if(!sf_getfloat("dt", &dt)) sf_error("Need dt="); sf_putint(out, "n1", nt); sf_putfloat(out, "d1", dt); sf_putfloat(out, "o1", 0.0); sf_putstring(out, "label1", "Time"); sf_putstring(out, "unit1", "s"); sf_putstring(out, "label2", "Lateral"); sf_putstring(out, "unit2", "km"); } /* lengths of padding boundary */ if(!sf_getint("padx", &padx)) padx=nz/2; if(!sf_getint("padz", &padz)) padz=nz/2; padnx=nx+2*padx; padnz=nz+2*padz; n0=n0+padz; n12=padnz*padnx; /* set Laplacian coefficients */ idz2=1.0/(dz*dz); idx2=1.0/(dx*dx); c11=4.0*idz2/3.0; c12=-idz2/12.0; c21=4.0*idx2/3.0; c22=-idx2/12.0; c0=-2.0*(c11+c12+c21+c22); /* wavefield snapshot */ if(snap){ wave=sf_output("wave"); sf_putint(wave, "n1", padnz); sf_putint(wave, "d1", 1); sf_putint(wave, "o1", -padz); sf_putint(wave, "n2", padnx); sf_putint(wave, "d2", 1); sf_putint(wave, "o2", -padx); sf_putint(wave, "n3", 1+(nt-1)/jt); if(adj){ sf_putfloat(wave, "d3", -jt*dt); sf_putfloat(wave, "o3", (nt-1)*dt); }else{ sf_putfloat(wave, "d3", jt*dt); sf_putfloat(wave, "o3", 0.0); } } /* allocate arrays */ vv=sf_floatalloc2(nz, nx); dd=sf_floatalloc2(nt, nx); mm=sf_floatalloc2(nz, nx); padvv=sf_floatalloc2(padnz, padnx); u0=sf_floatalloc2(padnz, padnx); u1=sf_floatalloc2(padnz, padnx); u2=sf_floatalloc2(padnz, padnx); /* read velocity */ sf_floatread(vv[0], nz*nx, vel); /* pad boundary */ dt2=dt*dt; for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) padvv[ix+padx][iz+padz]=vv[ix][iz]*vv[ix][iz]*dt2; for(iz=0; iz<padz; iz++){ for(ix=padx; ix<nx+padx; ix++){ padvv[ix][iz]=padvv[ix][padz]; padvv[ix][iz+nz+padz]=padvv[ix][nz+padz-1]; } } for(ix=0; ix<padx; ix++){ for(iz=0; iz<padnz; iz++){ padvv[ix][iz]=padvv[padx][iz]; padvv[ix+nx+padx][iz]=padvv[nx+padx-1][iz]; } } memset(u0[0], 0.0, n12*sizeof(float)); memset(u1[0], 0.0, n12*sizeof(float)); memset(u2[0], 0.0, n12*sizeof(float)); if(adj){ /* migration */ /* read data */ sf_floatread(dd[0], nt*nx, in); for(it=nt-1; it>=0; it--){ sf_warning("Migration: %d;", it); laplacian(adj, u0, u1, u2); tmp=u0; u0=u1; u1=u2; u2=tmp; #ifdef _OPENMP #pragma omp parallel for default(none) private(ix) shared(padx, nx, dd, u1, it, n0) #endif for(ix=padx; ix<padx+nx; ix++) /* inject data */ u1[ix][n0]+=dd[ix-padx][it]; if(snap && it%jt==0) sf_floatwrite(u1[0], n12, wave); } sf_warning("."); /* output image */ for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) mm[ix][iz]=u1[ix+padx][iz+padz]; sf_floatwrite(mm[0], nz*nx, out); }else{/* modeling */ /* read reflector */ sf_floatread(mm[0], nz*nx, in); for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) u1[ix+padx][iz+padz]=mm[ix][iz]; for(it=0; it<nt; it++){ sf_warning("Modeling: %d;", it); if(snap && it%jt==0) sf_floatwrite(u1[0], n12, wave); #ifdef _OPENMP #pragma omp parallel for default(none) private(ix) shared(padx, nx, dd, u1, it, n0) #endif for(ix=padx; ix<padx+nx; ix++) /* record data */ dd[ix-padx][it]=u1[ix][n0]; laplacian(adj, u0, u1, u2); tmp=u0; u0=u1; u1=u2; u2=tmp; } sf_warning("."); /* output data */ sf_floatwrite(dd[0], nt*nx, out); } free(*padvv); free(padvv); free(*vv); free(vv); free(*dd); free(dd); free(*mm); free(mm); free(*u0); free(u0); free(*u1); free(u1); free(*u2); free(u2); exit (0); }
int main(int argc, char *argv[]){ MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numtasks); numworkers = numtasks - 1; MPI_Comm_rank(MPI_COMM_WORLD,&taskid); if(taskid == MASTER){ // This code fragment runs in the master porcesses // clock_t start_t, end_t, total_t; allocate_memory(); phi_initialize(); fluid_initialize(); gs_allocate(); // start_t = clock(); // printf("Starting of the program, start_t = %ld\n", start_t); for ( t = 0; t < phi_timesteps; t++ ) { #ifdef growth neuman_boundary(phi_old, MESHX); neuman_boundary(mu_old, MESHX); concentration(phi_old, mu_old, conc, MESHX); neuman_boundary(conc, MESHX); laplacian(phi_old, lap_phi, MESHX); laplacian(mu_old, lap_mu, MESHX); anisotropic_solverloop(); update(phi_old, phi_new, MESHX); update(mu_old, mu_new, MESHX); if((t%save_phi) == 0) { write2file_phi(t, MESHX,phi_old); } #endif #ifdef FLUID if (t>SMOOTH) { fluid_solver(); if((t%save_fluid) ==0) { write2file_fluid (t,u_old,v_old,MESHX); } } #endif printf("t=%d\n",t); } free_memory(); // end_t = clock(); // printf("End of the big loop, end_t = %ld\n", end_t); // total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC; // printf("Total time taken by CPU: %f\n", total_t ); printf("Exiting of the program...\n"); } else { // This code fragment runs in the worker processes gs_allocate(); for ( t = 0; t < phi_timesteps; t++ ) { if ( t > SMOOTH ) { gs_mpi(); } } free(P); free(rhs_fn); free(a_x); free(a_y); } MPI_Finalize(); return(0); }
template <int dim> void update(MMSP::grid<dim,vector<double> >& grid, int steps) { MMSP::grid<dim,vector<double> > update(grid); double dt = 0.01; double width = 8.0; for (int step=0; step<steps; step++) { for (int i=0; i<nodes(grid); i++) { vector<int> x = position(grid,i); // determine nonzero fields within // the neighborhood of this node double S = 0.0; vector<int> s(fields(grid),0); for (int h=0; h<fields(grid); h++) { for (int j=0; j<dim; j++) for (int k=-1; k<=1; k++) { x[j] += k; if (grid(x)[h]>0.0) { s[h] = 1; x[j] -= k; goto next; } x[j] -= k; } next: S += s[h]; } // if only one field is nonzero, // then copy this node to update if (S<2.0) update(i) = grid(i); else { // compute laplacian of each field vector<double> lap = laplacian(grid,i); // compute variational derivatives vector<double> dFdp(fields(grid),0.0); for (int h=0; h<fields(grid); h++) if (s[h]>0.0) for (int j=h+1; j<fields(grid); j++) if (s[j]>0.0) { double gamma = energy(h,j); double eps = 4.0/acos(-1.0)*sqrt(0.5*gamma*width); double w = 4.0*gamma/width; dFdp[h] += 0.5*eps*eps*lap[j]+w*grid(i)[j]; dFdp[j] += 0.5*eps*eps*lap[h]+w*grid(i)[h]; for (int k=j+1; k<fields(grid); k++) if (s[k]>0.0) { dFdp[h] += 3.0*grid(i)[j]*grid(i)[k]; dFdp[j] += 3.0*grid(i)[k]*grid(i)[h]; dFdp[k] += 3.0*grid(i)[h]*grid(i)[j]; } } // compute time derivatives vector<double> dpdt(fields(grid),0.0); for (int h=0; h<fields(grid); h++) if (s[h]>0.0) for (int j=h+1; j<fields(grid); j++) if (s[j]>0.0) { double mu = mobility(h,j); dpdt[h] -= mu*(dFdp[h]-dFdp[j]); dpdt[j] -= mu*(dFdp[j]-dFdp[h]); } // compute update values double sum = 0.0; for (int h=0; h<fields(grid); h++) { double value = grid(i)[h]+dt*(2.0/S)*dpdt[h]; if (value>1.0) value = 1.0; if (value<0.0) value = 0.0; update(i)[h] = value; sum += value; } // project onto Gibbs simplex double rsum = 0.0; if (fabs(sum)>0.0) rsum = 1.0/sum; for (int h=0; h<fields(grid); h++) update(i)[h] *= rsum; } } swap(grid,update); ghostswap(grid); } }
return fvMatrixHolder< Type >( laplacian( ds, field(), name ), Deps( &field ) ); } template< class Type, class GType > inline fvMatrixHolder< Type > laplacian( const GeometricFieldHolder< GType, fvPatchField, volMesh >& field1, GeometricFieldHolder< Type, fvPatchField, volMesh >& field2 ) { return fvMatrixHolder< Type >( laplacian( field1(), field2() ), Deps( &field1, &field2 ) ); } template< class Type, class GType > inline fvMatrixHolder< Type > laplacian( const GeometricFieldHolder< GType, fvPatchField, volMesh >& field1, GeometricFieldHolder< Type, fvPatchField, volMesh >& field2 const word& name ) { return fvMatrixHolder< Type >( laplacian( field1(), field2(), name ), Deps( &field1, &field2 ) ); } template< class Type, class GType > inline fvMatrixHolder< Type > laplacian( const GeometricFieldHolder< GType, vsPatchField, surfaceMesh >& field1, GeometricFieldHolder< Type, fvPatchField, volMesh >& field2 ) { return fvMatrixHolder< Type >( laplacian( field1(), field2() ), Deps( &field1, &field2 ) ); } template< class Type, class GType > inline fvMatrixHolder< Type > laplacian( const GeometricFieldHolder< GType, vsPatchField, surfaceMesh >& field1, GeometricFieldHolder< Type, fvPatchField, volMesh >& field2 const word& name ) { return fvMatrixHolder< Type >( laplacian( field1(), field2(), name ), Deps( &field1, &field2 ) );