public IGlobalFreeDofOrdering OrderFreeDofs(IModel model)
        {
            if (doOptimizationsIfSingleSubdomain && (model.Subdomains.Count == 1))
            {
                ISubdomain subdomain = model.Subdomains.First();

                // Order subdomain dofs
                (int numSubdomainFreeDofs, DofTable subdomainFreeDofs) = freeOrderingStrategy.OrderSubdomainDofs(subdomain);
                ISubdomainFreeDofOrdering subdomainOrdering;
                if (cacheElementToSubdomainDofMaps)
                {
                    subdomainOrdering = new SubdomainFreeDofOrderingCaching(numSubdomainFreeDofs, subdomainFreeDofs);
                }
                else
                {
                    subdomainOrdering = new SubdomainFreeDofOrderingGeneral(numSubdomainFreeDofs, subdomainFreeDofs);
                }

                // Reorder subdomain dofs
                reorderingStrategy.ReorderDofs(subdomain, subdomainOrdering);

                // Order global dofs
                return(new GlobalFreeDofOrderingSingle(subdomain, subdomainOrdering));
            }
            else
            {
                // Order subdomain dofs
                var subdomainOrderings = new Dictionary <ISubdomain, ISubdomainFreeDofOrdering>(model.Subdomains.Count);
                foreach (ISubdomain subdomain in model.Subdomains)
                {
                    (int numSubdomainFreeDofs, DofTable subdomainFreeDofs) = freeOrderingStrategy.OrderSubdomainDofs(subdomain);
                    ISubdomainFreeDofOrdering subdomainOrdering;
                    if (cacheElementToSubdomainDofMaps)
                    {
                        subdomainOrdering = new SubdomainFreeDofOrderingCaching(
                            numSubdomainFreeDofs, subdomainFreeDofs);
                    }
                    else
                    {
                        subdomainOrdering = new SubdomainFreeDofOrderingGeneral(numSubdomainFreeDofs, subdomainFreeDofs);
                    }
                    subdomainOrderings.Add(subdomain, subdomainOrdering);

                    // Reorder subdomain dofs
                    reorderingStrategy.ReorderDofs(subdomain, subdomainOrdering);
                }

                // Order global dofs
                (int numGlobalFreeDofs, DofTable globalFreeDofs) = freeOrderingStrategy.OrderGlobalDofs(model);
                return(new GlobalFreeDofOrderingGeneral(numGlobalFreeDofs, globalFreeDofs, subdomainOrderings));
            }
        }
        public IGlobalFreeDofOrdering OrderFreeDofs(IModel model)
        {
            if (doOptimizationsIfSingleSubdomain && (model.Subdomains.Count == 1))
            {
                ISubdomain subdomain = model.Subdomains.First();
                ISubdomainFreeDofOrdering subdomainOrdering;
                if (!subdomain.ConnectivityModified)
                {
                    subdomainOrdering = subdomain.FreeDofOrdering;
                }
                else
                {
                    // Order subdomain dofs
                    Debug.WriteLine($"{this.GetType().Name}: Ordering free dofs of subdomain {subdomain.ID}");
                    (int numSubdomainFreeDofs, DofTable subdomainFreeDofs) = freeOrderingStrategy.OrderSubdomainDofs(subdomain);
                    if (cacheElementToSubdomainDofMaps)
                    {
                        subdomainOrdering = new SubdomainFreeDofOrderingCaching(numSubdomainFreeDofs, subdomainFreeDofs);
                    }
                    else
                    {
                        subdomainOrdering = new SubdomainFreeDofOrderingGeneral(numSubdomainFreeDofs, subdomainFreeDofs);
                    }

                    // Reorder subdomain dofs
                    reorderingStrategy.ReorderDofs(subdomain, subdomainOrdering);
                }

                // Order global dofs
                return(new GlobalFreeDofOrderingSingle(subdomain, subdomainOrdering));
            }
            else
            {
                // Order subdomain dofs
                var subdomainOrderings = new Dictionary <ISubdomain, ISubdomainFreeDofOrdering>(model.Subdomains.Count);
                foreach (ISubdomain subdomain in model.Subdomains)
                {
                    ISubdomainFreeDofOrdering subdomainOrdering;
                    if (!subdomain.ConnectivityModified)
                    {
                        subdomainOrdering = subdomain.FreeDofOrdering;
                    }
                    else
                    {
                        Debug.WriteLine($"{this.GetType().Name}: Ordering free dofs of subdomain {subdomain.ID}");
                        (int numSubdomainFreeDofs, DofTable subdomainFreeDofs) = freeOrderingStrategy.OrderSubdomainDofs(subdomain);
                        if (cacheElementToSubdomainDofMaps)
                        {
                            subdomainOrdering = new SubdomainFreeDofOrderingCaching(numSubdomainFreeDofs, subdomainFreeDofs);
                        }
                        else
                        {
                            subdomainOrdering = new SubdomainFreeDofOrderingGeneral(numSubdomainFreeDofs, subdomainFreeDofs);
                        }

                        // Reorder subdomain dofs
                        reorderingStrategy.ReorderDofs(subdomain, subdomainOrdering);
                    }
                    subdomainOrderings.Add(subdomain, subdomainOrdering);
                }

                // Order global dofs
                (int numGlobalFreeDofs, DofTable globalFreeDofs) = freeOrderingStrategy.OrderGlobalDofs(model);
                return(new GlobalFreeDofOrderingGeneral(numGlobalFreeDofs, globalFreeDofs, subdomainOrderings));
            }
        }