|
| 1 | +from stompy.model.openfoam import depth_average |
| 2 | +import numpy as np |
| 3 | +from stompy import utils |
| 4 | + |
| 5 | +import six |
| 6 | + |
| 7 | +sim_dir="y:/DWR/fishpassage-DWR-7/fishpassage-DWR-7-7cms-local" |
| 8 | +## |
| 9 | +six.moves.reload_module(depth_average) |
| 10 | +pf = depth_average.PostFoam(sim_dir=sim_dir) |
| 11 | + |
| 12 | +# OF generated: |
| 13 | +#centers0=pf.cell_centers(proc) |
| 14 | +import time |
| 15 | + |
| 16 | +center_fn="test-centers.dat" |
| 17 | +t=time.time() |
| 18 | +pf.compute_cell_centers_py(proc,center_fn) |
| 19 | +print("Elapsed: ",time.time()-t) |
| 20 | + |
| 21 | + |
| 22 | + |
| 23 | +import pandas as pd |
| 24 | +df = pd.read_csv(center_fn,sep=r'\s+',names=['type','x','y','z']) |
| 25 | +centers_py = df[ ['x','y','z'] ].values |
| 26 | +err = centers0 - centers_py |
| 27 | +print("RMSE: " , np.sqrt(np.mean(err**2))) |
| 28 | + |
| 29 | +## |
| 30 | + |
| 31 | +# about 25s for a processor with 35k faces, almost all the time |
| 32 | +# in calc_face_center |
| 33 | + |
| 34 | +def calc_face_center(face): |
| 35 | + VSMALL=1e-14 |
| 36 | + if len(face)==3: |
| 37 | + return face.mean(axis=0),0.5*np.cross(face[1]-face[0],face[2]-face[0]) |
| 38 | + else: |
| 39 | + sumN=np.zeros(3,np.float64) |
| 40 | + sumA=0.0 |
| 41 | + sumAc=np.zeros(3,np.float64) |
| 42 | + |
| 43 | + fCentre = face.mean(axis=0) |
| 44 | + |
| 45 | + nPoints=face.shape[0] |
| 46 | + for pi in range(nPoints): |
| 47 | + p1=face[pi] |
| 48 | + p2=face[(pi+1)%nPoints] |
| 49 | + |
| 50 | + centroid3 = p1 + p2 + fCentre |
| 51 | + area_norm = np.cross( p2 - p1, fCentre - p1) |
| 52 | + area = utils.mag(area_norm) |
| 53 | + |
| 54 | + sumN += area_norm; |
| 55 | + sumA += area; |
| 56 | + sumAc += area*centroid3; |
| 57 | + |
| 58 | + return (1.0/3.0)*sumAc/(sumA + VSMALL), 0.5*sumN |
| 59 | + |
| 60 | +def cell_center_py(facefile, xyz, owner, neigh): |
| 61 | + """ |
| 62 | + facefile: |
| 63 | + xyz: pointfile.values.reshape([-1,3]) |
| 64 | + owner: [Nfaces] index of face's owner cell |
| 65 | + neigh: [NInternalFaces] index of faces's neighbor cell |
| 66 | + """ |
| 67 | + # replicate cell center calculation from openfoam-master/src/meshTools/primitiveMeshGeometry.C |
| 68 | + faces=[] # [N,{xyz}] array per face |
| 69 | + |
| 70 | + VSMALL=1e-14 |
| 71 | + nfaces = facefile.nfaces |
| 72 | + # WRONG ncells = owner.shape[0] |
| 73 | + ncells = 1+max(owner.max(),neigh.max()) # or get it from owner file |
| 74 | + n_internal = neigh.shape[0] |
| 75 | + |
| 76 | + face_ctr=np.zeros((nfaces,3),np.float64) |
| 77 | + face_area=np.zeros((nfaces,3),np.float64) |
| 78 | + |
| 79 | + if 1: # get face centers |
| 80 | + # 20 s for one domain |
| 81 | + for fIdx in utils.progress(range(nfaces)): |
| 82 | + face_nodes = facefile.faces[fIdx]["id_pts"][:] |
| 83 | + face = xyz[list(face_nodes)] |
| 84 | + face_ctr[fIdx],face_area[fIdx] = calc_face_center(face) |
| 85 | + |
| 86 | + if 1: # estimated cell centers |
| 87 | + cell_est_centers = np.zeros( (ncells,3), np.float64) |
| 88 | + cell_n_faces = np.zeros( ncells, np.int32) |
| 89 | + |
| 90 | + for j,ctr in enumerate(face_ctr): |
| 91 | + c_own = owner[j] |
| 92 | + cell_est_centers[c_own] += ctr |
| 93 | + cell_n_faces[c_own] += 1 |
| 94 | + |
| 95 | + for j,ctr in enumerate(face_ctr[:n_internal]): |
| 96 | + c_nbr = neigh[j] |
| 97 | + cell_est_centers[c_nbr] += ctr |
| 98 | + cell_n_faces[c_nbr] += 1 |
| 99 | + |
| 100 | + cell_est_centers[:] /= cell_n_faces[:,None] |
| 101 | + |
| 102 | + if 1: # refined cell centers |
| 103 | + cell_centers=np.zeros_like(cell_est_centers) |
| 104 | + cell_volumes=np.zeros(ncells,np.float64) |
| 105 | + |
| 106 | + def mydot(a,b): # fighting with numpy to get vectorized dot product |
| 107 | + return (a*b).sum(axis=-1) |
| 108 | + |
| 109 | + pyr3Vol_own = mydot(face_area, face_ctr - cell_est_centers[owner]).clip(VSMALL) |
| 110 | + pyrCtr_own = (3.0/4.0)*face_ctr + (1.0/4.0)*cell_est_centers[owner] |
| 111 | + for j in range(nfaces): |
| 112 | + cell_centers[owner[j]] += pyr3Vol_own[j,None] * pyrCtr_own[j] |
| 113 | + cell_volumes[owner[j]] += pyr3Vol_own[j] |
| 114 | + |
| 115 | + # note sign flip to account for nbr normal |
| 116 | + pyr3Vol_nbr = mydot(face_area[:n_internal], cell_est_centers[neigh] - face_ctr[:n_internal]).clip(VSMALL) |
| 117 | + pyrCtr_nbr = (3.0/4.0)*face_ctr[:n_internal] + (1.0/4.0)*cell_est_centers[neigh] |
| 118 | + |
| 119 | + for j in range(n_internal): |
| 120 | + cell_centers[neigh[j]] += pyr3Vol_nbr[j,None] * pyrCtr_nbr[j] |
| 121 | + cell_volumes[neigh[j]] += pyr3Vol_nbr[j] |
| 122 | + |
| 123 | + cell_centers /= cell_volumes[:,None] |
| 124 | + cell_volumes *= 1.0/3.0 |
| 125 | + |
| 126 | + return cell_centers, cell_volumes |
| 127 | + |
| 128 | +proc=0 |
| 129 | +centers0=pf.cell_centers(proc) |
| 130 | + |
| 131 | +faces0 = pf.face_centers(proc) |
| 132 | + |
| 133 | +facefile = pf.read_facefile(proc) |
| 134 | +pointfile = pf.read_pointfile(proc) |
| 135 | +owner = pf.read_owner(proc) |
| 136 | +neigh = pf.read_neighbor(proc) |
| 137 | + |
| 138 | +ctrs,vols = cell_center_py(facefile, pointfile.values.reshape([-1,3]), owner.values, neigh.values) |
0 commit comments