Source code for ansys.dyna.core.lib.card_layout

# Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""Pure functions for assembling a keyword's card sequence.

Given a flat list of ``CardInterface`` objects (which may include
``OptionCardSet`` entries) and an ``OptionsInterface`` that knows which
options are active, these functions compute the ordered card list used
for reading and writing keyword data.
"""

import typing

from ansys.dyna.core.lib.card_interface import CardInterface
from ansys.dyna.core.lib.card_position import CardPlacement
from ansys.dyna.core.lib.option_card import OptionCardSet, OptionsInterface


[docs] def get_non_option_cards(cards: typing.List[CardInterface]) -> typing.List[CardInterface]: """Return cards that are not ``OptionCardSet`` entries.""" return [card for card in cards if type(card) != OptionCardSet]
[docs] def get_sorted_option_cards(cards: typing.List[CardInterface]) -> typing.List[OptionCardSet]: """Return ``OptionCardSet`` entries sorted by position.""" option_cards = [card for card in cards if type(card) == OptionCardSet] option_cards.sort() return option_cards
[docs] def get_post_options_with_no_title_order(cards: typing.List[CardInterface]) -> typing.List[OptionCardSet]: """Return POST-placed option cards that have ``title_order == 0``. These represent options whose presence is discovered at read time (they don't appear in the keyword title line). """ option_cards = [card for card in get_sorted_option_cards(cards) if card.title_order == 0] for option_card in option_cards: if option_card.position.placement == CardPlacement.PRE: raise ValueError("Cards with a title order of 0 must not have 'pre' placement") return [o for o in option_cards if o.position.placement == CardPlacement.POST]
[docs] def get_active_options(cards: typing.List[CardInterface], options_api: OptionsInterface) -> typing.List[OptionCardSet]: """Return active option card sets, sorted by position.""" option_cards = get_sorted_option_cards(cards) return [o for o in option_cards if options_api.is_option_active(o.name)]
[docs] def get_pre_option_cards( cards: typing.List[CardInterface], options_api: OptionsInterface ) -> typing.List[CardInterface]: """Return the inner cards of active PRE-placed option sets.""" active = get_active_options(cards, options_api) nested = [o.cards for o in active if o.position.placement == CardPlacement.PRE] return [card for group in nested for card in group]
[docs] def get_post_option_cards( cards: typing.List[CardInterface], options_api: OptionsInterface ) -> typing.List[CardInterface]: """Return the inner cards of active POST-placed option sets.""" active = get_active_options(cards, options_api) nested = [o.cards for o in active if o.position.placement == CardPlacement.POST] return [card for group in nested for card in group]
[docs] def get_main_option_cards_by_index( cards: typing.List[CardInterface], options_api: OptionsInterface ) -> typing.Dict[int, typing.List[CardInterface]]: """Return active MAIN option cards grouped by their insertion index. The key *N* is the 0-based index of the non-option card **after which** the option cards are inserted. """ active = get_active_options(cards, options_api) by_index: typing.Dict[int, typing.List[CardInterface]] = {} for option_set in active: if option_set.position.placement == CardPlacement.MAIN: idx = option_set.position.index by_index.setdefault(idx, []).extend(option_set.cards) return by_index
[docs] def get_all_cards(cards: typing.List[CardInterface], options_api: OptionsInterface) -> typing.List[CardInterface]: """Assemble the full card sequence with active option cards interleaved. Layout order: PRE options, then non-option cards with MAIN options inserted at their designated indices, then POST options. """ main_by_index = get_main_option_cards_by_index(cards, options_api) result = get_pre_option_cards(cards, options_api) non_option = get_non_option_cards(cards) for i, card in enumerate(non_option): result.append(card) result.extend(main_by_index.get(i, [])) result.extend(get_post_option_cards(cards, options_api)) return result