{-# 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 :: ChargeDistribution -> Double
totalCharge (PointCharge Double
q Position
_)       = Double
q
totalCharge (LineCharge ScalarField
lambda Curve
c)   = forall v.
(InnerSpace v, Scalar v ~ Double) =>
Int -> Field v -> Curve -> v
simpleLineIntegral Int
1000 ScalarField
lambda Curve
c
totalCharge (SurfaceCharge ScalarField
sigma Surface
s) = forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Field v -> Surface -> v
surfaceIntegral Int
200 Int
200 ScalarField
sigma Surface
s
totalCharge (VolumeCharge ScalarField
rho Volume
v)    = forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Int -> Field v -> Volume -> v
volumeIntegral Int
50 Int
50 Int
50 ScalarField
rho Volume
v
totalCharge (MultipleCharges [ChargeDistribution]
ds)           = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ChargeDistribution -> Double
totalCharge ChargeDistribution
d | ChargeDistribution
d <- [ChargeDistribution]
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 :: Double -> Position -> VectorField
eFieldFromPointCharge Double
q Position
r' Position
r
    = (Double
k forall a. Num a => a -> a -> a
* Double
q) forall v. VectorSpace v => Scalar v -> v -> v
*^ Displacement
d forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d forall a. Floating a => a -> a -> a
** Double
3
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
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 :: ScalarField -> Curve -> VectorField
eFieldFromLineCharge ScalarField
lambda Curve
c Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(InnerSpace v, Scalar v ~ Double) =>
Int -> Field v -> Curve -> v
simpleLineIntegral Int
1000 VectorField
integrand Curve
c
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: VectorField
integrand Position
r' = ScalarField
lambda Position
r' forall v. VectorSpace v => Scalar v -> v -> v
*^ Displacement
d forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d forall a. Floating a => a -> a -> a
** Double
3
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
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 :: ScalarField -> Surface -> VectorField
eFieldFromSurfaceCharge ScalarField
sigma Surface
s Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Field v -> Surface -> v
surfaceIntegral Int
200 Int
200 VectorField
integrand Surface
s
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: VectorField
integrand Position
r' = ScalarField
sigma Position
r' forall v. VectorSpace v => Scalar v -> v -> v
*^ Displacement
d forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d forall a. Floating a => a -> a -> a
** Double
3
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
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 :: ScalarField -> Volume -> VectorField
eFieldFromVolumeCharge ScalarField
rho Volume
v Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Int -> Field v -> Volume -> v
volumeIntegral Int
50 Int
50 Int
50 VectorField
integrand Volume
v
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: VectorField
integrand Position
r' = ScalarField
rho Position
r' forall v. VectorSpace v => Scalar v -> v -> v
*^ Displacement
d forall v s.
(VectorSpace v, s ~ Scalar v, Fractional s) =>
v -> s -> v
^/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d forall a. Floating a => a -> a -> a
** Double
3
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
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 :: ChargeDistribution -> VectorField
eField (PointCharge Double
q Position
r') = Double -> Position -> VectorField
eFieldFromPointCharge Double
q Position
r'
eField (LineCharge ScalarField
lam Curve
c) = ScalarField -> Curve -> VectorField
eFieldFromLineCharge ScalarField
lam Curve
c
eField (SurfaceCharge ScalarField
sig Surface
s) = ScalarField -> Surface -> VectorField
eFieldFromSurfaceCharge ScalarField
sig Surface
s
eField (VolumeCharge ScalarField
rho Volume
v) = ScalarField -> Volume -> VectorField
eFieldFromVolumeCharge ScalarField
rho Volume
v
eField (MultipleCharges [ChargeDistribution]
cds) = forall v. AdditiveGroup v => [Field v] -> Field v
addFields forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ChargeDistribution -> VectorField
eField [ChargeDistribution]
cds

-------------------
-- Electric Flux --
-------------------

-- | The electric flux through a surface produced by a charge distribution.
electricFlux :: Surface -> ChargeDistribution -> Double
electricFlux :: Surface -> ChargeDistribution -> Double
electricFlux Surface
surf ChargeDistribution
dist = Int -> Int -> VectorField -> Surface -> Double
dottedSurfaceIntegral Int
200 Int
200 (ChargeDistribution -> VectorField
eField ChargeDistribution
dist) Surface
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 :: Position -> VectorField -> ScalarField
electricPotentialFromField Position
base VectorField
ef Position
r = -Int -> VectorField -> Curve -> Double
dottedLineIntegral Int
1000 VectorField
ef (Position -> Position -> Curve
straightLine Position
base Position
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 :: ChargeDistribution -> ScalarField
electricPotentialFromCharge (PointCharge Double
q Position
r') = Double -> Position -> ScalarField
ePotFromPointCharge Double
q Position
r'
electricPotentialFromCharge (LineCharge ScalarField
lam Curve
c) = ScalarField -> Curve -> ScalarField
ePotFromLineCharge ScalarField
lam Curve
c
electricPotentialFromCharge (SurfaceCharge ScalarField
sig Surface
s) = ScalarField -> Surface -> ScalarField
ePotFromSurfaceCharge ScalarField
sig Surface
s
electricPotentialFromCharge (VolumeCharge ScalarField
rho Volume
v) = ScalarField -> Volume -> ScalarField
ePotFromVolumeCharge ScalarField
rho Volume
v
electricPotentialFromCharge (MultipleCharges [ChargeDistribution]
cds) = forall v. AdditiveGroup v => [Field v] -> Field v
addFields forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ChargeDistribution -> ScalarField
electricPotentialFromCharge [ChargeDistribution]
cds

ePotFromPointCharge
    :: Charge          -- ^ charge (in Coulombs)
    -> Position        -- ^ of point charge
    -> ScalarField     -- ^ electric potential
ePotFromPointCharge :: Double -> Position -> ScalarField
ePotFromPointCharge Double
q Position
r' Position
r
    = (Double
k forall a. Num a => a -> a -> a
* Double
q) forall a. Fractional a => a -> a -> a
/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
r

ePotFromLineCharge
    :: ScalarField     -- ^ linear charge density lambda
    -> Curve           -- ^ geometry of the line charge
    -> ScalarField     -- ^ electric potential
ePotFromLineCharge :: ScalarField -> Curve -> ScalarField
ePotFromLineCharge ScalarField
lambda Curve
c Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(InnerSpace v, Scalar v ~ Double) =>
Int -> Field v -> Curve -> v
simpleLineIntegral Int
1000 ScalarField
integrand Curve
c
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: ScalarField
integrand Position
r' = ScalarField
lambda Position
r' forall a. Fractional a => a -> a -> a
/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
r

ePotFromSurfaceCharge
    :: ScalarField     -- ^ surface charge density sigma
    -> Surface         -- ^ geometry of the surface charge
    -> ScalarField     -- ^ electric potential
ePotFromSurfaceCharge :: ScalarField -> Surface -> ScalarField
ePotFromSurfaceCharge ScalarField
sigma Surface
s Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Field v -> Surface -> v
surfaceIntegral Int
200 Int
200 ScalarField
integrand Surface
s
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: ScalarField
integrand Position
r' = ScalarField
sigma Position
r' forall a. Fractional a => a -> a -> a
/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
r

ePotFromVolumeCharge
    :: ScalarField     -- ^ volume charge density rho
    -> Volume          -- ^ geometry of the volume charge
    -> ScalarField     -- ^ electric potential
ePotFromVolumeCharge :: ScalarField -> Volume -> ScalarField
ePotFromVolumeCharge ScalarField
rho Volume
v Position
r
    = Double
k forall v. VectorSpace v => Scalar v -> v -> v
*^ forall v.
(VectorSpace v, Scalar v ~ Double) =>
Int -> Int -> Int -> Field v -> Volume -> v
volumeIntegral Int
50 Int
50 Int
50 ScalarField
integrand Volume
v
      where
        k :: Double
k = Double
9e9  -- 1 / (4 * pi * epsilon0)
        integrand :: ScalarField
integrand Position
r' = ScalarField
rho Position
r' forall a. Fractional a => a -> a -> a
/ forall v s. (InnerSpace v, s ~ Scalar v, Floating s) => v -> s
magnitude Displacement
d
            where
              d :: Displacement
d = Position -> VectorField
displacement Position
r' Position
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 --
---------------------------------