To solve John's problem, we first need to define the variables and constraints of the linear programming model. Let's denote:

- \(x\) as the number of SD pills John should buy.
- \(y\) as the number of LD pills John should buy.

The objective is to minimize the total cost, which can be represented as \(1x + 1.5y\), since each SD pill costs $1 and each LD pill costs $1.50.

There are two main constraints based on John's nutritional needs:
1. Calcium intake: \(1x + 2y \geq 15\) (since each SD pill contains 1 unit of calcium and each LD pill contains 2 units of calcium, and he needs at least 15 units).
2. Iron intake: \(4x + 1y \geq 20\) (since each SD pill contains 4 units of iron and each LD pill contains 1 unit of iron, and he needs at least 20 units).

Additionally, we have non-negativity constraints:
- \(x \geq 0\)
- \(y \geq 0\)

Because John cannot buy a negative number of pills.

Now, let's translate this problem into Gurobi code in Python:

```python
from gurobipy import *

# Create a new model
m = Model("John_Supplementation")

# Define variables
x = m.addVar(name="SD_pills", vtype=GRB.CONTINUOUS, lb=0)
y = m.addVar(name="LD_pills", vtype=GRB.CONTINUOUS, lb=0)

# Set the objective function
m.setObjective(1*x + 1.5*y, GRB.MINIMIZE)

# Add constraints
m.addConstr(1*x + 2*y >= 15, name="Calcium_Constraint")
m.addConstr(4*x + 1*y >= 20, name="Iron_Constraint")

# Optimize model
m.optimize()

# Print solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Buy {x.x} SD pills")
    print(f"Buy {y.x} LD pills")
    print(f"Total cost: ${1*x.x + 1.5*y.x}")
else:
    print("No optimal solution found")

```