Coverage for src/beamme/four_c/beam_potential.py: 88%
32 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:17 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:17 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2018-2025 BeamMe Authors
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22"""This file includes functions to ease the creation of input files using beam
23interaction potentials."""
25from beamme.core.boundary_condition import BoundaryCondition as _BoundaryCondition
28class BeamPotential:
29 """Class which provides functions for the usage of beam to beam potential
30 interactions within 4C based on a potential law in form of a power law."""
32 def __init__(
33 self,
34 input_file,
35 mesh,
36 *,
37 pot_law_prefactor=None,
38 pot_law_exponent=None,
39 pot_law_line_charge_density=None,
40 pot_law_line_charge_density_funcs=None,
41 ):
42 """Initialize object to enable beam potential interactions.
44 Args
45 ----
46 input_file:
47 Input file of current problem setup.
48 mesh:
49 Mesh object of current problem setup.
50 pot_law_prefactors: float, int, _np.array, list
51 Prefactors of a potential law in form of a power law. Same number
52 of prefactors and exponents/line charge densities/functions must be
53 provided!
54 pot_law_exponent: float, int, _np.array, list
55 Exponents of a potential law in form of a power law. Same number
56 of exponents and prefactors/line charge densities/functions must be
57 provided!
58 pot_law_line_charge_density: float, int, _np.array, list
59 Line charge densities of a potential law in form of a power law.
60 Same number of line charge densities and prefactors/exponents/functions
61 must be provided!
62 pot_law_line_charge_density_funcs:
63 Functions for line charge densities of a potential law in form of a
64 power law. Same number of functions and prefactors/exponents/line
65 charge densities must be provided!
66 """
68 self.input_file = input_file
69 self.mesh = mesh
71 # if only one potential law prefactor/exponent is present, convert it
72 # into a list for simplified usage
73 if isinstance(pot_law_prefactor, (float, int)):
74 pot_law_prefactor = [pot_law_prefactor]
75 if isinstance(pot_law_exponent, (float, int)):
76 pot_law_exponent = [pot_law_exponent]
77 if isinstance(pot_law_line_charge_density, (float, int)):
78 pot_law_line_charge_density = [pot_law_line_charge_density]
80 # check if same number of prefactors and exponents are provided
81 if (
82 not len(pot_law_prefactor)
83 == len(pot_law_exponent)
84 == len(pot_law_line_charge_density)
85 ):
86 raise ValueError(
87 "Number of potential law prefactors do not match potential law exponents!"
88 )
90 self.pot_law_prefactor = pot_law_prefactor
91 self.pot_law_exponent = pot_law_exponent
92 self.pot_law_line_charge_density = pot_law_line_charge_density
93 self.pot_law_line_charge_density_funcs = pot_law_line_charge_density_funcs
95 def add_header(
96 self,
97 *,
98 potential_type="volume",
99 cutoff_radius=None,
100 evaluation_strategy=None,
101 regularization_type=None,
102 regularization_separation=None,
103 integration_segments=1,
104 gauss_points=10,
105 potential_reduction_length=-1,
106 automatic_differentiation=False,
107 choice_master_slave=None,
108 ):
109 """Set the basic header options for beam potential interactions.
111 Args
112 ----
113 potential_type: string
114 Type of applied potential (volume, surface).
115 cutoff_radius: float
116 Neglect all contributions at separation larger than this cutoff
117 radius.
118 evaluation_strategy: string
119 Strategy to evaluate interaction potential.
120 regularization_type: string
121 Type of regularization to use for force law at separations below
122 specified separation (constant_extrapolation, linear_extrapolation).
123 regularization_separation: float
124 Use specified regularization type for separations smaller than
125 this value.
126 integration_segments: int
127 Number of integration segments to be used per beam element.
128 gauss_points: int
129 Number of Gauss points to be used per integration segment.
130 potential_reduction_length: float
131 Potential is smoothly decreased within this length when using the
132 single length specific (SBIP) approach to enable an axial pull off
133 force.
134 automatic_differentiation: bool
135 Use automatic differentiation via FAD.
136 choice_master_slave: string
137 Rule how to assign the role of master and slave to beam elements (if
138 applicable) (lower_eleGID_is_slave, higher_eleGID_is_slave).
139 """
141 settings = {
142 "POT_LAW_PREFACTOR": " ".join(map(str, self.pot_law_prefactor)),
143 "POT_LAW_EXPONENT": " ".join(map(str, self.pot_law_exponent)),
144 "TYPE": potential_type,
145 "CUTOFF_RADIUS": cutoff_radius,
146 "STRATEGY": evaluation_strategy,
147 "N_INTEGRATION_SEGMENTS": integration_segments,
148 "N_GAUSS_POINTS": gauss_points,
149 "POTENTIAL_REDUCTION_LENGTH": potential_reduction_length,
150 "AUTOMATIC_DIFFERENTIATION": automatic_differentiation,
151 }
153 if regularization_type is not None:
154 settings = settings | {
155 "REGULARIZATION_TYPE": regularization_type,
156 "REGULARIZATION_SEPARATION": regularization_separation,
157 }
159 if choice_master_slave is not None:
160 settings = settings | {"CHOICE_MASTER_SLAVE": choice_master_slave}
162 self.input_file.add(
163 {"BEAM POTENTIAL": settings},
164 )
166 def add_runtime_output(
167 self,
168 *,
169 output_beam_potential=True,
170 interval_steps=1,
171 every_iteration=False,
172 forces=True,
173 moments=True,
174 uids=True,
175 per_ele_pair=True,
176 ):
177 """Set the basic runtime output options for beam potential
178 interactions.
180 Args
181 ----
182 output_beam_potential: bool
183 If the output for beam potential should be written.
184 interval_steps: int
185 Interval at which output is written.
186 every_iteration: bool
187 If output at every Newton iteration should be written.
188 forces: bool
189 If the forces should be written.
190 moments: bool
191 If the moments should be written.
192 uids: bool
193 If the unique ids should be written.
194 per_ele_pair: bool
195 If the forces/moments should be written per element pair.
196 """
198 self.input_file.add(
199 {
200 "BEAM POTENTIAL/RUNTIME VTK OUTPUT": {
201 "VTK_OUTPUT_BEAM_POTENTIAL": output_beam_potential,
202 "INTERVAL_STEPS": interval_steps,
203 "EVERY_ITERATION": every_iteration,
204 "FORCES": forces,
205 "MOMENTS": moments,
206 "WRITE_UIDS": uids,
207 "WRITE_FORCE_MOMENT_PER_ELEMENTPAIR": per_ele_pair,
208 }
209 }
210 )
212 def add_potential_charge_condition(self, *, geometry_set=None):
213 """Add potential charge condition to geometry.
215 Args
216 ----
217 geometry_set:
218 Add potential charge condition to this set.
219 """
221 for i, (line_charge, func) in enumerate(
222 zip(
223 self.pot_law_line_charge_density, self.pot_law_line_charge_density_funcs
224 )
225 ):
226 if func != "none":
227 self.mesh.add(func)
229 bc = _BoundaryCondition(
230 geometry_set,
231 {"POTLAW": i + 1, "VAL": line_charge, "FUNCT": func},
232 bc_type="DESIGN LINE BEAM POTENTIAL CHARGE CONDITIONS",
233 )
235 self.mesh.add(bc)