diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -5,6 +5,11 @@
 ## Unreleased changes
 
 
+## Version 0.7.2.0
+
+-   `slynx`: Allow global normalization of mixture models.
+
+
 ## Version 0.7.1.0
 
 -   Be less strict with quoted identifiers/names in phylogenetic trees.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 # The ELynx Suite
 
-Version: 0.7.0.0.
+Version: 0.7.2.0.
 Reproducible evolution made easy.
 
 <p align="center"><img src="https://travis-ci.org/dschrempf/elynx.svg?branch=master"/></p>
@@ -73,13 +73,13 @@
     # OR: stack exec slynx -- --help
     # OR: slynx --help
 
-    Up to date
-    ELynx Suite version 0.7.0.0.
+    ELynx Suite version 0.7.2.0.
     Developed by Dominik Schrempf.
-    Compiled on July 10, 2022, at 08:48 am, UTC.
+    Compiled on May 3, 2023, at 13:18 pm, UTC.
     
     Usage: slynx [-v|--verbosity VALUE] [-o|--output-file-basename NAME]
                  [-f|--force] [--no-elynx-file] COMMAND
+    
       Analyze, and simulate multi sequence alignments.
     
     Available options:
diff --git a/slynx.cabal b/slynx.cabal
--- a/slynx.cabal
+++ b/slynx.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               slynx
-version:            0.7.1.0
+version:            0.7.2.0
 synopsis:           Handle molecular sequences
 description:
   Examine, modify, and simulate molecular sequences in a reproducible way. Please see the README on GitHub at <https://github.com/dschrempf/elynx>.
diff --git a/src/SLynx/Simulate/Options.hs b/src/SLynx/Simulate/Options.hs
--- a/src/SLynx/Simulate/Options.hs
+++ b/src/SLynx/Simulate/Options.hs
@@ -34,6 +34,7 @@
 --   -o,--output-file NAME    Specify output file NAME
 module SLynx.Simulate.Options
   ( GammaRateHeterogeneityParams,
+    MixtureModelGlobalNormalization (..),
     SimulateArguments (..),
     simulateArguments,
     simulateFooter,
@@ -53,11 +54,19 @@
 -- | Number of gamma rate categories and alpha parameter.
 type GammaRateHeterogeneityParams = (Int, Double)
 
+data MixtureModelGlobalNormalization = GlobalNormalization | LocalNormalization
+  deriving (Show, Read, Eq, Generic)
+
+instance FromJSON MixtureModelGlobalNormalization
+
+instance ToJSON MixtureModelGlobalNormalization
+
 -- | Arguments needed to simulate sequences.
 data SimulateArguments = SimulateArguments
   { argsTreeFile :: FilePath,
     argsSubstitutionModelString :: Maybe String,
     argsMixtureModelString :: Maybe String,
+    argsMixtureModelGlobalNormalization :: MixtureModelGlobalNormalization,
     argsEDMFile :: Maybe FilePath,
     argsSiteprofilesFiles :: Maybe [FilePath],
     argsMixtureWeights :: Maybe [Double],
@@ -90,6 +99,7 @@
     <$> treeFileOpt
     <*> phyloSubstitutionModelOpt
     <*> phyloMixtureModelOpt
+    <*> globalNormalizationFlag
     <*> maybeEDMFileOpt
     <*> maybeSiteprofilesFilesOpt
     <*> maybeMixtureWeights
@@ -126,6 +136,16 @@
           <> help
             "Set the phylogenetic mixture model; available models are shown below (mutually exclusive with -s option)"
       )
+
+globalNormalizationFlag :: Parser MixtureModelGlobalNormalization
+globalNormalizationFlag =
+  flag
+    LocalNormalization
+    GlobalNormalization
+    ( long "global-normalization"
+        <> short 'n'
+        <> help "Normalize mixture model globally (one normalization constant for all components)"
+    )
 
 maybeEDMFileOpt :: Parser (Maybe FilePath)
 maybeEDMFileOpt =
diff --git a/src/SLynx/Simulate/PhyloModel.hs b/src/SLynx/Simulate/PhyloModel.hs
--- a/src/SLynx/Simulate/PhyloModel.hs
+++ b/src/SLynx/Simulate/PhyloModel.hs
@@ -35,11 +35,8 @@
 import qualified ELynx.MarkovProcess.SubstitutionModel as S
 import ELynx.Tools.Equality
 import ELynx.Tools.InputOutput
-import Numeric.LinearAlgebra
-  ( norm_1,
-    size,
-    vector,
-  )
+import Numeric.LinearAlgebra (norm_1, size, vector)
+import SLynx.Simulate.Options (MixtureModelGlobalNormalization (..))
 
 nNuc :: Int
 -- nNuc = length (alphabet :: [Nucleotide])
@@ -109,59 +106,61 @@
 -- This is the main function that connects the model string, the parameters and
 -- the stationary distribution. It should check that the model is valid.
 assembleSubstitutionModel ::
+  S.Normalize ->
   String ->
   Maybe S.Params ->
   Maybe StationaryDistribution ->
   Either String S.SubstitutionModel
 -- DNA models.
-assembleSubstitutionModel "JC" Nothing Nothing = Right jc
-assembleSubstitutionModel "F81" Nothing (Just d) =
-  Right $ assertLength d nNuc $ f81 d
-assembleSubstitutionModel "HKY" (Just [k]) (Just d) =
-  Right $ assertLength d nNuc $ hky k d
-assembleSubstitutionModel "GTR4" (Just es) (Just d) =
-  Right $ assertLength d nNuc $ gtr4 es d
+assembleSubstitutionModel nz "JC" Nothing Nothing = Right $ jc nz
+assembleSubstitutionModel nz "F81" Nothing (Just d) =
+  Right $ assertLength d nNuc $ f81 nz d
+assembleSubstitutionModel nz "HKY" (Just [k]) (Just d) =
+  Right $ assertLength d nNuc $ hky nz k d
+assembleSubstitutionModel nz "GTR4" (Just es) (Just d) =
+  Right $ assertLength d nNuc $ gtr4 nz es d
 -- Protein models.
-assembleSubstitutionModel "Poisson" Nothing Nothing = Right poisson
-assembleSubstitutionModel "Poisson-Custom" Nothing (Just d) =
-  Right $ assertLength d nAA $ poissonCustom Nothing d
-assembleSubstitutionModel "LG" Nothing Nothing = Right lg
-assembleSubstitutionModel "LG-Custom" Nothing (Just d) =
-  Right $ assertLength d nAA $ lgCustom Nothing d
-assembleSubstitutionModel "WAG" Nothing Nothing = Right wag
-assembleSubstitutionModel "WAG-Custom" Nothing (Just d) =
-  Right $ assertLength d nAA $ wagCustom Nothing d
-assembleSubstitutionModel "GTR20" (Just es) (Just d) =
-  Right $ assertLength d nAA $ gtr20 es d
+assembleSubstitutionModel nz "Poisson" Nothing Nothing = Right $ poisson nz
+assembleSubstitutionModel nz "Poisson-Custom" Nothing (Just d) =
+  Right $ assertLength d nAA $ poissonCustom Nothing nz d
+assembleSubstitutionModel nz "LG" Nothing Nothing = Right $ lg nz
+assembleSubstitutionModel nz "LG-Custom" Nothing (Just d) =
+  Right $ assertLength d nAA $ lgCustom Nothing nz d
+assembleSubstitutionModel nz "WAG" Nothing Nothing = Right $ wag nz
+assembleSubstitutionModel nz "WAG-Custom" Nothing (Just d) =
+  Right $ assertLength d nAA $ wagCustom Nothing nz d
+assembleSubstitutionModel nz "GTR20" (Just es) (Just d) =
+  Right $ assertLength d nAA $ gtr20 nz es d
 -- Ohterwisse, we cannot assemble the model.
-assembleSubstitutionModel n mps mf =
+assembleSubstitutionModel nz n mps mf =
   Left $
     unlines
       [ "Cannot assemble substitution model.",
+        "Normalize: " ++ show nz,
         "Name: " ++ show n,
         "Parameters: " ++ show mps,
         "Stationary distribution: " ++ show mf
       ]
 
-parseSubstitutionModel :: Parser S.SubstitutionModel
-parseSubstitutionModel = do
+parseSubstitutionModel :: S.Normalize -> Parser S.SubstitutionModel
+parseSubstitutionModel nz = do
   n <- name
   mps <- optional params
   mf <- optional stationaryDistribution
-  let esm = assembleSubstitutionModel n mps mf
+  let esm = assembleSubstitutionModel nz n mps mf
   case esm of
     Left err -> fail err
     Right sm -> return sm
 
-edmModel :: [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel
-edmModel cs mws = do
+edmModel :: MixtureModelGlobalNormalization -> [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel
+edmModel nz cs mws = do
   _ <- string "EDM"
   _ <- char mmStart
   n <- name
   mps <- optional params
   _ <- char mmEnd
   when (null cs) $ error "edmModel: no EDM components given."
-  let sms = map (\c -> assembleSubstitutionModel n mps (Just $ snd c)) cs
+  let sms = map (\c -> assembleSubstitutionModel subNz n mps (Just $ snd c)) cs
       edmName = "EDM" ++ show (length cs)
       ws = fromMaybe (map fst cs) mws
       errs = [e | (Left e) <- sms]
@@ -171,30 +170,36 @@
     then fail $ head errs
     else
       return $
-        M.fromSubstitutionModels edmName (V.fromList ws) (V.fromList $ rights sms)
+        M.fromSubstitutionModels edmName mmNz (V.fromList ws) (V.fromList $ rights sms)
+  where
+    (subNz, mmNz) = case nz of
+      GlobalNormalization -> (S.DoNotNormalize, S.DoNormalize)
+      LocalNormalization -> (S.DoNormalize, S.DoNotNormalize)
 
-cxxModel :: Maybe [M.Weight] -> Parser M.MixtureModel
-cxxModel mws = do
+cxxModel :: MixtureModelGlobalNormalization -> Maybe [M.Weight] -> Parser M.MixtureModel
+cxxModel LocalNormalization _ = fail "Local normalization impossible with CXX models."
+cxxModel _ mws = do
   _ <- char 'C'
   n <- decimal :: Parser Int
   return $ cxx n mws
 
-standardMixtureModel :: [M.Weight] -> Parser M.MixtureModel
-standardMixtureModel ws = do
+standardMixtureModel :: MixtureModelGlobalNormalization -> [M.Weight] -> Parser M.MixtureModel
+standardMixtureModel nz ws = do
   _ <- string "MIXTURE"
   _ <- char mmStart
-  sms <- parseSubstitutionModel `sepBy1` char separator
+  sms <- parseSubstitutionModel subNz `sepBy1` char separator
   _ <- char mmEnd
   -- XXX: The use of `Data.List.NonEmpty.fromList` leads to uninformative error messages.
-  return $ M.fromSubstitutionModels "MIXTURE" (V.fromList ws) (V.fromList sms)
+  return $ M.fromSubstitutionModels "MIXTURE" mmNz (V.fromList ws) (V.fromList sms)
+  where
+    (subNz, mmNz) = case nz of
+      GlobalNormalization -> (S.DoNotNormalize, S.DoNormalize)
+      LocalNormalization -> (S.DoNormalize, S.DoNotNormalize)
 
-mixtureModel ::
-  Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel
-mixtureModel Nothing Nothing =
-  try (cxxModel Nothing) <|> fail "No weights provided."
-mixtureModel Nothing mws@(Just ws) =
-  try (cxxModel mws) <|> standardMixtureModel ws
-mixtureModel (Just cs) mws = edmModel cs mws
+mixtureModel :: MixtureModelGlobalNormalization -> Maybe [EDMComponent] -> Maybe [M.Weight] -> Parser M.MixtureModel
+mixtureModel nz Nothing Nothing = try (cxxModel nz Nothing) <|> fail "No weights provided."
+mixtureModel nz Nothing mws@(Just ws) = try (cxxModel nz mws) <|> standardMixtureModel nz ws
+mixtureModel nz (Just cs) mws = edmModel nz cs mws
 
 -- | Parse the phylogenetic model string. The argument list is somewhat long,
 -- but models can have many parameters and we have to check for redundant
@@ -206,26 +211,21 @@
 getPhyloModel ::
   Maybe String ->
   Maybe String ->
+  MixtureModelGlobalNormalization ->
   Maybe [M.Weight] ->
   Maybe [EDMComponent] ->
   Either String P.PhyloModel
-getPhyloModel Nothing Nothing _ _ = Left "No model was given. See help."
-getPhyloModel (Just _) (Just _) _ _ =
+getPhyloModel Nothing Nothing _ _ _ = Left "No model was given. See help."
+getPhyloModel (Just _) (Just _) _ _ _ =
   Left "Both, substitution and mixture model string given; use only one."
-getPhyloModel (Just s) Nothing Nothing Nothing =
-  Right $
-    P.SubstitutionModel $
-      parseStringWith
-        parseSubstitutionModel
-        s
-getPhyloModel (Just _) Nothing (Just _) _ =
+getPhyloModel (Just s) Nothing nz Nothing Nothing
+  | nz == GlobalNormalization = Left "Global normalization not possible for substitution models."
+  | otherwise = Right $ P.SubstitutionModel $ parseStringWith (parseSubstitutionModel S.DoNormalize) s
+getPhyloModel (Just _) Nothing _ (Just _) _ =
   Left "Weights given; but cannot be used with substitution model."
-getPhyloModel (Just _) Nothing _ (Just _) =
-  Left
-    "Empirical distribution mixture model components given; but cannot be used with substitution model."
-getPhyloModel Nothing (Just m) mws mcs =
-  Right $
-    P.MixtureModel $
-      parseStringWith
-        (mixtureModel mcs mws)
-        m
+getPhyloModel (Just _) Nothing _ _ (Just _) =
+  let msg1 = "Empirical distribution mixture model components given;"
+      msg2 = " but cannot be used with substitution model."
+   in Left $ msg1 <> msg2
+getPhyloModel Nothing (Just m) nz mws mcs =
+  Right $ P.MixtureModel $ parseStringWith (mixtureModel nz mcs mws) m
diff --git a/src/SLynx/Simulate/Simulate.hs b/src/SLynx/Simulate/Simulate.hs
--- a/src/SLynx/Simulate/Simulate.hs
+++ b/src/SLynx/Simulate/Simulate.hs
@@ -211,9 +211,10 @@
     : summarizeSM (MM.substModel c)
 
 -- Summarize a mixture model; lines to be printed to screen or log.
-summarizeMM :: MM.MixtureModel -> [BL.ByteString]
-summarizeMM m =
+summarizeMM :: MixtureModelGlobalNormalization -> MM.MixtureModel -> [BL.ByteString]
+summarizeMM nz m =
   [ BL.pack $ "Mixture model: " ++ MM.name m ++ ".",
+    BL.pack $ "Mixture model normalization: " ++ show nz ++ ".",
     BL.pack $ "Number of components: " ++ show n ++ "."
   ]
     ++ detail
@@ -229,9 +230,9 @@
         else []
 
 -- Summarize a phylogenetic model; lines to be printed to screen or log.
-summarizePM :: MP.PhyloModel -> [BL.ByteString]
-summarizePM (MP.MixtureModel mm) = summarizeMM mm
-summarizePM (MP.SubstitutionModel sm) = summarizeSM sm
+summarizePM :: MixtureModelGlobalNormalization -> MP.PhyloModel -> [BL.ByteString]
+summarizePM nz (MP.MixtureModel mm) = summarizeMM nz mm
+summarizePM _ (MP.SubstitutionModel sm) = summarizeSM sm
 
 -- | Simulate sequences.
 simulateCmd :: ELynx SimulateArguments ()
@@ -278,17 +279,18 @@
   let ms = argsSubstitutionModelString l
       mm = argsMixtureModelString l
       mws = argsMixtureWeights l
-      eitherPhyloModel' = getPhyloModel ms mm mws edmCsOrSiteprofiles
+      nz = argsMixtureModelGlobalNormalization l
+      eitherPhyloModel' = getPhyloModel ms mm nz mws edmCsOrSiteprofiles
   phyloModel' <- case eitherPhyloModel' of
     Left err -> lift $ error err
     Right pm -> return pm
   let maybeGammaParams = argsGammaParams l
   phyloModel <- case maybeGammaParams of
     Nothing -> do
-      logInfoB $ BL.unlines $ summarizePM phyloModel'
+      logInfoB $ BL.unlines $ summarizePM nz phyloModel'
       return phyloModel'
     Just (n, alpha) -> do
-      logInfoB $ BL.intercalate "\n" $ summarizePM phyloModel'
+      logInfoB $ BL.intercalate "\n" $ summarizePM nz phyloModel'
       logInfoS ""
       logInfoB $ BL.intercalate "\n" $ summarizeGammaRateHeterogeneity n alpha
       return $ expand n alpha phyloModel'
