content: {-# OPTIONS_GHC -Wall #-}
  {-# LANGUAGE Safe #-}
  
  {- | 
  Module      :  Physics.Learn.Charge
  Copyright   :  (c) Scott N. Walck 2011-2019
  License     :  BSD3 (see LICENSE)
  Maintainer  :  Scott N. Walck <walck@lvc.edu>
  Stability   :  experimental
  
  This module contains functions for working with charge, electric field,
  electric flux, and electric potential.
  -}
  
  module Physics.Learn.Charge
      (
      -- * Charge
        Charge
      , ChargeDistribution(..)
      , totalCharge
      -- * Electric Field
      , eField
      , eFieldFromPointCharge
      , eFieldFromLineCharge
      , eFieldFromSurfaceCharge
      , eFieldFromVolumeCharge
      -- * Electric Flux
      , electricFlux
      -- * Electric Potential
      , electricPotentialFromField
      , electricPotentialFromCharge
      )
      where
  
  import Physics.Learn.CarrotVec
      ( magnitude
      , (*^)
      , (^/)
      )
  import Physics.Learn.Position
      ( Position
      , ScalarField
      , VectorField
      , displacement
      , addFields
      )
  import Physics.Learn.Curve
      ( Curve(..)
      , straightLine
      , simpleLineIntegral
      , dottedLineIntegral
      )
  import Physics.Learn.Surface
      ( Surface(..)
      , surfaceIntegral
      , dottedSurfaceIntegral
      )
  import Physics.Learn.Volume
      ( Volume(..)
      , volumeIntegral
      )
  
  -- | Electric charge, in units of Coulombs (C)
  type Charge = Double
  
  -- | A charge distribution is a point charge, a line charge, a surface charge,
  --   a volume charge, or a combination of these.
  --   The 'ScalarField' describes a linear charge density, a surface charge density,
  --   or a volume charge density.
  data ChargeDistribution = PointCharge Charge Position        -- ^ point charge
                          | LineCharge ScalarField Curve       -- ^ 'ScalarField' is linear charge density (C/m)
                          | SurfaceCharge ScalarField Surface  -- ^ 'ScalarField' is surface charge density (C/m^2)
                          | VolumeCharge ScalarField Volume    -- ^ 'ScalarField' is volume charge density (C/m^3)
                          | MultipleCharges [ChargeDistribution]  -- ^ combination of charge distributions
  
  -- | Total charge (in C) of a charge distribution.
  totalCharge :: ChargeDistribution -> Charge
  totalCharge (PointCharge q _)       = q
  totalCharge (LineCharge lambda c)   = simpleLineIntegral 1000 lambda c
  totalCharge (SurfaceCharge sigma s) = surfaceIntegral 200 200 sigma s
  totalCharge (VolumeCharge rho v)    = volumeIntegral 50 50 50 rho v
  totalCharge (MultipleCharges ds)           = sum [totalCharge d | d <- ds]
  
  {-
  shiftChargeDistribution :: Displacement -> ChargeDistribution -> ChargeDistribution
  shiftChargeDistribution d (Point
  -}
  
  -- | Electric field produced by a point charge.
  --   The function 'eField' calls this function
  --   to evaluate the electric field produced by a point charge.
  eFieldFromPointCharge
      :: Charge          -- ^ charge (in Coulombs)
      -> Position        -- ^ of point charge
      -> VectorField     -- ^ electric field (in V/m)
  eFieldFromPointCharge q r' r
      = (k * q) *^ d ^/ magnitude d ** 3
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          d = displacement r' r
  
  -- | Electric field produced by a line charge.
  --   The function 'eField' calls this function
  --   to evaluate the electric field produced by a line charge.
  eFieldFromLineCharge
      :: ScalarField     -- ^ linear charge density lambda
      -> Curve           -- ^ geometry of the line charge
      -> VectorField     -- ^ electric field (in V/m)
  eFieldFromLineCharge lambda c r
      = k *^ simpleLineIntegral 1000 integrand c
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = lambda r' *^ d ^/ magnitude d ** 3
              where
                d = displacement r' r
  
  -- | Electric field produced by a surface charge.
  --   The function 'eField' calls this function
  --   to evaluate the electric field produced by a surface charge.
  eFieldFromSurfaceCharge
      :: ScalarField     -- ^ surface charge density sigma
      -> Surface         -- ^ geometry of the surface charge
      -> VectorField     -- ^ electric field (in V/m)
  eFieldFromSurfaceCharge sigma s r
      = k *^ surfaceIntegral 200 200 integrand s
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = sigma r' *^ d ^/ magnitude d ** 3
              where
                d = displacement r' r
  
  -- | Electric field produced by a volume charge.
  --   The function 'eField' calls this function
  --   to evaluate the electric field produced by a volume charge.
  eFieldFromVolumeCharge
      :: ScalarField     -- ^ volume charge density rho
      -> Volume          -- ^ geometry of the volume charge
      -> VectorField     -- ^ electric field (in V/m)
  eFieldFromVolumeCharge rho v r
      = k *^ volumeIntegral 50 50 50 integrand v
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = rho r' *^ d ^/ magnitude d ** 3
              where
                d = displacement r' r
  
  -- | The electric field produced by a charge distribution.
  --   This is the simplest way to find the electric field, because it
  --   works for any charge distribution (point, line, surface, volume, or combination).
  eField :: ChargeDistribution -> VectorField
  eField (PointCharge q r') = eFieldFromPointCharge q r'
  eField (LineCharge lam c) = eFieldFromLineCharge lam c
  eField (SurfaceCharge sig s) = eFieldFromSurfaceCharge sig s
  eField (VolumeCharge rho v) = eFieldFromVolumeCharge rho v
  eField (MultipleCharges cds) = addFields $ map eField cds
  
  -------------------
  -- Electric Flux --
  -------------------
  
  -- | The electric flux through a surface produced by a charge distribution.
  electricFlux :: Surface -> ChargeDistribution -> Double
  electricFlux surf dist = dottedSurfaceIntegral 200 200 (eField dist) surf
  
  ------------------------
  -- Electric Potential --
  ------------------------
  
  -- | Electric potential from electric field, given a position to be the zero
  --   of electric potential.
  electricPotentialFromField :: Position     -- ^ position where electric potential is zero
                             -> VectorField  -- ^ electric field
                             -> ScalarField  -- ^ electric potential
  electricPotentialFromField base ef r = -dottedLineIntegral 1000 ef (straightLine base r)
  
  -- | Electric potential produced by a charge distribution.
  --   The position where the electric potential is zero is taken to be infinity.
  electricPotentialFromCharge :: ChargeDistribution -> ScalarField
  electricPotentialFromCharge (PointCharge q r') = ePotFromPointCharge q r'
  electricPotentialFromCharge (LineCharge lam c) = ePotFromLineCharge lam c
  electricPotentialFromCharge (SurfaceCharge sig s) = ePotFromSurfaceCharge sig s
  electricPotentialFromCharge (VolumeCharge rho v) = ePotFromVolumeCharge rho v
  electricPotentialFromCharge (MultipleCharges cds) = addFields $ map electricPotentialFromCharge cds
  
  ePotFromPointCharge
      :: Charge          -- ^ charge (in Coulombs)
      -> Position        -- ^ of point charge
      -> ScalarField     -- ^ electric potential
  ePotFromPointCharge q r' r
      = (k * q) / magnitude d
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          d = displacement r' r
  
  ePotFromLineCharge
      :: ScalarField     -- ^ linear charge density lambda
      -> Curve           -- ^ geometry of the line charge
      -> ScalarField     -- ^ electric potential
  ePotFromLineCharge lambda c r
      = k *^ simpleLineIntegral 1000 integrand c
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = lambda r' / magnitude d
              where
                d = displacement r' r
  
  ePotFromSurfaceCharge
      :: ScalarField     -- ^ surface charge density sigma
      -> Surface         -- ^ geometry of the surface charge
      -> ScalarField     -- ^ electric potential
  ePotFromSurfaceCharge sigma s r
      = k *^ surfaceIntegral 200 200 integrand s
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = sigma r' / magnitude d
              where
                d = displacement r' r
  
  ePotFromVolumeCharge
      :: ScalarField     -- ^ volume charge density rho
      -> Volume          -- ^ geometry of the volume charge
      -> ScalarField     -- ^ electric potential
  ePotFromVolumeCharge rho v r
      = k *^ volumeIntegral 50 50 50 integrand v
        where
          k = 9e9  -- 1 / (4 * pi * epsilon0)
          integrand r' = rho r' / magnitude d
              where
                d = displacement r' r
  
  {-
  Student Exercise:  Write a function for electric potential difference.
  
  -- | The electric potential difference V(end) - V(beginning) between the endpoints
  --   of a curve.
  electricPotentialDifference :: Curve -> ChargeDistribution -> Double
  electricPotentialDifference c dist = -dottedLineIntegral 1000 (eField dist) c
  -}
  
  ---------------------------------
  -- Common Charge Distributions --
  ---------------------------------
  
  