From 27a9dc291938672785e46a13939825bc7dc3cb94 Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Tue, 5 Nov 2024 11:31:14 -0800 Subject: [PATCH 1/9] attempting to implement cs_tallies --- examples/fixed_source/cooper_combo/input.py | 4 +- examples/fixed_source/kobayashi3-TD/input.py | 7 +- mcdc/card.py | 13 ++ mcdc/global_.py | 1 + mcdc/kernel.py | 148 ++++++++++++++++--- mcdc/main.py | 102 ++++++++++++- mcdc/tally.py | 81 ++++++++++ mcdc/type_.py | 71 +++++++++ 8 files changed, 403 insertions(+), 24 deletions(-) diff --git a/examples/fixed_source/cooper_combo/input.py b/examples/fixed_source/cooper_combo/input.py index 952a6083..5e3e4059 100644 --- a/examples/fixed_source/cooper_combo/input.py +++ b/examples/fixed_source/cooper_combo/input.py @@ -56,8 +56,8 @@ mcdc.tally.mesh_tally( scores=["flux"], - x=np.linspace(0.0, 4.0, 40), - y=np.linspace(0.0, 4.0, 40), + x=np.linspace(0.0, 4.0, 41), + y=np.linspace(0.0, 4.0, 41), ) # Setting diff --git a/examples/fixed_source/kobayashi3-TD/input.py b/examples/fixed_source/kobayashi3-TD/input.py index 4bdea735..7308f928 100644 --- a/examples/fixed_source/kobayashi3-TD/input.py +++ b/examples/fixed_source/kobayashi3-TD/input.py @@ -61,14 +61,19 @@ x=np.linspace(0.0, 60.0, 31), y=np.linspace(0.0, 100.0, 51), t=np.linspace(0.0, 200.0, 21), + # g=np.array([-0.5, 3.5, 6.5]) # fast (0, 1, 2, 3) and thermal (4, 5, 6) groups ) mcdc.tally.cell_tally(source_cell, scores=["flux"]) mcdc.tally.cell_tally(void_cell, scores=["flux"]) mcdc.tally.cell_tally(shield_cell, scores=["flux"]) + +mcdc.tally.cs_tally(N_cs_bins=[10], size=[1], scores=["flux"]) + + # Setting -mcdc.setting(N_particle=80) +mcdc.setting(N_particle=50) # Run mcdc.run() diff --git a/mcdc/card.py b/mcdc/card.py index 0b300c16..141679c2 100644 --- a/mcdc/card.py +++ b/mcdc/card.py @@ -394,3 +394,16 @@ def __init__(self, cell_ID): # Set card data self.cell_ID = cell_ID self.N_bin = 1 + + +class CSTallyCard(TallyCard): + def __init__(self): + TallyCard.__init__(self, "CS tally") + + # Set card data + self.x = np.array([-INF, INF]) + self.y = np.array([-INF, INF]) + self.z = np.array([-INF, INF]) + self.N_bin = 1 + self.N_cs_bins = 1 + self.size = 1 diff --git a/mcdc/global_.py b/mcdc/global_.py index 3e3d8f58..ef28b0c3 100644 --- a/mcdc/global_.py +++ b/mcdc/global_.py @@ -36,6 +36,7 @@ def reset(self): self.mesh_tallies = [] self.surface_tallies = [] self.cell_tallies = [] + self.cs_tallies = [] self.setting = { "tag": "Setting", diff --git a/mcdc/kernel.py b/mcdc/kernel.py index f67f0466..aad7a2ac 100644 --- a/mcdc/kernel.py +++ b/mcdc/kernel.py @@ -1977,22 +1977,6 @@ def score_cell_tally(P_arr, distance, tally, data, mcdc): cell_idx = stride["tally"] score = 0 - # # Particle 4D direction - # ux = P["ux"] - # uy = P["uy"] - # uz = P["uz"] - # ut = 1.0 / physics.get_speed(P_arr, mcdc) - - # # Particle initial and final coordinate - # x = P["x"] - # y = P["y"] - # z = P["z"] - # t = P["t"] - # x_final = x + ux * distance - # y_final = y + uy * distance - # z_final = z + uz * distance - # t_final = t + ut * distance - # Score flux = distance * P["w"] for i in range(tally["N_score"]): @@ -2006,10 +1990,136 @@ def score_cell_tally(P_arr, distance, tally, data, mcdc): SigmaF = get_MacroXS(XS_FISSION, material, P_arr, mcdc) score = flux * SigmaF - # print(f'cell_idx = {cell_idx}, score = {score}') tally_bin[TALLY_SCORE, cell_idx] += score +@njit +def score_cs_tally(P_arr, distance, tally, data, mcdc): + P = P_arr[0] + tally_bin = data[TALLY] + material = mcdc["materials"][P["material_ID"]] + N_cs_bins = tally["filter"]["N_cs_bins"] + cs_bin_size = tally["filter"]["cs_bin_size"] + cs_centers = tally["filter"]["cs_centers"] + stride = tally["stride"] + + # Particle 4D direction + ux = P["ux"] + uy = P["uy"] + uz = P["uz"] + ut = 1.0 / physics.get_speed(P_arr, mcdc) + + # Particle initial and final coordinate + x = P["x"] + y = P["y"] + z = P["z"] + t = P["t"] + x_final = x + ux * distance + y_final = y + uy * distance + z_final = z + uz * distance + t_final = t + ut * distance + + # Check each coarse bin + for bin_idx in range(N_cs_bins): + center = cs_centers[bin_idx] + + # Bin edges + x_min, x_max = center[0] - cs_bin_size / 2, center[0] + cs_bin_size / 2 + y_min, y_max = center[1] - cs_bin_size / 2, center[1] + cs_bin_size / 2 + z_min, z_max = center[2] - cs_bin_size / 2, center[2] + cs_bin_size / 2 + + # Check for intersection with coarse bin + # If particle starts or ends inside the bin, it should score into the bin + + # TODO: handle case where particle crosses a corner, but doesn't start or end in the bin + + if ( + (x_min <= x <= x_max or x_min <= x_final <= x_max) + and (y_min <= y <= y_max or y_min <= y_final <= y_max) + and (z_min <= z <= z_max or z_min <= z_final <= z_max) + ): + + distance_in_bin = min( + distance, + calculate_distance_in_coarse_bin( + P_arr, distance, center, cs_bin_size, mcdc + ), + ) + + # Calculate flux and other scores + flux = distance_in_bin * P["w"] + for i in range(tally["N_score"]): + score_type = tally["scores"][i] + if score_type == SCORE_FLUX: + score = flux + elif score_type == SCORE_DENSITY: + score = flux / physics.get_speed(P_arr, mcdc) + elif score_type == SCORE_TOTAL: + SigmaT = get_MacroXS(XS_TOTAL, material, P_arr, mcdc) + score = flux * SigmaT + elif score_type == SCORE_FISSION: + SigmaF = get_MacroXS(XS_FISSION, material, P_arr, mcdc) + score = flux * SigmaF + adapt.global_add( + tally_bin, (TALLY_SCORE, bin_idx + i), score + ) # TODO: fix this score indexing, this is wrong + + +@njit +def calculate_distance_in_coarse_bin(P_arr, distance, center, cs_bin_size, mcdc): + def intersect_plane(p0, p1, min_val, max_val, axis): + if p1[axis] != p0[axis]: # Avoid division by zero if line is parallel to plane + t_min = (min_val - p0[axis]) / (p1[axis] - p0[axis]) + t_max = (max_val - p0[axis]) / (p1[axis] - p0[axis]) + return [t_min, t_max] if t_min <= t_max else [t_max, t_min] + return [float("-inf"), float("inf")] # No intersection if parallel + + P = P_arr[0] + # Particle 4D direction + ux = P["ux"] + uy = P["uy"] + uz = P["uz"] + ut = 1.0 / physics.get_speed(P_arr, mcdc) + + # Particle initial and final coordinate + x = P["x"] + y = P["y"] + z = P["z"] + t = P["t"] + x_final = x + ux * distance + y_final = y + uy * distance + z_final = z + uz * distance + t_final = t + ut * distance + + start = np.array([x, y, z]) + end = np.array([x_final, y_final, z_final]) + + # Bin edges + x_min, x_max = center[0] - cs_bin_size / 2, center[0] + cs_bin_size / 2 + y_min, y_max = center[1] - cs_bin_size / 2, center[1] + cs_bin_size / 2 + z_min, z_max = center[2] - cs_bin_size / 2, center[2] + cs_bin_size / 2 + + # Calculate intersection parameters for each axis + tx_min, tx_max = intersect_plane(start, end, x_min, x_max, 0) + ty_min, ty_max = intersect_plane(start, end, y_min, y_max, 1) + tz_min, tz_max = intersect_plane(start, end, z_min, z_max, 2) + + # Determine the entry and exit parameters + t_entry = max(tx_min, ty_min, tz_min) + t_exit = min(tx_max, ty_max, tz_max) + + # Check if there's a valid intersection + if t_entry > t_exit or t_exit < 0 or t_entry > 1: + return 0.0 + + # Calculate entry and exit points in 3D space + entry_point = start + t_entry * (end - start) + exit_point = start + t_exit * (end - start) + + # Return the distance between entry and exit points + return np.linalg.norm(exit_point - entry_point) + + @njit def tally_reduce(data, mcdc): tally_bin = data[TALLY] @@ -2403,6 +2513,10 @@ def move_to_event(P_arr, data, mcdc): for tally in mcdc["mesh_tallies"]: score_mesh_tally(P_arr, distance, tally, data, mcdc) + for tally in mcdc["cs_tallies"]: + # print(f'kernel.py cs_tally = {tally}') + score_cs_tally(P_arr, distance, tally, data, mcdc) + cell = mcdc["cells"][P["cell_ID"]] for tally in mcdc["cell_tallies"]: if tally["filter"]["cell_ID"] == P["cell_ID"] and cell["N_tally"] != 0: diff --git a/mcdc/main.py b/mcdc/main.py index 1381ab68..09dbb508 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -217,6 +217,11 @@ def copy_field(dst, src, name): else: data = getattr(src, name) + # print(f'dst, src, name = {dst, src, name}') + # print(f'dst = {dst.dtype.names}') + # print(f'name = {name}') + # print(f'dst[name] = {dst[name]}') + if isinstance(dst[name], np.ndarray): if isinstance(data, np.ndarray) and dst[name].shape != data.shape: for dim in data.shape: @@ -463,6 +468,7 @@ def prepare(): type_.make_type_mesh_tally(input_deck) type_.make_type_surface_tally(input_deck) type_.make_type_cell_tally(input_deck) + type_.make_type_cs_tally(input_deck) type_.make_type_setting(input_deck) type_.make_type_uq(input_deck) type_.make_type_domain_decomp(input_deck) @@ -706,6 +712,7 @@ def prepare(): N_mesh_tally = len(input_deck.mesh_tallies) N_surface_tally = len(input_deck.surface_tallies) N_cell_tally = len(input_deck.cell_tallies) + N_cs_tally = len(input_deck.cs_tallies) tally_size = 0 # Mesh tallies @@ -895,22 +902,109 @@ def prepare(): # Filter strides stride = N_score if Nt > 1: - mcdc["mesh_tallies"][i]["stride"]["t"] = stride + mcdc["cell_tallies"][i]["stride"]["t"] = stride stride *= Nt if Ng > 1: - mcdc["mesh_tallies"][i]["stride"]["g"] = stride + mcdc["cell_tallies"][i]["stride"]["g"] = stride stride *= Ng if N_azi > 1: - mcdc["mesh_tallies"][i]["stride"]["azi"] = stride + mcdc["cell_tallies"][i]["stride"]["azi"] = stride stride *= N_azi if Nmu > 1: - mcdc["mesh_tallies"][i]["stride"]["mu"] = stride + mcdc["cell_tallies"][i]["stride"]["mu"] = stride stride *= Nmu # Set tally stride and accumulate total tally size mcdc["cell_tallies"][i]["stride"]["tally"] = tally_size tally_size += mcdc["cell_tallies"][i]["N_bin"] + # CS tallies + for i in range(N_cs_tally): + # Direct assignment + copy_field(mcdc["cs_tallies"][i], input_deck.cs_tallies[i], "N_bin") + + # Filters (variables with possible different sizes) + if not input_deck.technique["domain_decomposition"]: + for name in ["x", "y", "z", "t", "mu", "azi", "g"]: + N = len(getattr(input_deck.cs_tallies[i], name)) + mcdc["cs_tallies"][i]["filter"][name][:N] = getattr( + input_deck.cs_tallies[i], name + ) + + # else: # decomposed mesh filters + # mxn, mxp, myn, myp, mzn, mzp = dd_mesh_bounds(i) + + # # Filters + # new_x = input_deck.mesh_tallies[i].x[mxn:mxp] + # new_y = input_deck.mesh_tallies[i].y[myn:myp] + # new_z = input_deck.mesh_tallies[i].z[mzn:mzp] + # mcdc["mesh_tallies"][i]["filter"]["x"] = new_x + # mcdc["mesh_tallies"][i]["filter"]["y"] = new_y + # mcdc["mesh_tallies"][i]["filter"]["z"] = new_z + # for name in ["t", "mu", "azi", "g"]: + # N = len(getattr(input_deck.mesh_tallies[i], name)) + # mcdc["mesh_tallies"][i]["filter"][name][:N] = getattr( + # input_deck.mesh_tallies[i], name + # ) + + # Set tally scores + N_score = len(input_deck.cs_tallies[i].scores) + mcdc["cs_tallies"][i]["N_score"] = N_score + for j in range(N_score): + score_name = input_deck.cs_tallies[i].scores[j] + score_type = None + if score_name == "flux": + score_type = SCORE_FLUX + elif score_name == "density": + score_type = SCORE_DENSITY + elif score_name == "total": + score_type = SCORE_TOTAL + elif score_name == "fission": + score_type = SCORE_FISSION + elif score_name == "net-current": + score_type = SCORE_NET_CURRENT + mcdc["cs_tallies"][i]["scores"][j] = score_type + + # Filter grid sizes + Nmu = len(input_deck.cs_tallies[i].mu) - 1 + N_azi = len(input_deck.cs_tallies[i].azi) - 1 + Ng = len(input_deck.cs_tallies[i].g) - 1 + Nx = len(input_deck.cs_tallies[i].x) - 1 + Ny = len(input_deck.cs_tallies[i].y) - 1 + Nz = len(input_deck.cs_tallies[i].z) - 1 + Nt = len(input_deck.cs_tallies[i].t) - 1 + + # Update N_bin + mcdc["cs_tallies"][i]["N_bin"] *= N_score + + # Filter strides + stride = N_score + if Nz > 1: + mcdc["cs_tallies"][i]["stride"]["z"] = stride + stride *= Nz + if Ny > 1: + mcdc["cs_tallies"][i]["stride"]["y"] = stride + stride *= Ny + if Nx > 1: + mcdc["cs_tallies"][i]["stride"]["x"] = stride + stride *= Nx + if Nt > 1: + mcdc["cs_tallies"][i]["stride"]["t"] = stride + stride *= Nt + if Ng > 1: + mcdc["cs_tallies"][i]["stride"]["g"] = stride + stride *= Ng + if N_azi > 1: + mcdc["cs_tallies"][i]["stride"]["azi"] = stride + stride *= N_azi + if Nmu > 1: + mcdc["cs_tallies"][i]["stride"]["mu"] = stride + stride *= Nmu + + # Set tally stride and accumulate total tally size + mcdc["cs_tallies"][i]["stride"]["tally"] = tally_size + tally_size += mcdc["cs_tallies"][i]["N_bin"] + # Set tally data if not input_deck.technique["uq"]: tally = np.zeros((3, tally_size), dtype=type_.float64) diff --git a/mcdc/tally.py b/mcdc/tally.py index 79933808..db75e917 100644 --- a/mcdc/tally.py +++ b/mcdc/tally.py @@ -7,6 +7,7 @@ MeshTallyCard, SurfaceTallyCard, CellTallyCard, + CSTallyCard, ) from mcdc.constant import ( INF, @@ -159,6 +160,21 @@ def surface_tally( def cell_tally(cell, scores=["flux"]): + """ + Create a tally card to collect MC solutions. + + Parameters + ---------- + cell : CellCard + Cell to which the tally is attached to + scores : list of str {"flux", "net-current"} + List of physical quantities to be scored. + + Returns + ------- + CellTallyCard + The tally card. + """ # Make tally card card = CellTallyCard(cell.ID) @@ -187,3 +203,68 @@ def cell_tally(cell, scores=["flux"]): global_.input_deck.cell_tallies.append(card) return card + + +def cs_tally( + N_cs_bins=10, + size=1, + x=np.array([-INF, INF]), + y=np.array([-INF, INF]), + z=np.array([-INF, INF]), + t=np.array([-INF, INF]), + mu=np.array([-1.0, 1.0]), + azi=np.array([-PI, PI]), + g=np.array([-INF, INF]), + E=np.array([0.0, INF]), + scores=["flux"], +): + # Make tally card + card = CSTallyCard() + + # Set ID + card.ID = len(global_.input_deck.cs_tallies) + card.N_cs_bins = N_cs_bins + card.size = size + + # Set mesh + card.x = x + card.y = y + card.z = z + + # Set other filters + card.t = t + card.mu = mu + card.azi = azi + + # Set energy group grid + if type(g) == type("string") and g == "all": + G = global_.input_deck.materials[0].G + card.g = np.linspace(0, G, G + 1) - 0.5 + else: + card.g = g + if global_.input_deck.setting["mode_CE"]: + card.g = E + + # Calculate total number bins + Nx = len(card.x) - 1 + Ny = len(card.y) - 1 + Nz = len(card.z) - 1 + Nt = len(card.t) - 1 + Nmu = len(card.mu) - 1 + N_azi = len(card.azi) - 1 + Ng = len(card.g) - 1 + card.N_bin = Nx * Ny * Nz * Nt * Nmu * N_azi * Ng + + # Scores + for s in scores: + score_checked = check_support( + "score type", + s, + ["flux", "total", "fission", "density"], + ) + card.scores.append(score_checked) + + # Add to deck + global_.input_deck.cs_tallies.append(card) + + return card diff --git a/mcdc/type_.py b/mcdc/type_.py index 20606f23..7fd7bbeb 100644 --- a/mcdc/type_.py +++ b/mcdc/type_.py @@ -45,6 +45,7 @@ mesh_tally = None surface_tally = None cell_tally = None +cs_tally = None technique = None global_ = None @@ -894,6 +895,74 @@ def make_type_cell_tally(input_deck): cell_tally = into_dtype(struct) +def make_type_cs_tally(input_deck): + global cs_tally + struct = [] + + # Maximum numbers of mesh and filter grids and scores + Nmax_cs_bins = 2 + Nmax_x = 2 + Nmax_y = 2 + Nmax_z = 2 + Nmax_t = 2 + Nmax_mu = 2 + Nmax_azi = 2 + Nmax_g = 2 + Nmax_score = 1 + for card in input_deck.cs_tallies: + Nmax_cs_bins = max(Nmax_cs_bins, len(card.N_cs_bins)) + Nmax_x = max(Nmax_x, len(card.x)) + Nmax_y = max(Nmax_y, len(card.y)) + Nmax_z = max(Nmax_z, len(card.z)) + Nmax_t = max(Nmax_t, len(card.t)) + Nmax_mu = max(Nmax_mu, len(card.mu)) + Nmax_azi = max(Nmax_azi, len(card.azi)) + Nmax_g = max(Nmax_g, len(card.g)) + Nmax_score = max(Nmax_score, len(card.scores)) + + # # reduce tally sizes for subdomains + # if input_deck.technique["domain_decomposition"]: + # Nmax_x, Nmax_y, Nmax_z = dd_meshtally(input_deck) + + # Set the filter + filter_ = [ + ("N_cs_bins", int64), + ("cs_bin_size", float64), + ("cs_centers", float64, (Nmax_cs_bins,)), + ("x", float64, (Nmax_x,)), + ("y", float64, (Nmax_y,)), + ("z", float64, (Nmax_z,)), + ("t", float64, (Nmax_t,)), + ("mu", float64, (Nmax_mu,)), + ("azi", float64, (Nmax_azi,)), + ("g", float64, (Nmax_g,)), + ] + struct += [("filter", filter_)] + + # Tally strides + stride = [ + ("tally", int64), + ("sensitivity", int64), + ("mu", int64), + ("azi", int64), + ("g", int64), + ("t", int64), + ("x", int64), + ("y", int64), + ("z", int64), + ] + struct += [("stride", stride)] + + # Total number of bins + struct += [("N_bin", int64)] + + # Scores + struct += [("N_score", int64), ("scores", int64, (Nmax_score,))] + + # Make tally structure + cs_tally = into_dtype(struct) + + # ============================================================================== # Setting # ============================================================================== @@ -1318,6 +1387,7 @@ def make_type_global(input_deck): N_mesh_tally = len(input_deck.mesh_tallies) N_surface_tally = len(input_deck.surface_tallies) N_cell_tally = len(input_deck.cell_tallies) + N_cs_tally = len(input_deck.cs_tallies) # Cell data sizes N_cell_surface = 0 @@ -1389,6 +1459,7 @@ def make_type_global(input_deck): ("mesh_tallies", mesh_tally, (N_mesh_tally,)), ("surface_tallies", surface_tally, (N_surface_tally,)), ("cell_tallies", cell_tally, (N_cell_tally,)), + ("cs_tallies", cs_tally, (N_cs_tally,)), ("setting", setting), ("technique", technique), ("domain_decomp", domain_decomp), From efb2501be37598fd26d608afdf86f4c506559573 Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Mon, 16 Dec 2024 13:14:52 -0700 Subject: [PATCH 2/9] Compressed sensing tallies, still some issues --- examples/fixed_source/cooper_combo/input.py | 2 +- examples/fixed_source/cooper_combo/process.py | 2 + examples/fixed_source/kobayashi3-TD/input.py | 12 +- examples/fixed_source/sphere_in_cube/input.py | 18 +- mcdc/card.py | 2 +- mcdc/kernel.py | 164 ++++---- mcdc/main.py | 351 ++++++++++++++---- mcdc/tally.py | 8 +- mcdc/type_.py | 23 +- 9 files changed, 421 insertions(+), 161 deletions(-) diff --git a/examples/fixed_source/cooper_combo/input.py b/examples/fixed_source/cooper_combo/input.py index 5e3e4059..8daf6352 100644 --- a/examples/fixed_source/cooper_combo/input.py +++ b/examples/fixed_source/cooper_combo/input.py @@ -61,7 +61,7 @@ ) # Setting -mcdc.setting(N_particle=50) +mcdc.setting(N_particle=1e5) mcdc.implicit_capture() # Run diff --git a/examples/fixed_source/cooper_combo/process.py b/examples/fixed_source/cooper_combo/process.py index 8ab5fad0..8103e3e8 100644 --- a/examples/fixed_source/cooper_combo/process.py +++ b/examples/fixed_source/cooper_combo/process.py @@ -13,6 +13,8 @@ phi = tally["flux/mean"][:] phi_sd = tally["flux/sdev"][:] + np.save("flux_results.npy", phi) + # Plot result X, Y = np.meshgrid(x_mid, x_mid) diff --git a/examples/fixed_source/kobayashi3-TD/input.py b/examples/fixed_source/kobayashi3-TD/input.py index 7308f928..116f4312 100644 --- a/examples/fixed_source/kobayashi3-TD/input.py +++ b/examples/fixed_source/kobayashi3-TD/input.py @@ -60,7 +60,7 @@ scores=["flux"], x=np.linspace(0.0, 60.0, 31), y=np.linspace(0.0, 100.0, 51), - t=np.linspace(0.0, 200.0, 21), + # t=np.linspace(0.0, 200.0, 21), # g=np.array([-0.5, 3.5, 6.5]) # fast (0, 1, 2, 3) and thermal (4, 5, 6) groups ) @@ -69,11 +69,17 @@ mcdc.tally.cell_tally(shield_cell, scores=["flux"]) -mcdc.tally.cs_tally(N_cs_bins=[10], size=[1], scores=["flux"]) +mcdc.tally.cs_tally( + N_cs_bins=[150], + cs_bin_size=[8], + x=np.linspace(0.0, 60.0, 31), + y=np.linspace(0.0, 100.0, 51), + scores=["flux"], +) # Setting -mcdc.setting(N_particle=50) +mcdc.setting(N_particle=1e5) # Run mcdc.run() diff --git a/examples/fixed_source/sphere_in_cube/input.py b/examples/fixed_source/sphere_in_cube/input.py index 61157306..215838f0 100644 --- a/examples/fixed_source/sphere_in_cube/input.py +++ b/examples/fixed_source/sphere_in_cube/input.py @@ -40,17 +40,25 @@ # ============================================================================= mcdc.tally.mesh_tally( scores=["fission"], - x=np.linspace(0.0, 4.0, 2), - y=np.linspace(0.0, 4.0, 2), - z=np.linspace(0.0, 4.0, 2), + x=np.linspace(0.0, 4.0, 41), + y=np.linspace(0.0, 4.0, 41), + # z=np.linspace(0.0, 4.0, 41), # t=np.linspace(0.0, 200.0, 2), ) - mcdc.tally.cell_tally(sphere_cell, scores=["fission"]) +mcdc.tally.cs_tally( + N_cs_bins=[1601], + cs_bin_size=[1], + x=np.linspace(0.0, 4.0, 41), + y=np.linspace(0.0, 4.0, 41), + scores=["fission"], +) + + # Setting -mcdc.setting(N_particle=100) +mcdc.setting(N_particle=1e5) mcdc.implicit_capture() # Run diff --git a/mcdc/card.py b/mcdc/card.py index 141679c2..880fe050 100644 --- a/mcdc/card.py +++ b/mcdc/card.py @@ -406,4 +406,4 @@ def __init__(self): self.z = np.array([-INF, INF]) self.N_bin = 1 self.N_cs_bins = 1 - self.size = 1 + self.cs_bin_size = 1 diff --git a/mcdc/kernel.py b/mcdc/kernel.py index e145264e..3819673e 100644 --- a/mcdc/kernel.py +++ b/mcdc/kernel.py @@ -20,6 +20,8 @@ from mcdc.constant import * from mcdc.print_ import print_error, print_msg +from shapely.geometry import LineString, box + # ============================================================================= # Domain Decomposition # ============================================================================= @@ -1990,18 +1992,27 @@ def score_cell_tally(P_arr, distance, tally, data, mcdc): SigmaF = get_MacroXS(XS_FISSION, material, P_arr, mcdc) score = flux * SigmaF - tally_bin[TALLY_SCORE, cell_idx] += score + tally_bin[TALLY_SCORE, cell_idx + i] += score @njit def score_cs_tally(P_arr, distance, tally, data, mcdc): + # Each time that this function is called, EVERY cs bin needs to be checked to see if the particle is in it. + # The particle needs to score into all the bins that it is within P = P_arr[0] tally_bin = data[TALLY] material = mcdc["materials"][P["material_ID"]] N_cs_bins = tally["filter"]["N_cs_bins"] - cs_bin_size = tally["filter"]["cs_bin_size"] + + # rescaling the size to be in terms of problem units, not mesh cells/pixels + Nx = len(tally["filter"]["x"]) - 1 + cs_bin_size = ( + tally["filter"]["cs_bin_size"] / Nx + ) # TODO: might cause problems in nonysmmetric problems + cs_centers = tally["filter"]["cs_centers"] stride = tally["stride"] + bin_idx = stride["tally"] # Particle 4D direction ux = P["ux"] @@ -2020,61 +2031,46 @@ def score_cs_tally(P_arr, distance, tally, data, mcdc): t_final = t + ut * distance # Check each coarse bin - for bin_idx in range(N_cs_bins): - center = cs_centers[bin_idx] - - # Bin edges - x_min, x_max = center[0] - cs_bin_size / 2, center[0] + cs_bin_size / 2 - y_min, y_max = center[1] - cs_bin_size / 2, center[1] + cs_bin_size / 2 - z_min, z_max = center[2] - cs_bin_size / 2, center[2] + cs_bin_size / 2 - - # Check for intersection with coarse bin - # If particle starts or ends inside the bin, it should score into the bin - - # TODO: handle case where particle crosses a corner, but doesn't start or end in the bin + for j in range(N_cs_bins): + center = (cs_centers[0][j], cs_centers[1][j]) + + # Last bin covers the whole problem + if j == N_cs_bins - 1: + cs_bin_size = INF + + distance_in_bin = min( + distance, + calculate_distance_in_coarse_bin( + P_arr, distance, center, cs_bin_size, mcdc + ), + ) - if ( - (x_min <= x <= x_max or x_min <= x_final <= x_max) - and (y_min <= y <= y_max or y_min <= y_final <= y_max) - and (z_min <= z <= z_max or z_min <= z_final <= z_max) - ): + # Calculate flux and other scores + flux = distance_in_bin * P["w"] + for i in range(tally["N_score"]): + score_type = tally["scores"][i] + if score_type == SCORE_FLUX: + score = flux + elif score_type == SCORE_DENSITY: + score = flux / physics.get_speed(P_arr, mcdc) + elif score_type == SCORE_TOTAL: + SigmaT = get_MacroXS(XS_TOTAL, material, P_arr, mcdc) + score = flux * SigmaT + elif score_type == SCORE_FISSION: + SigmaF = get_MacroXS(XS_FISSION, material, P_arr, mcdc) + score = flux * SigmaF - distance_in_bin = min( - distance, - calculate_distance_in_coarse_bin( - P_arr, distance, center, cs_bin_size, mcdc - ), - ) + tally_bin[TALLY_SCORE, bin_idx + j * tally["N_score"] + i] += score - # Calculate flux and other scores - flux = distance_in_bin * P["w"] - for i in range(tally["N_score"]): - score_type = tally["scores"][i] - if score_type == SCORE_FLUX: - score = flux - elif score_type == SCORE_DENSITY: - score = flux / physics.get_speed(P_arr, mcdc) - elif score_type == SCORE_TOTAL: - SigmaT = get_MacroXS(XS_TOTAL, material, P_arr, mcdc) - score = flux * SigmaT - elif score_type == SCORE_FISSION: - SigmaF = get_MacroXS(XS_FISSION, material, P_arr, mcdc) - score = flux * SigmaF - adapt.global_add( - tally_bin, (TALLY_SCORE, bin_idx + i), score - ) # TODO: fix this score indexing, this is wrong + # adapt.global_add( + # tally_bin, (TALLY_SCORE, bin_idx + i), score + # ) # TODO: fix this score indexing, this is wrong @njit def calculate_distance_in_coarse_bin(P_arr, distance, center, cs_bin_size, mcdc): - def intersect_plane(p0, p1, min_val, max_val, axis): - if p1[axis] != p0[axis]: # Avoid division by zero if line is parallel to plane - t_min = (min_val - p0[axis]) / (p1[axis] - p0[axis]) - t_max = (max_val - p0[axis]) / (p1[axis] - p0[axis]) - return [t_min, t_max] if t_min <= t_max else [t_max, t_min] - return [float("-inf"), float("inf")] # No intersection if parallel - P = P_arr[0] + # Particle 4D direction ux = P["ux"] uy = P["uy"] @@ -2091,33 +2087,51 @@ def intersect_plane(p0, p1, min_val, max_val, axis): z_final = z + uz * distance t_final = t + ut * distance - start = np.array([x, y, z]) - end = np.array([x_final, y_final, z_final]) + start = np.array([x, y]) + end = np.array([x_final, y_final]) - # Bin edges + # Edges of the coarse bin x_min, x_max = center[0] - cs_bin_size / 2, center[0] + cs_bin_size / 2 y_min, y_max = center[1] - cs_bin_size / 2, center[1] + cs_bin_size / 2 - z_min, z_max = center[2] - cs_bin_size / 2, center[2] + cs_bin_size / 2 - # Calculate intersection parameters for each axis - tx_min, tx_max = intersect_plane(start, end, x_min, x_max, 0) - ty_min, ty_max = intersect_plane(start, end, y_min, y_max, 1) - tz_min, tz_max = intersect_plane(start, end, z_min, z_max, 2) - - # Determine the entry and exit parameters - t_entry = max(tx_min, ty_min, tz_min) - t_exit = min(tx_max, ty_max, tz_max) - - # Check if there's a valid intersection - if t_entry > t_exit or t_exit < 0 or t_entry > 1: + def clip_segment_to_box(start, end, x_min, x_max, y_min, y_max): + t0, t1 = 0.0, 1.0 + + dx = end[0] - start[0] + dy = end[1] - start[1] + + def clip(p, q): + nonlocal t0, t1 + if p < 0: + t = q / p + if t > t1: + return False + if t > t0: + t0 = t + elif p > 0: + t = q / p + if t < t0: + return False + if t < t1: + t1 = t + elif q < 0: + return False + return True + + if clip(-dx, start[0] - x_min): + if clip(dx, x_max - start[0]): + if clip(-dy, start[1] - y_min): + if clip(dy, y_max - start[1]): + if t1 < 1: + end = start + t1 * np.array([dx, dy]) + if t0 > 0: + start = start + t0 * np.array([dx, dy]) + return np.linalg.norm(end - start) return 0.0 - # Calculate entry and exit points in 3D space - entry_point = start + t_entry * (end - start) - exit_point = start + t_exit * (end - start) + distance_inside = clip_segment_to_box(start, end, x_min, x_max, y_min, y_max) - # Return the distance between entry and exit points - return np.linalg.norm(exit_point - entry_point) + return distance_inside @njit @@ -2140,20 +2154,12 @@ def tally_reduce(data, mcdc): @njit def tally_accumulate(data, mcdc): - - # print(f'fixed_source_data = {data[TALLY][TALLY_SCORE][-1]}') - tally_bin = data[TALLY] - # print(data[0][0, 30000], data[0][0, 30001]) N_bin = tally_bin.shape[1] - # print(f'N_bin = {N_bin}') - for i in range(N_bin): # Accumulate score and square of score into sum and sum_sq score = tally_bin[TALLY_SCORE, i] - # if (score != 0 and i > 29999): - # print(f'score = {score}, i = {i}') tally_bin[TALLY_SUM, i] += score tally_bin[TALLY_SUM_SQ, i] += score * score @@ -2520,6 +2526,10 @@ def move_to_event(P_arr, data, mcdc): ID = cell["tally_IDs"][i] tally = mcdc["cell_tallies"][ID] score_cell_tally(P_arr, distance, tally, data, mcdc) + + # CS tallies + for tally in mcdc["cs_tallies"]: + score_cs_tally(P_arr, distance, tally, data, mcdc) if mcdc["setting"]["mode_eigenvalue"]: eigenvalue_tally(P_arr, distance, mcdc) diff --git a/mcdc/main.py b/mcdc/main.py index 298da724..6207c86a 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -2,8 +2,13 @@ import importlib.metadata import matplotlib.pyplot as plt import numba as nb +from scipy.stats.qmc import Halton +import cvxpy as cp from matplotlib import colors as mpl_colors +from matplotlib.patches import Rectangle +from shapely.geometry import Polygon, box +import scipy.fft as spfft # Parse command-line arguments # TODO: Will be inside run() once Python/Numba adapter is integrated @@ -190,6 +195,11 @@ def run(): loop_fixed_source(data_arr, mcdc_arr) mcdc["runtime_simulation"] = MPI.Wtime() - simulation_start + # Compressed sensing reconstruction - after the sim runs and gets results + N_cs_bins = mcdc["cs_tallies"]["filter"]["N_cs_bins"][0] + if N_cs_bins != 0: + cs_reconstruct(data, mcdc) + # Output: generate hdf5 output files output_start = MPI.Wtime() generate_hdf5(data, mcdc) @@ -203,6 +213,176 @@ def run(): closeout(mcdc) +def calculate_cs_overlap(corners, grid): + quadrilateral = Polygon(corners) + + # Get the dimensions of the grid + grid_height, grid_width = grid.shape + + # Create an array to hold the overlap values + overlap = np.zeros_like(grid, dtype=float) + + # Loop over each grid cell + for i in range(grid_height): + for j in range(grid_width): + # Define the current grid cell as a shapely box + cell = box(j - 0.5, i - 0.5, j + 0.5, i + 0.5) + + # Calculate the intersection area between the cell and the quadrilateral + intersection = cell.intersection(quadrilateral).area + + # Normalize by the cell area (which is 1 in this case) + overlap[i, j] = intersection + + overlap_1d = overlap.flatten() + + return overlap_1d + + +def calculate_cs_A(data, mcdc): + x_grid = mcdc["mesh_tallies"]["filter"]["x"][0] + y_grid = mcdc["mesh_tallies"]["filter"]["y"][0] + Nx = len(x_grid) - 1 + Ny = len(y_grid) - 1 + + N_cs_bins = mcdc["cs_tallies"]["filter"]["N_cs_bins"][0] + bin_size = mcdc["cs_tallies"]["filter"]["cs_bin_size"][0] + + S = [[] for _ in range(N_cs_bins)] + + [x_centers, y_centers] = mcdc["cs_tallies"]["filter"]["cs_centers"][0] + + # Calculate the overlap grid for each bin, and flatten into a row of S + for ibin in range(N_cs_bins): + bin_x_min = x_centers[ibin] - bin_size / 2 + bin_x_max = x_centers[ibin] + bin_size / 2 + bin_y_min = y_centers[ibin] - bin_size / 2 + bin_y_max = y_centers[ibin] + bin_size / 2 + + overlap = np.zeros((len(y_grid) - 1, len(x_grid) - 1)) + + for i in range(len(y_grid) - 1): + for j in range(len(x_grid) - 1): + cell_x_min = x_grid[j] + cell_x_max = x_grid[j + 1] + cell_y_min = y_grid[i] + cell_y_max = y_grid[i + 1] + + # Calculate overlap in x and y directions + overlap_x = max( + 0, min(bin_x_max, cell_x_max) - max(bin_x_min, cell_x_min) + ) + overlap_y = max( + 0, min(bin_y_max, cell_y_max) - max(bin_y_min, cell_y_min) + ) + + # Calculate fractional overlap + cell_area = (cell_x_max - cell_x_min) * (cell_y_max - cell_y_min) + overlap[i, j] = (overlap_x * overlap_y) / cell_area + + S[ibin] = overlap.flatten() + + print(f"N_cs_bin = {N_cs_bins}") + S[-1] = np.ones(Nx * Ny) + S = np.array(S) + S_summed = np.sum(S, axis=0).reshape(Ny, Nx) + plt.imshow(S_summed) + plt.colorbar() + plt.title("S_Summed") + plt.show() + + print(S.shape[1]) + assert S.shape[1] == Nx * Ny, "Size of S must match Nx * Ny." + assert ( + S.shape[1] == mcdc["cs_tallies"]["N_bin"][0] + ), "Size of S must match number of cells in desired mesh tally" + np.save("sphere_S.npy", S) + # TODO: can this be done in a different way? idk + # Construct the DCT matrix T + idct_basis_x = spfft.idct(np.identity(Nx), axis=0) + idct_basis_y = spfft.idct(np.identity(Ny), axis=0) + + T_inv = np.kron(idct_basis_y, idct_basis_x) + A = S @ T_inv + return A, T_inv + + +def calculate_cs_sparse_solution(data, mcdc, A, b): + print(f"A = {A}") + print(f"b = {b}") + N_fine_cells = mcdc["cs_tallies"]["N_bin"][0] + print(f"N_fine_cells = {N_fine_cells}") + + # setting up the problem with CVXPY + vx = cp.Variable(N_fine_cells) + + # Basis pursuit denoising + l = 0 + objective = cp.Minimize(0.5 * cp.norm(A @ vx - b, 2) + l * cp.norm(vx, 1)) + prob = cp.Problem(objective) + result = prob.solve(verbose=False) + + # # Basis pursuit + # objective = cp.Minimize(cp.norm(vx, 1)) + # constraints = [A @ vx == b] + # prob = cp.Problem(objective, constraints) + # result = prob.solve(verbose=True) + # print(f'vx.value = {vx.value}') + + # formatting the sparse solution + sparse_solution = np.array(vx.value).squeeze() + + return sparse_solution + + +def cs_reconstruct(data, mcdc): + tally_bin = data[TALLY] + + print(tally_bin.shape) + + tally = mcdc["cs_tallies"][0] + stride = tally["stride"] + bin_idx = stride["tally"] + N_cs_bins = tally["filter"]["N_cs_bins"] + Nx = len(mcdc["mesh_tallies"]["filter"]["x"][0]) - 1 + Ny = len(mcdc["mesh_tallies"]["filter"]["y"][0]) - 1 + + b = tally_bin[TALLY_SUM, bin_idx : bin_idx + N_cs_bins] + + print(f"measurements b = {b}") + + A, T_inv = calculate_cs_A(data, mcdc) + x = calculate_cs_sparse_solution(data, mcdc, A, b) + + np.save("sparse_solution.npy", x) + print(f"sparse solution shape = {x.shape}") + print(x) + + recon = T_inv @ x + print(f"recon.shape = {recon.shape}") + print(f"recon = {recon}") + + recon_reshaped = recon.reshape(Ny, Nx) + + plt.imshow(recon_reshaped) + plt.title("Ny, Nx") + plt.colorbar() + plt.show() + + return recon + # reconstruction + + # # Find the sparse solution, and then find the reconstruction + # sparse_solution[res] = finding_sparse_solution(A[res], fluxes[res].size, b, bpdn_lambda) + # reconstruction[res] = np.reshape(un_matrix[res] @ sparse_solution[res], fluxes[res].shape) + # rescaled_recons[res] = downsample_to_resolution(reconstruction[res], input_flux.shape) + + # if return_centers: + # return reconstruction, input_flux, rescaled_recons, bin_centers[0] + # else: + # return reconstruction, input_flux, rescaled_recons + + # ============================================================================= # utilities for handling discrepancies between input and program types # ============================================================================= @@ -217,11 +397,6 @@ def copy_field(dst, src, name): else: data = getattr(src, name) - # print(f'dst, src, name = {dst, src, name}') - # print(f'dst = {dst.dtype.names}') - # print(f'name = {name}') - # print(f'dst[name] = {dst[name]}') - if isinstance(dst[name], np.ndarray): if isinstance(data, np.ndarray) and dst[name].shape != data.shape: for dim in data.shape: @@ -406,6 +581,45 @@ def dd_mesh_bounds(idx): return mesh_xn, mesh_xp, mesh_yn, mesh_yp, mesh_zn, mesh_zp +def generate_cs_centers(mcdc, N_dim=2, seed=123456789): + N_cs_bins = int(mcdc["cs_tallies"]["filter"]["N_cs_bins"]) + x_lims = ( + mcdc["cs_tallies"]["filter"]["x"][0][-1], + mcdc["cs_tallies"]["filter"]["x"][0][0], + ) + y_lims = ( + mcdc["cs_tallies"]["filter"]["y"][0][-1], + mcdc["cs_tallies"]["filter"]["y"][0][0], + ) + + # Generate Halton sequence according to the seed + halton_seq = Halton(d=N_dim, seed=seed) + points = halton_seq.random(n=N_cs_bins) + + # Extract x and y coordinates as tuples separately, scaled to the problem dimensions + x_coords = tuple(points[:, 0] * (x_lims[1] - x_lims[0]) + x_lims[0]) + y_coords = tuple(points[:, 1] * (y_lims[1] - y_lims[0]) + y_lims[0]) + + # # Generate the centers of the cells + # x_centers = np.linspace(0.05, 3.95, 40) + # y_centers = np.linspace(0.05, 3.95, 40) + + # # Create the meshgrid for all cell centers + # X, Y = np.meshgrid(x_centers, y_centers) + + # # Flatten the arrays to get the list of coordinates + # x_coords = X.flatten() + # y_coords = Y.flatten() + + # x_coords_list = x_coords.tolist() + # y_coords_list = y_coords.tolist() + + # x_coords_list.append(2.0) + # y_coords_list.append(2.0) + + return (x_coords, y_coords) + + def prepare(): """ Preparing the MC transport simulation: @@ -928,6 +1142,13 @@ def prepare(): # Direct assignment copy_field(mcdc["cs_tallies"][i], input_deck.cs_tallies[i], "N_bin") + mcdc["cs_tallies"][i]["filter"]["N_cs_bins"] = input_deck.cs_tallies[ + i + ].N_cs_bins[0] + mcdc["cs_tallies"][i]["filter"]["cs_bin_size"] = input_deck.cs_tallies[ + i + ].cs_bin_size[0] + # Filters (variables with possible different sizes) if not input_deck.technique["domain_decomposition"]: for name in ["x", "y", "z", "t", "mu", "azi", "g"]: @@ -936,21 +1157,7 @@ def prepare(): input_deck.cs_tallies[i], name ) - # else: # decomposed mesh filters - # mxn, mxp, myn, myp, mzn, mzp = dd_mesh_bounds(i) - - # # Filters - # new_x = input_deck.mesh_tallies[i].x[mxn:mxp] - # new_y = input_deck.mesh_tallies[i].y[myn:myp] - # new_z = input_deck.mesh_tallies[i].z[mzn:mzp] - # mcdc["mesh_tallies"][i]["filter"]["x"] = new_x - # mcdc["mesh_tallies"][i]["filter"]["y"] = new_y - # mcdc["mesh_tallies"][i]["filter"]["z"] = new_z - # for name in ["t", "mu", "azi", "g"]: - # N = len(getattr(input_deck.mesh_tallies[i], name)) - # mcdc["mesh_tallies"][i]["filter"][name][:N] = getattr( - # input_deck.mesh_tallies[i], name - # ) + mcdc["cs_tallies"][i]["filter"]["cs_centers"] = generate_cs_centers(mcdc) # Set tally scores N_score = len(input_deck.cs_tallies[i].scores) @@ -970,45 +1177,12 @@ def prepare(): score_type = SCORE_NET_CURRENT mcdc["cs_tallies"][i]["scores"][j] = score_type - # Filter grid sizes - Nmu = len(input_deck.cs_tallies[i].mu) - 1 - N_azi = len(input_deck.cs_tallies[i].azi) - 1 - Ng = len(input_deck.cs_tallies[i].g) - 1 - Nx = len(input_deck.cs_tallies[i].x) - 1 - Ny = len(input_deck.cs_tallies[i].y) - 1 - Nz = len(input_deck.cs_tallies[i].z) - 1 - Nt = len(input_deck.cs_tallies[i].t) - 1 - # Update N_bin mcdc["cs_tallies"][i]["N_bin"] *= N_score - # Filter strides - stride = N_score - if Nz > 1: - mcdc["cs_tallies"][i]["stride"]["z"] = stride - stride *= Nz - if Ny > 1: - mcdc["cs_tallies"][i]["stride"]["y"] = stride - stride *= Ny - if Nx > 1: - mcdc["cs_tallies"][i]["stride"]["x"] = stride - stride *= Nx - if Nt > 1: - mcdc["cs_tallies"][i]["stride"]["t"] = stride - stride *= Nt - if Ng > 1: - mcdc["cs_tallies"][i]["stride"]["g"] = stride - stride *= Ng - if N_azi > 1: - mcdc["cs_tallies"][i]["stride"]["azi"] = stride - stride *= N_azi - if Nmu > 1: - mcdc["cs_tallies"][i]["stride"]["mu"] = stride - stride *= Nmu - # Set tally stride and accumulate total tally size mcdc["cs_tallies"][i]["stride"]["tally"] = tally_size - tally_size += mcdc["cs_tallies"][i]["N_bin"] + tally_size += mcdc["cs_tallies"][i]["filter"]["N_cs_bins"] # Set tally data if not input_deck.technique["uq"]: @@ -1404,7 +1578,10 @@ def prepare(): def cardlist_to_h5group(dictlist, input_group, name): - main_group = input_group.create_group(name + "s") + if name[-1] != "s": + main_group = input_group.create_group(name + "s") + else: + main_group = input_group.create_group(name) for item in dictlist: group = main_group.create_group(name + "_%i" % getattr(item, "ID")) card_to_h5group(item, group) @@ -1430,7 +1607,10 @@ def card_to_h5group(card, group): def dictlist_to_h5group(dictlist, input_group, name): - main_group = input_group.create_group(name + "s") + if name[-1] != "s": + main_group = input_group.create_group(name + "s") + else: + main_group = input_group.create_group(name) for item in dictlist: group = main_group.create_group(name + "_%i" % item["ID"]) dict_to_h5group(item, group) @@ -1525,11 +1705,12 @@ def generate_hdf5(data, mcdc): input_deck.mesh_tallies, input_group, "mesh_tallies" ) cardlist_to_h5group( - input_deck.surface_tallies, input_group, "surface_tally" + input_deck.surface_tallies, input_group, "surface_tallies" ) cardlist_to_h5group( input_deck.cell_tallies, input_group, "cell_tallies" ) + cardlist_to_h5group(input_deck.cs_tallies, input_group, "cs_tallies") dict_to_h5group(input_deck.setting, input_group.create_group("setting")) dict_to_h5group( input_deck.technique, input_group.create_group("technique") @@ -1670,34 +1851,72 @@ def generate_hdf5(data, mcdc): N_bin = tally["N_bin"] start = tally["stride"]["tally"] tally_bin = data[TALLY][:, start : start + N_bin] + tally_bin = tally_bin.reshape(shape) + + # Roll tally so that score is in the front + tally_bin = np.rollaxis(tally_bin, 1, 0) + + # Iterate over scores + for i in range(N_score): + score_type = tally["scores"][i] + score_tally_bin = np.squeeze(tally_bin[i]) + if score_type == SCORE_FLUX: + score_name = "flux" + elif score_type == SCORE_NET_CURRENT: + score_name = "net-current" + elif score_type == SCORE_FISSION: + score_name = "fission" + group_name = "tallies/cell_tally_%i/%s/" % (ID, score_name) - # print(f'data = {data[TALLY][2]}') - # if data[TALLY][1].all() == data[TALLY][2].all: - # print('hell yeah') - # print(f'data keys = {data[TALLY].dtype.names}') + mean = score_tally_bin[TALLY_SUM] + sdev = score_tally_bin[TALLY_SUM_SQ] - # print(f'tally_bin = {tally_bin}') + f.create_dataset(group_name + "mean", data=mean) + f.create_dataset(group_name + "sdev", data=sdev) + if mcdc["technique"]["uq"]: + mc_var = score_tally_bin[TALLY_UQ_BATCH_VAR] + tot_var = score_tally_bin[TALLY_UQ_BATCH] + uq_var = tot_var - mc_var + f.create_dataset(group_name + "uq_var", data=uq_var) + + # CS tallies + for ID, tally in enumerate(mcdc["cs_tallies"]): + if mcdc["technique"]["iQMC"]: + break + N_cs_bins = tally["filter"]["N_cs_bins"] + # Shape + N_score = tally["N_score"] + + if not mcdc["technique"]["uq"]: + shape = (3, N_cs_bins, N_score) + else: + shape = (5, N_cs_bins, N_score) + + # Reshape tally + start = tally["stride"]["tally"] + tally_bin = data[TALLY][:, start : start + N_cs_bins] tally_bin = tally_bin.reshape(shape) # Roll tally so that score is in the front - tally_bin = np.rollaxis(tally_bin, 1, 0) + tally_bin = np.rollaxis(tally_bin, 2, 0) # Iterate over scores for i in range(N_score): score_type = tally["scores"][i] score_tally_bin = np.squeeze(tally_bin[i]) - # print(f'score_tally_bin = {score_tally_bin}') if score_type == SCORE_FLUX: score_name = "flux" elif score_type == SCORE_NET_CURRENT: score_name = "net-current" elif score_type == SCORE_FISSION: score_name = "fission" - group_name = "tallies/cell_tally_%i/%s/" % (ID, score_name) + group_name = "tallies/cs_tally_%i/%s/" % (ID, score_name) + + center_points = tally["filter"]["cs_centers"] + f.create_dataset(group_name + "center_points", data=center_points) mean = score_tally_bin[TALLY_SUM] - # print(f'ID = {ID}, score_name = {score_name}, mean = {mean}') sdev = score_tally_bin[TALLY_SUM_SQ] f.create_dataset(group_name + "mean", data=mean) diff --git a/mcdc/tally.py b/mcdc/tally.py index db75e917..d035b135 100644 --- a/mcdc/tally.py +++ b/mcdc/tally.py @@ -207,7 +207,7 @@ def cell_tally(cell, scores=["flux"]): def cs_tally( N_cs_bins=10, - size=1, + cs_bin_size=1, x=np.array([-INF, INF]), y=np.array([-INF, INF]), z=np.array([-INF, INF]), @@ -223,14 +223,16 @@ def cs_tally( # Set ID card.ID = len(global_.input_deck.cs_tallies) - card.N_cs_bins = N_cs_bins - card.size = size # Set mesh card.x = x card.y = y card.z = z + # Set bin properties + card.N_cs_bins = N_cs_bins + card.cs_bin_size = [cs_bin_size[0] / (len(x) - 1) * (x[-1] - x[0])] + # Set other filters card.t = t card.mu = mu diff --git a/mcdc/type_.py b/mcdc/type_.py index 7fd7bbeb..e9a031a4 100644 --- a/mcdc/type_.py +++ b/mcdc/type_.py @@ -900,7 +900,6 @@ def make_type_cs_tally(input_deck): struct = [] # Maximum numbers of mesh and filter grids and scores - Nmax_cs_bins = 2 Nmax_x = 2 Nmax_y = 2 Nmax_z = 2 @@ -909,8 +908,8 @@ def make_type_cs_tally(input_deck): Nmax_azi = 2 Nmax_g = 2 Nmax_score = 1 + N_cs_centers = 1 for card in input_deck.cs_tallies: - Nmax_cs_bins = max(Nmax_cs_bins, len(card.N_cs_bins)) Nmax_x = max(Nmax_x, len(card.x)) Nmax_y = max(Nmax_y, len(card.y)) Nmax_z = max(Nmax_z, len(card.z)) @@ -919,6 +918,7 @@ def make_type_cs_tally(input_deck): Nmax_azi = max(Nmax_azi, len(card.azi)) Nmax_g = max(Nmax_g, len(card.g)) Nmax_score = max(Nmax_score, len(card.scores)) + N_cs_centers = card.N_cs_bins[0] # # reduce tally sizes for subdomains # if input_deck.technique["domain_decomposition"]: @@ -926,9 +926,16 @@ def make_type_cs_tally(input_deck): # Set the filter filter_ = [ - ("N_cs_bins", int64), + ("N_cs_bins", int), ("cs_bin_size", float64), - ("cs_centers", float64, (Nmax_cs_bins,)), + ( + "cs_centers", + float64, + ( + 2, + N_cs_centers, + ), + ), ("x", float64, (Nmax_x,)), ("y", float64, (Nmax_y,)), ("z", float64, (Nmax_z,)), @@ -937,6 +944,7 @@ def make_type_cs_tally(input_deck): ("azi", float64, (Nmax_azi,)), ("g", float64, (Nmax_g,)), ] + struct += [("filter", filter_)] # Tally strides @@ -950,12 +958,17 @@ def make_type_cs_tally(input_deck): ("x", int64), ("y", int64), ("z", int64), + # ("N_cs_bins", int64), # TODO: get rid of this line? ] struct += [("stride", stride)] - # Total number of bins + # Total number of bins (will be used for the reconstruction) + # TODO: Might be able to get rid of this (just get N_bin from the mesh) struct += [("N_bin", int64)] + # Number of compressed sensing bins + # struct += [("N_cs_bins", int64)] + # Scores struct += [("N_score", int64), ("scores", int64, (Nmax_score,))] From af53369189b8b10b828b56e23774f599cbc8fa8f Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Wed, 18 Dec 2024 14:32:53 -0700 Subject: [PATCH 3/9] cs kinda maybe works, but not in numba yet --- .../sphere_in_cube/center_points.npy | Bin 3328 -> 25744 bytes examples/fixed_source/sphere_in_cube/input.py | 9 +- .../fixed_source/sphere_in_cube/process.py | 48 +++++++- .../sphere_in_cube/sparse_solution.npy | Bin 12928 -> 12928 bytes .../fixed_source/sphere_in_cube/sphere_S.npy | Bin 2560128 -> 20492928 bytes mcdc/card.py | 2 +- mcdc/kernel.py | 33 +++--- mcdc/main.py | 108 +++++++++--------- mcdc/tally.py | 12 +- mcdc/type_.py | 2 +- 10 files changed, 132 insertions(+), 82 deletions(-) diff --git a/examples/fixed_source/sphere_in_cube/center_points.npy b/examples/fixed_source/sphere_in_cube/center_points.npy index 674a38b94e8344798bd49d8a95eb2f036e9244cc..0fef328c9483617d3fb39271e95cdb0ab4b66783 100644 GIT binary patch literal 25744 zcmeHPy-HkR5WSB7>rY-`yG_6%#t=dX+^Nzfq)Cw~NZd_|5W^bMggiy6U(FcyYar?dDiYc z?>+4-wL87_{@4EM=XdMH;KZd>9^Y-iQL3~h;4e}1-|BfR6IPy;-K8?Jy`2X|Bzlglc z$h(TX>&Ux_yxV&4F?y8_KHkch`sWk%&n4=gYg|2VBJw69Zz}SpB5ykKW+HDk@>-GC zioChVn~%JO$XkrO#mKuCBlYv|gZlY%%IDAP34gy{Ct3gKALd;25BF*MFZ&m3B-#JD zPqKgJ`-lA=*gvy>w)b(q|N8s`=MOmlVike&FaG|-`73*isw&R^d0k-t%>J44_f^ID zd#-<&FL3?HeSzz5T)(u6!1YW2J#hWk=T*3V?)@V7A8`MM_08PBVOJdcgjf z{j=2r?*H@mY4*?TpY2KD{!?Fn;Qn3if3|%J-2d$F)7(GK{rBb%|L^$)>-KMW7+as0 z*Td`NemN(|*yfk>dJNwyINEb}P|lfV^%$;aa5UdIEa!8xdbm#?mGiuet&hp;;XZR* z&OtLaAI|GBoOkDF_3xydqtEK$&)aD^chA_Kzq}q^C(p`#1&qx{@_Kl`cV6y!U~K(g zUJv)%i*i2(WAop<9$qIe%e^9u%}4TjxL;hA`&by8f8_OWzql^<*f2K#$m`*LaZ~R9 zVQl`9*Tendw%nV<*!&}}hyB`ZouA{~bTGA7a6cEvyXj!n(#|!408tPi3IaqyfG7wM z1p%TUKokUsf&ftvAPNFRL4YU-5Cs9EAV3rZh=Kr75FiQyL_vTk2oMDUq98yN1c-tF zQ4k;s0z^T8C)mirqSn*w<~24%3CQjVrTa~-^1j_wO(Z1V?sJ-l8{hktNv zs)zf1C5BH5l^N+k9UN48|`8hV#!+*Dx F{sW>d{9gb7 literal 3328 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 diff --git a/examples/fixed_source/sphere_in_cube/sphere_S.npy b/examples/fixed_source/sphere_in_cube/sphere_S.npy index 278fe8a065ad26382bc12748baadb29390d6e7ee..1d4ef27b0a912fca0b7a8d156ca921ec97c04bca 100644 GIT binary patch delta 26467 zcmeHPF^^O?5YC=Xuq4fjo|bx-BFae@$UlQ?QbR?PCRJLlf;3Sol$3}_$u$%}q;yA- zNGA{wd**$!9-plrcefwh zy?XHG&QH&79NwCK_!$4ryVAR^^f=J2+zL#!hcDmUnS2rd{y2^-9~SE?Y-!x{t4^Bm z2C)@NJIlplc9nE}eSD@y+fot(u(?{AXwK0I&@=vCS>&xMX-<^%fM%#B3wLk`7VlLp zC=}W9K*khlD_B@V?j=TP5r%N31I?exDD5Sffbr1YPIHb|3Y-OxPebQFWiw6FB_(AB z8jt!pxq~njy{f0+X2nzoQ&pOwbV2H}_qkYXz_d-12+}ad!wzoGmFe0`7z>ZOy`AP9 zqZGZ0WtnQ+2~+JMgpva?aT2oDR7i|jeW(YfIz^HPgV7teosa(i;XZamb&4N!|Tad7Z*hNp4OxGe#GtY9_7UkMtQzQ}YMQD3fwi9_ib{MaY-HW&v>DHR%lQyN5 z5xA+eP1}{VDA$HQ+>5B}tZXOuBFiYXDK4#cWvg2)c0qG3ma|;81=aHQ6@G(D*t^KK zr}mKSLm~^kaKT=rQW4T|LmFZ`Hx}Mx?~qa2S^V^>`u5C^Fv@2G0#r6onaQG!NPws! z4?gSV3C#>tX4p34(r7xnEp(K^ouQs@IoKnyx4wCpkj)I2d z!XXfPigVmsXEati{~M$1$G@`UE3k4uN%-pBwygQk5|iUA;GHz(1I4qWmo!R#6&aAT z2L(s}|v5TH8nXW~gW}fA;EvPngkc{>7YFd}3Xjt}9#MrOr_^S_f*QyjHJc4wu zaMx_=G^n79-2B63KRP-^`}B5SvPmA8SKA7GcVjkmpBgk7 z7fyj`T$qQ{)jyeEhMY_3Lty}8jdl!kcbzVCo*kWcr{QD|6dq9}AA<($qMGnB5KZZp z&G9b!vt+t1@djde{gKUW(JtCka|!duC3vY4O>+X1#5n^k^)lh6L$7MNjm({^4&+r2 zcL!R!_`|1ZsBUN4rb%3lVT?d0CV;hXFTqBA+vy(0D@9F8HpdP(+Ot?N7KA$7n0}I@{!~3*Ti>; zYe1W&k)F2W_J?-=C}rkCbt&g9(?%yiE!u2(d)n@4d&Pg~T*)fwb>MLGJgNdI4HOGf z7EMcWxH;S$Zl1Oeal*|>p5=Qin)XW;r$vL5ERFQE-P88vFLQg^?rD1^=vlr+)8J|R zv^~E`?IlR@ iv|aKNn8Z3d&&<`*M2j1XfXCmzxcPSR@cxUN)Bgb{XC(Ci literal 2560128 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 Date: Thu, 19 Dec 2024 10:38:31 -0700 Subject: [PATCH 4/9] compressed sensing smoother integration, tested on sphere --- .../sphere_in_cube/center_points.npy | Bin 25744 -> 0 bytes examples/fixed_source/sphere_in_cube/input.py | 4 +- .../fixed_source/sphere_in_cube/process.py | 88 +++++++-------- .../sphere_in_cube/sparse_solution.npy | Bin 12928 -> 0 bytes .../fixed_source/sphere_in_cube/sphere_S.npy | Bin 20492928 -> 0 bytes mcdc/main.py | 101 +++++------------- mcdc/tally.py | 5 - mcdc/type_.py | 2 + 8 files changed, 77 insertions(+), 123 deletions(-) delete mode 100644 examples/fixed_source/sphere_in_cube/center_points.npy delete mode 100644 examples/fixed_source/sphere_in_cube/sparse_solution.npy delete mode 100644 examples/fixed_source/sphere_in_cube/sphere_S.npy diff --git a/examples/fixed_source/sphere_in_cube/center_points.npy b/examples/fixed_source/sphere_in_cube/center_points.npy deleted file mode 100644 index 0fef328c9483617d3fb39271e95cdb0ab4b66783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25744 zcmeHPy-HkR5WSB7>rY-`yG_6%#t=dX+^Nzfq)Cw~NZd_|5W^bMggiy6U(FcyYar?dDiYc z?>+4-wL87_{@4EM=XdMH;KZd>9^Y-iQL3~h;4e}1-|BfR6IPy;-K8?Jy`2X|Bzlglc z$h(TX>&Ux_yxV&4F?y8_KHkch`sWk%&n4=gYg|2VBJw69Zz}SpB5ykKW+HDk@>-GC zioChVn~%JO$XkrO#mKuCBlYv|gZlY%%IDAP34gy{Ct3gKALd;25BF*MFZ&m3B-#JD zPqKgJ`-lA=*gvy>w)b(q|N8s`=MOmlVike&FaG|-`73*isw&R^d0k-t%>J44_f^ID zd#-<&FL3?HeSzz5T)(u6!1YW2J#hWk=T*3V?)@V7A8`MM_08PBVOJdcgjf z{j=2r?*H@mY4*?TpY2KD{!?Fn;Qn3if3|%J-2d$F)7(GK{rBb%|L^$)>-KMW7+as0 z*Td`NemN(|*yfk>dJNwyINEb}P|lfV^%$;aa5UdIEa!8xdbm#?mGiuet&hp;;XZR* z&OtLaAI|GBoOkDF_3xydqtEK$&)aD^chA_Kzq}q^C(p`#1&qx{@_Kl`cV6y!U~K(g zUJv)%i*i2(WAop<9$qIe%e^9u%}4TjxL;hA`&by8f8_OWzql^<*f2K#$m`*LaZ~R9 zVQl`9*Tendw%nV<*!&}}hyB`ZouA{~bTGA7a6cEvyXj!n(#|!408tPi3IaqyfG7wM z1p%TUKokUsf&ftvAPNFRL4YU-5Cs9EAV3rZh=Kr75FiQyL_vTk2oMDUq98yN1c-tF zQ4k;s0z^T8C)mirqSn*w<~24%3CQjVrTa~-^1j_wO(Z1V?sJ-l8{hktNv zs)zf1C5BH5l^N+k9UN48|`8hV#!+*Dx F{sW>d{9gb7 diff --git a/examples/fixed_source/sphere_in_cube/input.py b/examples/fixed_source/sphere_in_cube/input.py index d53a4e0d..3a858582 100644 --- a/examples/fixed_source/sphere_in_cube/input.py +++ b/examples/fixed_source/sphere_in_cube/input.py @@ -49,8 +49,8 @@ mcdc.tally.cell_tally(sphere_cell, scores=["fission"]) mcdc.tally.cs_tally( - N_cs_bins=[1601], - cs_bin_size=np.array([1.0, 1.0]), + N_cs_bins=[150], + cs_bin_size=np.array([3.0, 3.0]), x=np.linspace(0.0, 4.0, 41), y=np.linspace(0.0, 4.0, 41), scores=["fission"], diff --git a/examples/fixed_source/sphere_in_cube/process.py b/examples/fixed_source/sphere_in_cube/process.py index fdf3e1cd..d7896a54 100644 --- a/examples/fixed_source/sphere_in_cube/process.py +++ b/examples/fixed_source/sphere_in_cube/process.py @@ -4,56 +4,58 @@ import scipy.fft as spfft import cvxpy as cp -# Load results -with h5py.File("output.h5", "r") as f: - # trying to compare cs results and mesh results - center_points = np.load("center_points.npy") - cs_results = f["tallies"]["cs_tally_0"]["fission"]["mean"][:] - cs_alphas = cs_results[:-1] / np.max(cs_results[:-1]) - # plt.scatter(center_points[0][:-1], center_points[1][:-1], alpha=cs_alphas) - # plt.show() +# Note: there are some lines in main.py with np.save(...) that I added +# for ease of post-processing, like getting the center points used and +# the sampling matrix S. None are required for the input file and this +# script to run, but may be useful for debugging purposes - mesh_results = f["tallies"]["mesh_tally_0"]["fission"]["mean"][:] - plt.imshow(cs_results[:-1].reshape(mesh_results.shape)) - plt.title("cs") - plt.show() - plt.imshow(mesh_results) - plt.title("mesh") +with h5py.File("output.h5", "r") as f: + S = f["tallies"]["cs_tally_0"]["S"][:] + recon = f["tallies"]["cs_tally_0"]["fission"]["reconstruction"] + plt.imshow(recon) + plt.title("Reconstruction, $\lambda$ = 0.5") # assuming l in main.py remains at 0.5 + plt.colorbar() plt.show() - print(f"cs_results = {cs_results}") - print(f"sh_results = {mesh_results.flatten()}") + cs_results = f["tallies"]["cs_tally_0"]["fission"]["mean"][:] + # mesh_results = f["tallies"]["mesh_tally_0"]["fission"]["mean"][:] + # plt.imshow(mesh_results) + # plt.title("mesh results") + # plt.show() Nx = 40 Ny = 40 -S = np.load("sphere_S.npy") -mesh_b = S @ mesh_results.flatten() -cs_b = cs_results - +N_fine_cells = Nx * Ny +# Can use this for post-processing +# mesh_b = S @ mesh_results.flatten() # b = mesh_b -# print(f'shape of mesh b = {mesh_b.shape}') -# print(f'shape of cs b = {cs_b.shape}') - -# idct_basis_x = spfft.idct(np.identity(Nx), axis=0) -# idct_basis_y = spfft.idct(np.identity(Ny), axis=0) - -# T_inv = np.kron(idct_basis_y, idct_basis_x) -# A = S @ T_inv -# N_fine_cells = 1600 - -# vx = cp.Variable(N_fine_cells) -# l = 0 -# objective = cp.Minimize(0.5 * cp.norm(A @ vx - b, 2) + l * cp.norm(vx, 1)) -# prob = cp.Problem(objective) -# result = prob.solve(verbose=False) -# sparse_solution = np.array(vx.value).squeeze() - -# recon = T_inv @ sparse_solution -# recon_reshaped = recon.reshape(Ny, Nx) - -# plt.imshow(recon_reshaped) -# plt.title('reconstruction') -# plt.show() +# Use this for analyzing the in-situ results +cs_b = cs_results +b = cs_b + +# Constructing T and A +idct_basis_x = spfft.idct(np.identity(Nx), axis=0) +idct_basis_y = spfft.idct(np.identity(Ny), axis=0) + +T_inv = np.kron(idct_basis_y, idct_basis_x) +A = S @ T_inv + +# Basis pursuit denoising solver - change l to get different results +vx = cp.Variable(N_fine_cells) +l = 10 +objective = cp.Minimize(0.5 * cp.norm(A @ vx - b, 2) + l * cp.norm(vx, 1)) +prob = cp.Problem(objective) +result = prob.solve(verbose=False) +sparse_solution = np.array(vx.value).squeeze() + +# Obtaining the reconstruction +recon = T_inv @ sparse_solution +recon_reshaped = recon.reshape(Ny, Nx) + +plt.imshow(recon_reshaped) +plt.title(f"Reconstruction, $\lambda$ = {l}") +plt.colorbar() +plt.show() diff --git a/examples/fixed_source/sphere_in_cube/sparse_solution.npy b/examples/fixed_source/sphere_in_cube/sparse_solution.npy deleted file mode 100644 index a8121470298d80f848725caaa2760909bd1990a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12928 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 qV|tWF-^eJ$a3TG3B#5WrY4#1gv0Jh> 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 z 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 diff --git a/mcdc/main.py b/mcdc/main.py index 8882a396..bdc5a274 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -93,7 +93,7 @@ def run(): loop_fixed_source(data_arr, mcdc_arr) mcdc["runtime_simulation"] = MPI.Wtime() - simulation_start - # Compressed sensing reconstruction - after the sim runs and gets results + # Compressed sensing reconstruction N_cs_bins = mcdc["cs_tallies"]["filter"]["N_cs_bins"][0] if N_cs_bins != 0: cs_reconstruct(data, mcdc) @@ -151,7 +151,6 @@ def calculate_cs_A(data, mcdc): [x_centers, y_centers] = mcdc["cs_tallies"]["filter"]["cs_centers"][0] x_centers[-1] = (x_grid[-1] + x_grid[0]) / 2 y_centers[-1] = (y_grid[-1] + y_grid[0]) / 2 - np.save("center_points.npy", mcdc["cs_tallies"]["filter"]["cs_centers"][0]) # Calculate the overlap grid for each bin, and flatten into a row of S for ibin in range(N_cs_bins): @@ -190,19 +189,13 @@ def calculate_cs_A(data, mcdc): S[ibin] = overlap.flatten() S = np.array(S) - - S_summed = np.sum(S, axis=0).reshape(Ny, Nx) - plt.imshow(S_summed) - plt.colorbar() - plt.title("S_Summed") - plt.show() + mcdc["cs_tallies"]["filter"]["cs_S"] = S assert np.allclose(S[-1], np.ones(Nx * Ny)), "Last row of S must be all ones" assert S.shape[1] == Nx * Ny, "Size of S must match Nx * Ny." assert ( S.shape[1] == mcdc["cs_tallies"]["N_bin"][0] ), "Size of S must match number of cells in desired mesh tally" - np.save("sphere_S.npy", S) # TODO: can this be done in a different way? idk # Construct the DCT matrix T @@ -221,7 +214,7 @@ def calculate_cs_sparse_solution(data, mcdc, A, b): vx = cp.Variable(N_fine_cells) # Basis pursuit denoising - l = 0 + l = 0.5 objective = cp.Minimize(0.5 * cp.norm(A @ vx - b, 2) + l * cp.norm(vx, 1)) prob = cp.Problem(objective) result = prob.solve(verbose=False) @@ -241,9 +234,6 @@ def calculate_cs_sparse_solution(data, mcdc, A, b): def cs_reconstruct(data, mcdc): tally_bin = data[TALLY] - - print(tally_bin.shape) - tally = mcdc["cs_tallies"][0] stride = tally["stride"] bin_idx = stride["tally"] @@ -253,38 +243,13 @@ def cs_reconstruct(data, mcdc): b = tally_bin[TALLY_SUM, bin_idx : bin_idx + N_cs_bins] - # print(f"measurements b = {b}") - A, T_inv = calculate_cs_A(data, mcdc) x = calculate_cs_sparse_solution(data, mcdc, A, b) - np.save("sparse_solution.npy", x) - # print(f"sparse solution shape = {x.shape}") - # print(x) - recon = T_inv @ x - # print(f"recon.shape = {recon.shape}") - # print(f"recon = {recon}") - recon_reshaped = recon.reshape(Ny, Nx) - plt.imshow(recon_reshaped) - plt.title("Reconstruction") - plt.colorbar() - plt.show() - - return recon - # reconstruction - - # # Find the sparse solution, and then find the reconstruction - # sparse_solution[res] = finding_sparse_solution(A[res], fluxes[res].size, b, bpdn_lambda) - # reconstruction[res] = np.reshape(un_matrix[res] @ sparse_solution[res], fluxes[res].shape) - # rescaled_recons[res] = downsample_to_resolution(reconstruction[res], input_flux.shape) - - # if return_centers: - # return reconstruction, input_flux, rescaled_recons, bin_centers[0] - # else: - # return reconstruction, input_flux, rescaled_recons + tally["filter"]["cs_reconstruction"] = recon_reshaped # ============================================================================= @@ -486,42 +451,25 @@ def dd_mesh_bounds(idx): def generate_cs_centers(mcdc, N_dim=3, seed=123456789): - # N_cs_bins = int(mcdc["cs_tallies"]["filter"]["N_cs_bins"]) - # x_lims = ( - # mcdc["cs_tallies"]["filter"]["x"][0][-1], - # mcdc["cs_tallies"]["filter"]["x"][0][0], - # ) - # y_lims = ( - # mcdc["cs_tallies"]["filter"]["y"][0][-1], - # mcdc["cs_tallies"]["filter"]["y"][0][0], - # ) - - # # Generate Halton sequence according to the seed - # halton_seq = Halton(d=N_dim, seed=seed) - # points = halton_seq.random(n=N_cs_bins) - - # # Extract x and y coordinates as tuples separately, scaled to the problem dimensions - # x_coords = tuple(points[:, 0] * (x_lims[1] - x_lims[0]) + x_lims[0]) - # y_coords = tuple(points[:, 1] * (y_lims[1] - y_lims[0]) + y_lims[0]) - - # Generate the centers of the cells - x_centers = np.linspace(0.05, 3.95, 40) - y_centers = np.linspace(0.05, 3.95, 40) - - # Create the meshgrid for all cell centers - X, Y = np.meshgrid(x_centers, y_centers) - - # Flatten the arrays to get the list of coordinates - x_coords = X.flatten() - y_coords = Y.flatten() + N_cs_bins = int(mcdc["cs_tallies"]["filter"]["N_cs_bins"]) + x_lims = ( + mcdc["cs_tallies"]["filter"]["x"][0][-1], + mcdc["cs_tallies"]["filter"]["x"][0][0], + ) + y_lims = ( + mcdc["cs_tallies"]["filter"]["y"][0][-1], + mcdc["cs_tallies"]["filter"]["y"][0][0], + ) - x_coords_list = x_coords.tolist() - y_coords_list = y_coords.tolist() + # Generate Halton sequence according to the seed + halton_seq = Halton(d=N_dim, seed=seed) + points = halton_seq.random(n=N_cs_bins) - x_coords_list.append(2.0) - y_coords_list.append(2.0) + # Extract x and y coordinates as tuples separately, scaled to the problem dimensions + x_coords = tuple(points[:, 0] * (x_lims[1] - x_lims[0]) + x_lims[0]) + y_coords = tuple(points[:, 1] * (y_lims[1] - y_lims[0]) + y_lims[0]) - return (x_coords_list, y_coords_list) + return (x_coords, y_coords) def prepare(): @@ -1948,7 +1896,14 @@ def generate_hdf5(data, mcdc): group_name = "tallies/cs_tally_%i/%s/" % (ID, score_name) center_points = tally["filter"]["cs_centers"] - f.create_dataset(group_name + "center_points", data=center_points) + S = tally["filter"]["cs_S"] + reconstruction = tally["filter"]["cs_reconstruction"] + + f.create_dataset( + "tallies/cs_tally_%i/center_points" % (ID), data=center_points + ) + f.create_dataset("tallies/cs_tally_%i/S" % (ID), data=S) + f.create_dataset(group_name + "reconstruction", data=reconstruction) mean = score_tally_bin[TALLY_SUM] sdev = score_tally_bin[TALLY_SUM_SQ] diff --git a/mcdc/tally.py b/mcdc/tally.py index cd61a77d..e1ff98e2 100644 --- a/mcdc/tally.py +++ b/mcdc/tally.py @@ -233,14 +233,9 @@ def cs_tally( # Set bin properties, convert bin size to problem units card.N_cs_bins = N_cs_bins - print(f"tally.py, {card.cs_bin_size[0]}") - print(type(card.cs_bin_size), card.cs_bin_size.shape) card.cs_bin_size[0] = cs_bin_size[0] / (len(x) - 1) * (x[-1] - x[0]) card.cs_bin_size[1] = cs_bin_size[1] / (len(y) - 1) * (y[-1] - y[0]) - print(f"tally.py, {card.cs_bin_size[0]}") - print(type(card.cs_bin_size), card.cs_bin_size.shape) - # Set other filters card.t = t card.mu = mu diff --git a/mcdc/type_.py b/mcdc/type_.py index af421d3d..be513907 100644 --- a/mcdc/type_.py +++ b/mcdc/type_.py @@ -954,6 +954,8 @@ def make_type_cs_tally(input_deck): N_cs_centers, ), ), + ("cs_S", float64, (N_cs_centers, (Nmax_x - 1) * (Nmax_y - 1))), + ("cs_reconstruction", float64, ((Nmax_x - 1), (Nmax_y - 1))), ("x", float64, (Nmax_x,)), ("y", float64, (Nmax_y,)), ("z", float64, (Nmax_z,)), From 819f31bb723674989eb26ee8eb2d1057285bcb04 Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Thu, 19 Dec 2024 11:08:04 -0700 Subject: [PATCH 5/9] removing unnecessary imports --- .../fixed_source/sphere_in_cube/process.py | 9 +++-- mcdc/kernel.py | 2 - mcdc/main.py | 37 +------------------ 3 files changed, 7 insertions(+), 41 deletions(-) diff --git a/examples/fixed_source/sphere_in_cube/process.py b/examples/fixed_source/sphere_in_cube/process.py index d7896a54..c77451d0 100644 --- a/examples/fixed_source/sphere_in_cube/process.py +++ b/examples/fixed_source/sphere_in_cube/process.py @@ -19,10 +19,11 @@ cs_results = f["tallies"]["cs_tally_0"]["fission"]["mean"][:] - # mesh_results = f["tallies"]["mesh_tally_0"]["fission"]["mean"][:] - # plt.imshow(mesh_results) - # plt.title("mesh results") - # plt.show() + mesh_results = f["tallies"]["mesh_tally_0"]["fission"]["mean"][:] + plt.imshow(mesh_results) + plt.title("mesh results") + plt.colorbar() + plt.show() Nx = 40 Ny = 40 diff --git a/mcdc/kernel.py b/mcdc/kernel.py index 83530bf6..c93c9310 100644 --- a/mcdc/kernel.py +++ b/mcdc/kernel.py @@ -32,8 +32,6 @@ def round(float_val): # return np.uint64(int_val).view(np.float64) -from shapely.geometry import LineString, box - # ============================================================================= # Domain Decomposition # ============================================================================= diff --git a/mcdc/main.py b/mcdc/main.py index bdc5a274..42204839 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -3,17 +3,10 @@ import mcdc.config as config import matplotlib.pyplot as plt import numba as nb -from scipy.stats.qmc import Halton -import cvxpy as cp - -import matplotlib.pyplot as plt from matplotlib import colors as mpl_colors -from matplotlib.patches import Rectangle -from shapely.geometry import Polygon, box import scipy.fft as spfft - -import numba as nb - +from scipy.stats.qmc import Halton +import cvxpy as cp from mcdc.card import UniverseCard from mcdc.print_ import ( @@ -111,32 +104,6 @@ def run(): closeout(mcdc) -def calculate_cs_overlap(corners, grid): - quadrilateral = Polygon(corners) - - # Get the dimensions of the grid - grid_height, grid_width = grid.shape - - # Create an array to hold the overlap values - overlap = np.zeros_like(grid, dtype=float) - - # Loop over each grid cell - for i in range(grid_height): - for j in range(grid_width): - # Define the current grid cell as a shapely box - cell = box(j - 0.5, i - 0.5, j + 0.5, i + 0.5) - - # Calculate the intersection area between the cell and the quadrilateral - intersection = cell.intersection(quadrilateral).area - - # Normalize by the cell area (which is 1 in this case) - overlap[i, j] = intersection - - overlap_1d = overlap.flatten() - - return overlap_1d - - def calculate_cs_A(data, mcdc): x_grid = mcdc["mesh_tallies"]["filter"]["x"][0] y_grid = mcdc["mesh_tallies"]["filter"]["y"][0] From 56781cb2d9dbd5b043a0b71c161f5f7b2e136447 Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Fri, 20 Dec 2024 11:33:51 -0700 Subject: [PATCH 6/9] fixed bug with sizing of last bin --- examples/fixed_source/kobayashi3-TD/input.py | 4 ++-- mcdc/main.py | 8 +++++++- mcdc/type_.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/fixed_source/kobayashi3-TD/input.py b/examples/fixed_source/kobayashi3-TD/input.py index 116f4312..98bef5e1 100644 --- a/examples/fixed_source/kobayashi3-TD/input.py +++ b/examples/fixed_source/kobayashi3-TD/input.py @@ -71,7 +71,7 @@ mcdc.tally.cs_tally( N_cs_bins=[150], - cs_bin_size=[8], + cs_bin_size=[8.0, 8.0], x=np.linspace(0.0, 60.0, 31), y=np.linspace(0.0, 100.0, 51), scores=["flux"], @@ -79,7 +79,7 @@ # Setting -mcdc.setting(N_particle=1e5) +mcdc.setting(N_particle=1e2) # Run mcdc.run() diff --git a/mcdc/main.py b/mcdc/main.py index 42204839..3b6eee67 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -122,13 +122,16 @@ def calculate_cs_A(data, mcdc): # Calculate the overlap grid for each bin, and flatten into a row of S for ibin in range(N_cs_bins): if ibin == N_cs_bins - 1: - cs_bin_size = np.array([Nx, Ny]) + cs_bin_size = np.array([x_grid[-1] + x_grid[0], y_grid[-1] + y_grid[0]]) bin_x_min = x_centers[ibin] - cs_bin_size[0] / 2 bin_x_max = x_centers[ibin] + cs_bin_size[0] / 2 bin_y_min = y_centers[ibin] - cs_bin_size[1] / 2 bin_y_max = y_centers[ibin] + cs_bin_size[1] / 2 + print(f"center = {x_centers[ibin], y_centers[ibin]}") + print(f"size = {cs_bin_size}") + overlap = np.zeros((len(y_grid) - 1, len(x_grid) - 1)) for i in range(len(y_grid) - 1): @@ -155,6 +158,9 @@ def calculate_cs_A(data, mcdc): overlap[i, j] = (overlap_x * overlap_y) / cell_area S[ibin] = overlap.flatten() + + # for i in range(len(S[-1])): + # print(S[-1][i]) S = np.array(S) mcdc["cs_tallies"]["filter"]["cs_S"] = S diff --git a/mcdc/type_.py b/mcdc/type_.py index be513907..cc81f4ee 100644 --- a/mcdc/type_.py +++ b/mcdc/type_.py @@ -955,7 +955,7 @@ def make_type_cs_tally(input_deck): ), ), ("cs_S", float64, (N_cs_centers, (Nmax_x - 1) * (Nmax_y - 1))), - ("cs_reconstruction", float64, ((Nmax_x - 1), (Nmax_y - 1))), + ("cs_reconstruction", float64, ((Nmax_y - 1), (Nmax_x - 1))), ("x", float64, (Nmax_x,)), ("y", float64, (Nmax_y,)), ("z", float64, (Nmax_z,)), From d337a0d8de1cee2d009e6a88f91bd20a756c4cb6 Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Sat, 21 Dec 2024 06:29:30 +0700 Subject: [PATCH 7/9] add cvxpy to Python dependencies --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 85c16f5f..5afecf3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ dependencies = [ "black", "sympy", "pre-commit", + "cvxpy" ] [project.optional-dependencies] docs = ["sphinx==7.2.6", "furo", "sphinx_toolbox"] From 267a2e98723bef5de2c977782511db2e5eb31016 Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Fri, 27 Dec 2024 13:25:07 -0700 Subject: [PATCH 8/9] fixed cs numba issue, stopped dynamically changing cs_bin_size --- examples/fixed_source/cooper_combo/input.py | 2 +- .../fixed_source/kobayashi3-TD/process.py | 21 +-- mcdc/kernel.py | 168 +++++++++++------- mcdc/main.py | 7 +- 4 files changed, 110 insertions(+), 88 deletions(-) diff --git a/examples/fixed_source/cooper_combo/input.py b/examples/fixed_source/cooper_combo/input.py index 8daf6352..c84c4f4e 100644 --- a/examples/fixed_source/cooper_combo/input.py +++ b/examples/fixed_source/cooper_combo/input.py @@ -61,7 +61,7 @@ ) # Setting -mcdc.setting(N_particle=1e5) +mcdc.setting(N_particle=1e2) mcdc.implicit_capture() # Run diff --git a/examples/fixed_source/kobayashi3-TD/process.py b/examples/fixed_source/kobayashi3-TD/process.py index 6e37fc1c..211b2d89 100644 --- a/examples/fixed_source/kobayashi3-TD/process.py +++ b/examples/fixed_source/kobayashi3-TD/process.py @@ -11,6 +11,10 @@ # Results with h5py.File("output.h5", "r") as f: + cs_recon = f["tallies/cs_tally_0/flux/reconstruction"][:] + plt.imshow(cs_recon) + plt.show() + tallies = f["tallies/mesh_tally_0"] flux = tallies["flux"] grid = tallies["grid"] @@ -30,20 +34,3 @@ print( f'cell {i+1} mean = {flux_score["mean"][()]}, sdev = {flux_score["sdev"][()]}' ) - -fig, ax = plt.subplots() -cax = ax.pcolormesh(X, Y, phi[0], vmin=phi[0].min(), vmax=phi[0].max()) -text = ax.text(0.02, 1.02, "", transform=ax.transAxes) -ax.set_aspect("equal", "box") -ax.set_xlabel("$y$ [cm]") -ax.set_ylabel("$x$ [cm]") - - -def animate(i): - cax.set_array(phi[i]) - cax.set_clim(phi[i].min(), phi[i].max()) - text.set_text(r"$t \in [%.1f,%.1f]$ s" % (t[i], t[i + 1])) - - -anim = animation.FuncAnimation(fig, animate, interval=10, frames=len(t) - 1) -plt.show() diff --git a/mcdc/kernel.py b/mcdc/kernel.py index c93c9310..f564ecb8 100644 --- a/mcdc/kernel.py +++ b/mcdc/kernel.py @@ -2044,18 +2044,22 @@ def score_cs_tally(P_arr, distance, tally, data, mcdc): # Check each coarse bin for j in range(N_cs_bins): - center = (cs_centers[0][j], cs_centers[1][j]) + center = np.array([cs_centers[0][j], cs_centers[1][j]]) + start = np.array([x, y]) + end = np.array([x_final, y_final]) + + distance_inside = calculate_distance_in_coarse_bin( + start, end, distance, center, cs_bin_size + ) # Last bin covers the whole problem if j == N_cs_bins - 1: - cs_bin_size = np.array([INF, INF]) + cs_bin_size_full_problem = np.array([INF, INF], dtype=np.float64) + distance_inside = calculate_distance_in_coarse_bin( + start, end, distance, center, cs_bin_size_full_problem + ) - distance_in_bin = np.minimum( - distance, - calculate_distance_in_coarse_bin( - P_arr, distance, center, cs_bin_size, mcdc - ), - ) + distance_in_bin = np.minimum(distance, distance_inside) # this line is good # Calculate flux and other scores flux = distance_in_bin * P["w"] @@ -2080,69 +2084,105 @@ def score_cs_tally(P_arr, distance, tally, data, mcdc): # tally_bin[TALLY_SCORE, bin_idx + j * tally["N_score"] + i] += score -@njit -def calculate_distance_in_coarse_bin(P_arr, distance, center, cs_bin_size, mcdc): - P = P_arr[0] +# @njit +# def cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max): +# # Uses Liang-Barsky alog +# t0, t1 = 0.0, 1.0 + +# dx = end[0] - start[0] +# dy = end[1] - start[1] + +# def clip(p, q): +# nonlocal t0, t1 +# if p < 0: +# t = q / p +# if t > t1: +# return False +# if t > t0: +# t0 = t +# elif p > 0: +# t = q / p +# if t < t0: +# return False +# if t < t1: +# t1 = t +# elif q < 0: +# return False +# return True + +# if clip(-dx, start[0] - x_min): +# if clip(dx, x_max - start[0]): +# if clip(-dy, start[1] - y_min): +# if clip(dy, y_max - start[1]): +# if t1 < 1: +# end = start + t1 * np.array([dx, dy]) +# if t0 > 0: +# start = start + t0 * np.array([dx, dy]) +# return np.linalg.norm(end - start) +# return 0.0 + + +@njit(debug=True) +def cs_clip(p, q, t0, t1): + if p < 0: + t = q / p + if t > t1: + return False, t0, t1 + if t > t0: + t0 = t + elif p > 0: + t = q / p + if t < t0: + return False, t0, t1 + if t < t1: + t1 = t + elif q < 0: + return False, t0, t1 + return True, t0, t1 + + +@njit(debug=True) +def cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max): + # Uses Liang-Barsky algorithm for finding tracklength in box + t0, t1 = 0.0, 1.0 + dx = end[0] - start[0] + dy = end[1] - start[1] + + # Perform clipping for each boundary + result, t0, t1 = cs_clip(-dx, start[0] - x_min, t0, t1) + if not result: + return 0.0 + result, t0, t1 = cs_clip(dx, x_max - start[0], t0, t1) + if not result: + return 0.0 + result, t0, t1 = cs_clip(-dy, start[1] - y_min, t0, t1) + if not result: + return 0.0 + result, t0, t1 = cs_clip(dy, y_max - start[1], t0, t1) + if not result: + return 0.0 - # Particle 4D direction - ux = P["ux"] - uy = P["uy"] - uz = P["uz"] + # Update start and end points based on clipping results + if t1 < 1: + end = start + t1 * np.array([dx, dy]) + if t0 > 0: + start = start + t0 * np.array([dx, dy]) - # Particle initial and final coordinate - x = P["x"] - y = P["y"] - z = P["z"] - t = P["t"] - x_final = x + ux * distance - y_final = y + uy * distance - z_final = z + uz * distance + return np.linalg.norm(end - start) - start = np.array([x, y]) - end = np.array([x_final, y_final]) +@njit +def calculate_distance_in_coarse_bin(start, end, distance, center, cs_bin_size): # Edges of the coarse bin - x_min, x_max = center[0] - cs_bin_size[0] / 2, center[0] + cs_bin_size[0] / 2 - y_min, y_max = center[1] - cs_bin_size[1] / 2, center[1] + cs_bin_size[1] / 2 - - def clip_segment_to_box(start, end, x_min, x_max, y_min, y_max): - t0, t1 = 0.0, 1.0 - - dx = end[0] - start[0] - dy = end[1] - start[1] - - def clip(p, q): - nonlocal t0, t1 - if p < 0: - t = q / p - if t > t1: - return False - if t > t0: - t0 = t - elif p > 0: - t = q / p - if t < t0: - return False - if t < t1: - t1 = t - elif q < 0: - return False - return True - - if clip(-dx, start[0] - x_min): - if clip(dx, x_max - start[0]): - if clip(-dy, start[1] - y_min): - if clip(dy, y_max - start[1]): - if t1 < 1: - end = start + t1 * np.array([dx, dy]) - if t0 > 0: - start = start + t0 * np.array([dx, dy]) - return np.linalg.norm(end - start) - return 0.0 + x_min = center[0] - cs_bin_size[0] / 2 + x_max = center[0] + cs_bin_size[0] / 2 + y_min = center[1] - cs_bin_size[1] / 2 + y_max = center[1] + cs_bin_size[1] / 2 - distance_inside = clip_segment_to_box(start, end, x_min, x_max, y_min, y_max) + # distance_inside = cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max) + distance_inside = 0.1234 - return distance_inside + return np.float64(distance_inside) @njit diff --git a/mcdc/main.py b/mcdc/main.py index 3b6eee67..f2778de3 100644 --- a/mcdc/main.py +++ b/mcdc/main.py @@ -122,6 +122,7 @@ def calculate_cs_A(data, mcdc): # Calculate the overlap grid for each bin, and flatten into a row of S for ibin in range(N_cs_bins): if ibin == N_cs_bins - 1: + # could just change to -INF, INF cs_bin_size = np.array([x_grid[-1] + x_grid[0], y_grid[-1] + y_grid[0]]) bin_x_min = x_centers[ibin] - cs_bin_size[0] / 2 @@ -129,9 +130,6 @@ def calculate_cs_A(data, mcdc): bin_y_min = y_centers[ibin] - cs_bin_size[1] / 2 bin_y_max = y_centers[ibin] + cs_bin_size[1] / 2 - print(f"center = {x_centers[ibin], y_centers[ibin]}") - print(f"size = {cs_bin_size}") - overlap = np.zeros((len(y_grid) - 1, len(x_grid) - 1)) for i in range(len(y_grid) - 1): @@ -158,9 +156,6 @@ def calculate_cs_A(data, mcdc): overlap[i, j] = (overlap_x * overlap_y) / cell_area S[ibin] = overlap.flatten() - - # for i in range(len(S[-1])): - # print(S[-1][i]) S = np.array(S) mcdc["cs_tallies"]["filter"]["cs_S"] = S From d84cecaab5454b1bd4ba77786a7831b378359e3e Mon Sep 17 00:00:00 2001 From: Ethan Lame Date: Fri, 27 Dec 2024 13:35:04 -0700 Subject: [PATCH 9/9] comment cleanup --- mcdc/kernel.py | 52 ++++++-------------------------------------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/mcdc/kernel.py b/mcdc/kernel.py index f564ecb8..7d9b5ff9 100644 --- a/mcdc/kernel.py +++ b/mcdc/kernel.py @@ -2081,48 +2081,9 @@ def score_cs_tally(P_arr, distance, tally, data, mcdc): (TALLY_SCORE, bin_idx + j * tally["N_score"] + i), round(score), ) - # tally_bin[TALLY_SCORE, bin_idx + j * tally["N_score"] + i] += score - - -# @njit -# def cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max): -# # Uses Liang-Barsky alog -# t0, t1 = 0.0, 1.0 - -# dx = end[0] - start[0] -# dy = end[1] - start[1] - -# def clip(p, q): -# nonlocal t0, t1 -# if p < 0: -# t = q / p -# if t > t1: -# return False -# if t > t0: -# t0 = t -# elif p > 0: -# t = q / p -# if t < t0: -# return False -# if t < t1: -# t1 = t -# elif q < 0: -# return False -# return True - -# if clip(-dx, start[0] - x_min): -# if clip(dx, x_max - start[0]): -# if clip(-dy, start[1] - y_min): -# if clip(dy, y_max - start[1]): -# if t1 < 1: -# end = start + t1 * np.array([dx, dy]) -# if t0 > 0: -# start = start + t0 * np.array([dx, dy]) -# return np.linalg.norm(end - start) -# return 0.0 - - -@njit(debug=True) + + +@njit def cs_clip(p, q, t0, t1): if p < 0: t = q / p @@ -2141,7 +2102,7 @@ def cs_clip(p, q, t0, t1): return True, t0, t1 -@njit(debug=True) +@njit def cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max): # Uses Liang-Barsky algorithm for finding tracklength in box t0, t1 = 0.0, 1.0 @@ -2179,10 +2140,9 @@ def calculate_distance_in_coarse_bin(start, end, distance, center, cs_bin_size): y_min = center[1] - cs_bin_size[1] / 2 y_max = center[1] + cs_bin_size[1] / 2 - # distance_inside = cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max) - distance_inside = 0.1234 + distance_inside = cs_tracklength_in_box(start, end, x_min, x_max, y_min, y_max) - return np.float64(distance_inside) + return distance_inside @njit