一维杆移动热源热扩散模拟中不同维度数组插值问题及TypeError报错排查
Let's work through your problem step by step—there are a few key issues in your code causing the mismatches, TypeError, and incorrect heat source application. Here's how to fix everything and create a flexible solution that works for any time-position function:
1. Fix the Heat Source Position Function (wf_pos)
Your original wf_pos has a critical logic error: you're trying to create an interp1d object using a scalar t and scalar position, which doesn't make sense. For your square-root position function (an analytical formula), you don't even need interpolation—just compute the position directly. For non-analytical functions, precompute positions over your time grid first, then create an interpolation function.
Option A: Analytical Position Function (your case)
def wf_pos(t): """Calculate heat source position (meters) for scalar or array input t""" return np.sqrt(t * dt)
Option B: Generic Non-Analytical Position Function
If you later switch to a position function that can't be computed directly, precompute positions for all your evaluation times first:
# Precompute positions for all time points in your evaluation grid t_all = t_eval # Use your existing time evaluation array pos_all = your_custom_position_function(t_all) # Replace with your function wf_pos_interp = interp1d(t_all, pos_all, kind='linear', fill_value="extrapolate") # Now call wf_pos_interp(t) to get the position at any time t
2. Fix the Floating-Point Mismatch Between Source Position and Grid
Using np.where(x_points == wf_start) will almost never work due to floating-point precision errors. Instead, find the nearest grid index to your target position:
def get_nearest_grid_index(x_grid, target_pos): """Find the index of the grid point closest to target_pos""" return np.argmin(np.abs(x_grid - target_pos))
Use this function in your plotting code to get valid start/end indices:
for k in range(5): # Calculate start/end times for this 3-minute segment start_time = t[(k)*t_seg] end_time = t[(k+1)*t_seg] # Get source positions at start/end of the segment wf_start = wf_pos(start_time) # Or wf_pos_interp(start_time) for non-analytical wf_end = wf_pos(end_time) # Find nearest grid indices idx_start = get_nearest_grid_index(x_points, wf_start) idx_end = get_nearest_grid_index(x_points, wf_end) # Ensure idx_end is greater than idx_start (in case source moves backward) if idx_end < idx_start: idx_start, idx_end = idx_end, idx_start # Plot the temperature segment (average over the time segment for clarity) ax[k].plot(x_points[idx_start:idx_end], u[(k)*t_seg : (k+1)*t_seg, idx_start:idx_end].mean(axis=0), label=r'$T_{\mathrm{bed}}(x)$', color='C3', linewidth=1.5) ax[k].set_ylabel(r'$T_{\mathrm{bed}}$ (°C)') ax[k].set_xlabel(r'Position along the bed (x)') ax[k].set_title(f'Bed temperature: {k*3} to {(k+1)*3} minutes') ax[k].legend() ax[k].grid(True)
3. Fix the TypeError and Incorrect Heat Source Application in the ODE
Your TypeError: object of type 'float' has no len() comes from two issues:
- The broken
wf_posfunction returning an invalid object - Overwriting the
xparameter (your spatial grid) inside theodefunction with the source position
Plus, your original ODE applies the heat source to every grid point (Tp += Q_val)—that's wrong! You only want to add the heat to the grid point where the source is located. Here's the fixed ODE:
def ode(t, T, Nx, x_grid, dx): """Fixed ODE form of the spatially discretized PDE""" NX = len(T) Tp = np.zeros(NX) # Compute finite difference Laplacian for i in range(1, NX-1): Tp[i] = (T[i-1] - 2 * T[i] + T[i+1]) # Get current source position and corresponding grid index source_pos = wf_pos(t) # Or wf_pos_interp(t) source_idx = get_nearest_grid_index(x_grid, source_pos) # Get heat source value and apply it to the correct grid point lindex = lindex_func(source_pos) Q_val = Qi_func(lindex) Tp[source_idx] += Q_val # Apply diffusion coefficient and divide by rho*Cp coef = k / (dx**2) Tp = coef * Tp Tp /= rhoCp # Apply boundary conditions (zero gradient) Tp[0] = Tp[1] Tp[NX-1] = Tp[NX-2] return Tp
Don't forget to update your args to avoid variable name conflicts:
args = (Nx, x_points, dx) # Use x_points instead of x here
4. Generalize for Any Time-Position Function
To make this work for any future position function:
- Precompute positions for all your evaluation times (if non-analytical)
- Use
interp1dto create a smooth interpolation function - Use
get_nearest_grid_indexto map the continuous position to your discrete grid - Ensure the ODE only applies the heat source to the correct grid point
These changes will eliminate your TypeError, fix the position-grid mismatch, and make your code flexible enough to handle any heat source movement pattern.
内容的提问来源于stack exchange,提问作者user30517380

