double NearestBoundary(long id) { long lvl0, lvl, reg, cell, pbd, pbl, surf, type, n, np, ptr, loc0, ltype; long surflist, ownrlist, nbrlist, facelist, sidelist, nf, side, k, j, pt; long nbhr, uni, ifc, ncol, tbi, ang, i, cgns, loc1, nt; double min, d, x, y, z, u, v, w, y2, z2, params[MAX_SURFACE_PARAMS]; double t, phi, phi2; /* Reset minimum distance */ min = INFTY; /* Pointer to first level */ lvl0 = (long)RDB[DATA_PTR_LVL0]; CheckPointer(FUNCTION_NAME, "(lvl0)", DATA_ARRAY, lvl0); /* Loop over levels */ while (lvl0 > VALID_PTR) { /* Pointer to private data */ lvl = (long)RDB[lvl0 + LVL_PTR_PRIVATE_DATA]; CheckPointer(FUNCTION_NAME, "(lvl)", PRIVA_ARRAY, lvl); /* Get coordinates */ x = GetPrivateData(lvl + LVL_PRIV_X, id); y = GetPrivateData(lvl + LVL_PRIV_Y, id); z = GetPrivateData(lvl + LVL_PRIV_Z, id); /* Get direction cosines */ u = GetPrivateData(lvl + LVL_PRIV_U, id); v = GetPrivateData(lvl + LVL_PRIV_V, id); w = GetPrivateData(lvl + LVL_PRIV_W, id); /* Check coordinates and direction cosines */ CheckValue(FUNCTION_NAME, "x", "", x, -INFTY, INFTY); CheckValue(FUNCTION_NAME, "y", "", y, -INFTY, INFTY); CheckValue(FUNCTION_NAME, "z", "", z, -INFTY, INFTY); CheckValue(FUNCTION_NAME, "u", "", u, -1.0, 1.0); CheckValue(FUNCTION_NAME, "v", "", v, -1.0, 1.0); CheckValue(FUNCTION_NAME, "w", "", w, -1.0, 1.0); /* Pointer to universe */ uni = (long)GetPrivateData(lvl + LVL_PRIV_PTR_UNIV, id); CheckPointer(FUNCTION_NAME, "(uni)", DATA_ARRAY, uni); /* Get time */ ptr = RDB[uni + UNIVERSE_PTR_PRIVA_T]; CheckPointer(FUNCTION_NAME, "(ptr)", PRIVA_ARRAY, ptr); t = GetPrivateData(ptr, id); /* Check for symmetry */ if ((ptr = (long)RDB[uni + UNIVERSE_PTR_SYM]) > VALID_PTR) if ((d = SymmetryBoundary(ptr, x, y, z, u, v, w)) < min) min = d; /* Get level type */ ltype = (long)GetPrivateData(lvl + LVL_PRIV_TYPE, id); /* Check type */ switch (ltype) { case UNIVERSE_TYPE_NEST: { /*****************************************************************/ /***** Nest ******************************************************/ /* Check for fuel performance interface */ if ((loc0 = (long)RDB[uni + UNIVERSE_PTR_IFC_FUEP]) > VALID_PTR) { /* First check nest boundaries */ /* Check nest region surfaces */ /* Pointer to nest region */ reg = (long)GetPrivateData(lvl + LVL_PRIV_PTR_NEST_REG, id); CheckPointer(FUNCTION_NAME, "(reg)", DATA_ARRAY, reg); /* First surface */ if ((surf = (long)RDB[reg + NEST_REG_PTR_SURF_IN]) > VALID_PTR) { /* Get type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Die on non-cylindrical */ if(type != SURF_CYL) Die(FUNCTION_NAME,"Non-cylindrical surface"); /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Copy surface parameters */ memcpy(¶ms,&RDB[ptr],np*sizeof(double)); y2 = 0.0; z2 = z; /* Cold to hot expansion of cylinder radius */ /* (params[2]) */ CoordExpans(loc0,¶ms[2],&y2,&z2,t,2); /* Get distance */ d = SurfaceDistance(-1, params, type, np, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "1", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } /* Second surface */ if ((surf = (long)RDB[reg + NEST_REG_PTR_SURF_OUT]) > VALID_PTR) { /* Get type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Die on non-cylindrical */ if(type != SURF_CYL) Die(FUNCTION_NAME,"Non-cylindrical surface"); /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Copy surface parameters */ memcpy(¶ms,&RDB[ptr],np*sizeof(double)); y2 = 0.0; z2 = z; /* Cold to hot expansion of cylinder radius */ /* (params[2]) */ CoordExpans(loc0,¶ms[2],&y2,&z2,t,2); /* Get distance */ d = SurfaceDistance(-1, params, type, np, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "2", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } /* Check the interface input boundaries, */ /* Find time interval */ tbi = (long)RDB[loc0 + IFC_FUEP_PTR_T]; /* Get pointer to limits */ ptr = (long)RDB[loc0 + IFC_FUEP_LIM_PTR_T]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get number of time bins */ nt = (long)RDB[loc0 + IFC_FUEP_N_T]; /* Find bin*/ i = SearchArray(&RDB[ptr], t, nt + 1); /* Check if found */ if (i < 0) break; /* Get direct pointer to time bin */ tbi = ListPtr(tbi, i); /* Find axial zone */ loc1 = (long)RDB[tbi + IFC_FUEP_T_PTR_AX]; while (loc1 > VALID_PTR) { /* Compare coordinates */ if ((z >= RDB[loc1 + IFC_FUEP_AX_ZMIN]) && (z < RDB[loc1 + IFC_FUEP_AX_ZMAX])) { /* Break loop */ break; } /* Next */ loc1 = NextItem(loc1); } /* Break case if not found*/ if (loc1 < VALID_PTR) break; /* Only check axial boundaries in 3D calculation */ if ((long)RDB[DATA_GEOM_DIM] == 3) { /* Distance to lower boundary */ params[0] = RDB[loc1 + IFC_FUEP_AX_ZMIN]; d = SurfaceDistance(-1, params, SURF_PZ, 1, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "3", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; /* Distance to upper boundary */ params[0] = RDB[loc1 + IFC_FUEP_AX_ZMAX]; d = SurfaceDistance(-1, params, SURF_PZ, 1, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "4", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } /* Get the correct angular segment */ ang = (long)RDB[loc1 + IFC_FUEP_AX_PTR_ANG]; /* Get polar angle */ phi = PolarAngle(x,y); while (ang > VALID_PTR) { /* Rotate if needed */ if(phi > 2.0*PI+RDB[ang + IFC_FUEP_ANG_AMIN]) phi2 = phi - 2.0*PI; else phi2 = phi; /* Compare coordinates */ if ((phi2 >= RDB[ang + IFC_FUEP_ANG_AMIN]) && (phi2 < RDB[ang + IFC_FUEP_ANG_AMAX])) break; /* Next */ ang = NextItem(ang); } /* Break case if not found */ if (ang < VALID_PTR) break; /* Calculate distance to angular zone boundaries */ /* Tää ei huomioi että rajoittava taso on vain puoliääretön */ /* (Tulee ylimääräisiä pysäytyksiä, jos kulmasegmenttejä */ /* on pariton määrä) */ params[0] = RDB[ang + IFC_FUEP_ANG_CMIN]; params[1] = 1.0; params[2] = 0.0; params[3] = 0.0; d = SurfaceDistance(-1, params, SURF_PLANE, 4, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "5", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; params[0] = RDB[ang + IFC_FUEP_ANG_CMAX]; d = SurfaceDistance(-1, params, SURF_PLANE, 4, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "6", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } else { /* Pointer to nest region */ reg = (long)GetPrivateData(lvl + LVL_PRIV_PTR_NEST_REG, id); CheckPointer(FUNCTION_NAME, "(reg)", DATA_ARRAY, reg); /* First surface */ if ((surf = (long)RDB[reg + NEST_REG_PTR_SURF_IN]) > VALID_PTR) { /* Get type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get distance */ d = SurfaceDistance(-1, &RDB[ptr], type, np, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "10", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } /* Second surface */ if ((surf = (long)RDB[reg + NEST_REG_PTR_SURF_OUT]) > VALID_PTR) { /* Get type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get distance */ d = SurfaceDistance(-1, &RDB[ptr], type, np, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "11", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } } /* Break case */ break; /*****************************************************************/ } case UNIVERSE_TYPE_LATTICE: { /*****************************************************************/ /***** Lattice ***************************************************/ /* Check pointer to lattice */ if ((long)GetPrivateData(lvl + LVL_PRIV_PTR_LAT, id) < VALID_PTR) Die(FUNCTION_NAME, "No lattice pointer"); /* Get surface type */ type = (long)GetPrivateData(lvl + LVL_PRIV_LAT_SURF_TYPE, id); /* Get number of surface parameters */ np = (long)GetPrivateData(lvl + LVL_PRIV_LAT_SURF_NP, id); /* Get parameters (noiden kerrointen pitää olla peräkkäin) */ for (n = 0; n < np; n++) params[n] = GetPrivateData(lvl + LVL_PRIV_LAT_SURF_C0 + n, id); /* Get distance */ d = SurfaceDistance(-1, params, type, np, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "12", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; /* Check if type is vertical stack */ if (type == SURF_PZ) { /* Put parameter for second surface */ params[0] = GetPrivateData(lvl + LVL_PRIV_LAT_SURF_C1, id); /* Get distance (ei tarkisteta, reunimmaiset pinnat voi */ /* olla +/- INFTY) */ d = SurfaceDistance(-1, params, type, np, x, y, z, u, v, w, id); /* Compare to minimum */ if (d < min) min = d; } /* Break case */ break; /*****************************************************************/ } case UNIVERSE_TYPE_CELL: { /*****************************************************************/ /***** Cell ******************************************************/ /* Pointer to cell */ cell = (long)GetPrivateData(lvl + LVL_PRIV_PTR_CELL, id); CheckPointer(FUNCTION_NAME, "(cell)", DATA_ARRAY, cell); /* Pointer to surface list */ loc0 = (long)RDB[cell + CELL_PTR_SURF_LIST]; CheckPointer(FUNCTION_NAME, "(loc0)", DATA_ARRAY, loc0); /* Loop over list */ while ((surf = (long)RDB[loc0++]) > VALID_PTR) { /* Get type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Check infinite */ if (type != SURF_INF) { /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get distance */ d = SurfaceDistance(surf, &RDB[ptr], type, np, x, y, z, u, v, w, id); if (d < 0.0) printf("%s %ld: x = %1.14E; y = %1.14E; z = %1.14E; u = %1.14E; v = %1.14E; w = %1.14E;\n", GetText(surf + SURFACE_PTR_NAME), type, x, y, z, u, v, w); CheckValue(FUNCTION_NAME, "d", "14", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) min = d; } } /* Break case */ break; /*****************************************************************/ } case UNIVERSE_TYPE_UMSH: { /*****************************************************************/ /***** Unstructured mesh based geometry **************************/ /* Pointer to cell */ if ((cell = (long)GetPrivateData(lvl + LVL_PRIV_PTR_CELL, id)) > VALID_PTR) { /* Get current tetra-cell (set in whereami.c) */ ptr = (long)RDB[cell + CELL_PTR_PREV_TET]; if ((cgns = (long)GetPrivateData(ptr, id)) < VALID_PTR) Die(FUNCTION_NAME, "UMSH tet was not stored"); /* Reset pointer to neighbour */ nbhr = -1; /* Get pointer to UMSH structure */ ptr = (long)RDB[uni + UNIVERSE_PTR_UMSH]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get pointer to UMSH interface */ ifc = (long)RDB[ptr + UMSH_PTR_IFC]; CheckPointer(FUNCTION_NAME, "(ifc)", DATA_ARRAY, ifc); /* Get pointer to interface surface list */ surflist = (long)RDB[ifc + IFC_PTR_SURF_LIST]; CheckPointer(FUNCTION_NAME, "(surflist)", DATA_ARRAY, surflist); /* Get pointer to interface owner list */ ownrlist = (long)RDB[ifc + IFC_PTR_OWNR_LIST]; CheckPointer(FUNCTION_NAME, "(ownrlist)", DATA_ARRAY, ownrlist); /* Get pointer to interface neighbour list */ nbrlist = (long)RDB[ifc + IFC_PTR_NBR_LIST]; CheckPointer(FUNCTION_NAME, "(nbrlist)", DATA_ARRAY, nbrlist); /* Get pointer to cell's face list */ facelist = (long)RDB[cgns + IFC_TET_MSH_PTR_FACES]; CheckPointer(FUNCTION_NAME, "(facelist)", DATA_ARRAY, facelist); /* Get pointer to cell's side list */ sidelist = (long)RDB[cgns + IFC_TET_MSH_PTR_SIDES]; CheckPointer(FUNCTION_NAME, "(sidelist)", DATA_ARRAY, sidelist); /* Loop over cell faces */ nf = (long)RDB[cgns + IFC_TET_MSH_NF]; CheckValue(FUNCTION_NAME, "nf", "", nf, 4, 4); for (i = 0; i < nf; i++) { /* Get index of face */ n = (long)RDB[facelist + i]; /* Get side for face */ side = (long)RDB[sidelist + i]; /* Get pointer to face surface */ surf = ListPtr(surflist, n); /* Get pointer to surface parameters */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get number of points on the face */ np = (long)RDB[surf + SURFACE_N_PARAMS]; CheckValue(FUNCTION_NAME, "np", "", np, 3, 3); /* Copy points to params */ k = 0; for (j = 0; j < np; j++) { /* Get pointer to beginning of point coordinates */ pt = (long)RDB[ptr + j]; /* Store coordinates to params */ params[k++] = RDB[pt + 0]; params[k++] = RDB[pt + 1]; params[k++] = RDB[pt + 2]; } /* Get distance */ d = SurfaceDistance(surf, params, SURF_PLANE, 9, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "15", d, 0.0, INFTY); /* Compare to minimum */ if (d < min) { min = d; /* Get neighbour */ if (side == -1) nbhr = (long)RDB[nbrlist + n]; else nbhr = (long)RDB[ownrlist + n]; } } /* Get collision count */ ptr = (long)RDB[DATA_PTR_COLLISION_COUNT]; ncol = GetPrivateData(ptr, id); /* Store value */ StoreValuePair(uni + UNIVERSE_PTR_NEXT_CELL, ncol, nbhr, id); } else { /* Point is in background universe, get distance to search */ /* mesh boundaries. */ /* Pointer to geometry */ loc0 = (long)GetPrivateData(lvl + LVL_PRIV_PTR_UMSH, id); CheckPointer(FUNCTION_NAME, "(loc0)", DATA_ARRAY, loc0); /* Pointer to interaface structure */ loc0 = (long)RDB[loc0 + UMSH_PTR_IFC]; CheckPointer(FUNCTION_NAME, "(loc0)", DATA_ARRAY, loc0); /* Get minimum distance */ d = NearestUMSHSurf(loc0, x, y, z, u, v, w, id); /* Compare to minimum */ if (d < min) min = d; } /* Break case */ break; /*****************************************************************/ } case UNIVERSE_TYPE_STL: { /*****************************************************************/ /***** STL based geometry ****************************************/ /* Pointer to geometry */ loc0 = (long)GetPrivateData(lvl + LVL_PRIV_PTR_STL, id); CheckPointer(FUNCTION_NAME, "(loc0)", DATA_ARRAY, loc0); /* Get minimum distance */ d = NearestSTLSurf(loc0, x, y, z, u, v, w, id); /* Compare to minimum */ if (d < min) min = d; /* Break case */ break; /*****************************************************************/ } case UNIVERSE_TYPE_PBED: { /*****************************************************************/ /***** Explicit stochastic geometry ******************************/ /* Check direct pointer to pebble */ if ((pbl = (long)GetPrivateData(lvl + LVL_PRIV_PTR_PEBBLE, id)) > VALID_PTR) { /* Put surface parameters */ params[0] = RDB[pbl + PEBBLE_X0]; params[1] = RDB[pbl + PEBBLE_Y0]; params[2] = RDB[pbl + PEBBLE_Z0]; params[3] = RDB[pbl + PEBBLE_RAD]; if ((x - params[0])*(x - params[0]) + (y - params[1])*(y - params[1]) + (z - params[2])*(z - params[2]) > params[3]*params[3]) Die(FUNCTION_NAME, "not inside"); /* Get distance */ d = SurfaceDistance(-1, params, SURF_SPH, 4, x, y, z, u, v, w, id); CheckValue(FUNCTION_NAME, "d", "16", d, 0.0, 2.0*params[3]); } else { /* Pointer to PB geometry */ pbd = (long)GetPrivateData(lvl + LVL_PRIV_PTR_PBED, id); CheckPointer(FUNCTION_NAME, "(pbd)", DATA_ARRAY, pbd); /* Get minimum distance */ d = NearestPBSurf(pbd, x, y, z, u, v, w, id); } /* Compare to minimum */ if (d < min) min = d; /* Break case */ break; /*****************************************************************/ } default: { /* Invalid type */ Die(FUNCTION_NAME, "Invalid universe type"); } } /* Break loop if level is last */ if ((long)GetPrivateData(lvl + LVL_PRIV_LAST, id) == YES) break; /* Next level */ lvl0 = NextItem(lvl0); } /* Return shortest distance */ return min; }
void ScoreICMTrk(long part, double x0, double y0, double z0, double u, double v, double w, double lmax, double E, double wgt, long id) { long icm, ntot, nmu0, nmu1, nmu2, nseg, surf, type, ptr, np, in0, in1; long idx, ng, ncross, icm0, icm1, idx0, idx1, ng0, ng1; long mua, mus, mua0, mus0, mua1, mus1; long s0, s1, s2; double d, l, x, y, z, un0, vn0, wn0, un1, vn1, wn1, un2, vn2, wn2; double wgt0, wgt1, mu0, mu1, mu2; const double *params; /* Check mode */ if ((long)RDB[DATA_ICM_CALC] == NO) return; /* Get sizes */ ntot = (long)RDB[DATA_ICM_NG0]; nmu0 = (long)RDB[DATA_ICM_NMU0]; nmu1 = (long)RDB[DATA_ICM_NMU1]; nmu2 = (long)RDB[DATA_ICM_NMU2]; nseg = (long)RDB[DATA_ICM_NSEG]; /* Get pointer to few-group structure */ ptr = (long)RDB[DATA_ICM_PTR_ENE0]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); /* Get few-group index */ if ((ng = GridSearch(ptr, E)) < 0) return; /* Convert index */ ng = ntot - ng - 1; CheckValue(FUNCTION_NAME, "ng1", "", ng, 0, ntot - 1); /* Reset new data */ icm1 = -1; idx1 = -1; mua1 = -1; mus1 = -1; ng1 = -1; wgt1 = -1; /* Loop over data */ icm = (long)RDB[DATA_PTR_ICM0]; while (icm > VALID_PTR) { /* Get original particle Albedo data */ icm0 = (long)RDB[part + PARTICLE_ICM_PTR_ICM]; idx0 = (long)RDB[part + PARTICLE_ICM_IDX]; mua0 = (long)RDB[part + PARTICLE_ICM_MUA]; mus0 = (long)RDB[part + PARTICLE_ICM_MUS]; ng0 = (long)RDB[part + PARTICLE_ICM_G]; wgt0 = RDB[part + PARTICLE_ICM_WGT]; /* Get surface pointer */ surf = (long)RDB[icm + ICM_PTR_SURF]; CheckPointer(FUNCTION_NAME, "(surf)", DATA_ARRAY, surf); /* Get surface type */ type = (long)RDB[surf + SURFACE_TYPE]; /* Get number of parameters */ np = (long)RDB[surf + SURFACE_N_PARAMS]; /* Pointer to parameter list */ ptr = (long)RDB[surf + SURFACE_PTR_PARAMS]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); params = &RDB[ptr]; /* Move to starting position */ /* Toi ekstrapolointi lienee turhaa sen jälkeen kun */ /* trackin.c:tä muutettiin 14.8.2014 / 2.1.22 */ Die(FUNCTION_NAME, "HUOM!!!"); x = x0 - 2.0*EXTRAP_L*u; y = y0 - 2.0*EXTRAP_L*v; z = z0 - 2.0*EXTRAP_L*w; /* Reset total distance and number of crossings */ l = 0.0; ncross = 0; /* Get initial position */ in0 = TestSurface(surf, x, y, z, NO, id); in1 = -1; /* Loop over all surfaces in track */ while (l < lmax) { /* Get distance */ d = SurfaceDistance(surf, params, type, np, x, y, z, u, v, w, id); /* Extrapolate */ d = d + EXTRAP_L; /* Update coordinates */ x = x + d*u; y = y + d*v; z = z + d*w; /* Test position */ in1 = TestSurface(surf, x, y, z, NO, id); /* Check with maximum */ if (l + d > lmax) { /* Go back to collision site (for debugging) */ x = x0 + lmax*u; y = y0 + lmax*v; z = z0 + lmax*w; /* Cancel crossing */ in1 = in0; /* Break loop */ break; } else { /* Update distance */ l = l + d; } /* Check if surface was crossed */ if (in0 != in1) { /* Add counter */ ncross++; /* Get surface index */ if ((idx = ICMIdx(surf, x, y, z, &un0, &vn0, &wn0, &un1, &vn1, &wn1, &un2, &vn2, &wn2)) > -1) { /* Calculate cosines */ mu0 = un0*u + vn0*v + wn0*w; mu1 = un1*u + vn1*v + wn1*w; mu2 = un2*u + vn2*v + wn2*w; /* Get bins */ ptr = (long)RDB[DATA_ICM_PTR_MU0]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); s0 = SearchArray(&RDB[ptr], fabs(mu0), nmu0 + 1); CheckValue(FUNCTION_NAME, "s0", "", s0, 0, nmu0 - 1); ptr = (long)RDB[DATA_ICM_PTR_MU1]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); s1 = SearchArray(&RDB[ptr], mu1, nmu1 + 1); CheckValue(FUNCTION_NAME, "s1", "", s1, 0, nmu1 - 1); ptr = (long)RDB[DATA_ICM_PTR_MU2]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); s2 = SearchArray(&RDB[ptr], mu2, nmu2 + 1); CheckValue(FUNCTION_NAME, "s2", "", s2, 0, nmu2 - 1); /* Calculate asymmetric and symmetric part */ mua = s1; mus = s0*nmu2 + s2; /* Check direction */ if ((in0 == NO) && (in1 == YES)) { /* Check bins */ CheckValue(FUNCTION_NAME, "idx", "(1)", idx, 0, nseg - 1); CheckValue(FUNCTION_NAME, "mua", "(1)", mua, 0, nmu1 - 1); CheckValue(FUNCTION_NAME, "mus", "(1)", mus, 0, nmu0*nmu2 - 1); CheckValue(FUNCTION_NAME, "ng", "(1)", ng, 0, ntot - 1); /* Score inward current */ if (RDB[DATA_CYCLE_IDX] > RDB[DATA_CRIT_SKIP] - 1.0) { ptr = (long)RDB[icm + ICM_RES_CURR0]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); AddBuf(1.0, wgt, ptr, id, -1, idx, mua, mus, ng); } /* Put new data and reset weight */ icm0 = icm; idx0 = idx; mua0 = mua; mus0 = mus; ng0 = ng; wgt0 = 1.0; } else if ((in0 == YES) && (in1 == NO)) { /* Check active cycles */ if (RDB[DATA_CYCLE_IDX] > RDB[DATA_CRIT_SKIP] - 1.0) { /* Check index, group and angular bins */ if ((idx0 > -1) && (ng0 > -1) && (mua0 > -1) && (mus0 > -1)) { /* Check bins */ CheckValue(FUNCTION_NAME, "idx0", "(2)", idx0, 0, nseg - 1); CheckValue(FUNCTION_NAME, "mua0", "(2)", mua0, 0, nmu1 - 1); CheckValue(FUNCTION_NAME, "mus0", "(2)", mus0, 0, nmu0*nmu2 - 1); CheckValue(FUNCTION_NAME, "ng0", "(2)", ng0, 0, ntot - 1); CheckValue(FUNCTION_NAME, "idx", "(2)", idx, 0, nseg - 1); CheckValue(FUNCTION_NAME, "mua", "(2)", mua, 0, nmu1 - 1); CheckValue(FUNCTION_NAME, "mus", "(2)", mus, 0, nmu0*nmu2 - 1); /* Score outward current */ ptr = (long)RDB[icm + ICM_RES_CC1]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); AddBuf(1.0, wgt, ptr, id, -1, idx0, mua0, mus0, ng0, idx, mua, mus, ng); ptr = (long)RDB[icm + ICM_RES_CC2]; CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr); AddBuf(wgt0, wgt, ptr, id, -1, idx0, mua0, mus0, ng0, idx, mua, mus, ng); } else if ((ng0 > -1) && (RDB[DATA_CYCLE_IDX] > RDB[DATA_CRIT_SKIP] + 20.0)) Warn(FUNCTION_NAME, "Problem in geometry?"); } /* Reset values */ icm0 = -1; idx0 = -1; mua0 = -1; mus0 = -1; ng0 = -1; wgt0 = 1.0; } } } /* Put previous position */ in0 = in1; } /* Check if particle is in */ if (in1 == YES) { /* Update new values */ if (icm1 > VALID_PTR) Die(FUNCTION_NAME, "Point (%E, %E, %E) is in multiple regions", x, y, z); else { icm1 = icm0; idx1 = idx0; mua1 = mua0; mus1 = mus0; ng1 = ng0; wgt1 = wgt0; } /* Check number of crossings */ if (ncross == 0) { /* Surface index cannot have changed */ if (idx0 != (long)RDB[part + PARTICLE_ICM_IDX]) Die(FUNCTION_NAME, "This is impossible"); /* No other crossings are possible, add to counter */ ptr = (long)RDB[icm + ICM_BREAK_PTR_COUNT]; CheckPointer(FUNCTION_NAME, "(ptr)", PRIVA_ARRAY, ptr); AddPrivateData(ptr, 1, id); /* Break loop */ break; } } /* Next */ icm = NextItem(icm); } /* Store values */ WDB[part + PARTICLE_ICM_PTR_ICM] = (double)icm1; WDB[part + PARTICLE_ICM_IDX] = (double)idx1; WDB[part + PARTICLE_ICM_MUA] = (double)mua1; WDB[part + PARTICLE_ICM_MUS] = (double)mus1; WDB[part + PARTICLE_ICM_G] = (double)ng1; WDB[part + PARTICLE_ICM_WGT] = wgt1; }
void ShellDistance(LLA const &p, LLA const &q, double &distance, double &bearing, ReferenceEllipsoid const &_ref) { double da = p.altitude() - q.altitude(); SurfaceDistance(p, q, distance, bearing, _ref); distance = sqrt(distance*distance + da*da); }