abmptools 2.1.0__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. {abmptools-2.1.0/abmptools.egg-info → abmptools-2.2.0}/PKG-INFO +18 -1
  2. {abmptools-2.1.0 → abmptools-2.2.0}/README.md +5 -0
  3. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/molecule_prep.py +8 -1
  4. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/__init__.py +4 -1
  5. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/__main__.py +30 -0
  6. abmptools-2.2.0/abmptools/cg/dpd/aij_assign.py +173 -0
  7. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/orchestrator.py +7 -2
  8. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/udf_writer.py +12 -4
  9. abmptools-2.2.0/abmptools/cg/dpd/udf_writer_udfm.py +249 -0
  10. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/builder.py +161 -12
  11. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/ndx.py +7 -2
  12. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/peptide_atomistic_openff.py +79 -42
  13. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/topology.py +81 -0
  14. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/topology_openff.py +185 -15
  15. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/__init__.py +10 -0
  16. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/__main__.py +51 -4
  17. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/dpdgen_exporter.py +21 -8
  18. abmptools-2.2.0/abmptools/fragmenter/cg_segmenter/fcews_export.py +316 -0
  19. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/notebook_ui.py +5 -4
  20. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/orchestrator.py +38 -0
  21. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/expand_to_system.py +40 -36
  22. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/analyzer.py +17 -5
  23. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/cli.py +7 -0
  24. abmptools-2.2.0/abmptools/udfcharge/__init__.py +28 -0
  25. abmptools-2.2.0/abmptools/udfcharge/__main__.py +63 -0
  26. abmptools-2.2.0/abmptools/udfcharge/core.py +279 -0
  27. {abmptools-2.1.0 → abmptools-2.2.0/abmptools.egg-info}/PKG-INFO +18 -1
  28. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools.egg-info/SOURCES.txt +6 -0
  29. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools.egg-info/requires.txt +13 -0
  30. {abmptools-2.1.0 → abmptools-2.2.0}/pyproject.toml +24 -1
  31. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_charge_method.py +15 -4
  32. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_ndx.py +23 -0
  33. {abmptools-2.1.0 → abmptools-2.2.0}/LICENSE +0 -0
  34. {abmptools-2.1.0 → abmptools-2.2.0}/NOTICE +0 -0
  35. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/__init__.py +0 -0
  36. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/abinit_io.py +0 -0
  37. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/addsolvfrag.py +0 -0
  38. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/ajf2config.py +0 -0
  39. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/ajfserial.py +0 -0
  40. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/__init__.py +0 -0
  41. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/__main__.py +0 -0
  42. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/builder.py +0 -0
  43. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/cli.py +0 -0
  44. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/density.py +0 -0
  45. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/mdp_protocol.py +0 -0
  46. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/models.py +0 -0
  47. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/ndx_writer.py +0 -0
  48. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/packing.py +0 -0
  49. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/parameterizer.py +0 -0
  50. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/pubchem.py +0 -0
  51. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/system_model_adapter.py +0 -0
  52. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/amorphous/trajectory_ingest.py +0 -0
  53. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/anlfmo.py +0 -0
  54. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/__init__.py +0 -0
  55. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/aij_io.py +0 -0
  56. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/calc_sett_io.py +0 -0
  57. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/dpm_writer.py +0 -0
  58. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/models.py +0 -0
  59. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/monomer_io.py +0 -0
  60. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/dpd/notebook_ui.py +0 -0
  61. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/__init__.py +0 -0
  62. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/__main__.py +0 -0
  63. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/_subprocess.py +0 -0
  64. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/builder.py +0 -0
  65. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/cli.py +0 -0
  66. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/forcefield_check.py +0 -0
  67. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/insane_runner.py +0 -0
  68. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/mdp_templates.py +0 -0
  69. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/models.py +0 -0
  70. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/pmf.py +0 -0
  71. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/pulling.py +0 -0
  72. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/system_packer.py +0 -0
  73. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/topology_composer.py +0 -0
  74. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/membrane/umbrella.py +0 -0
  75. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/__init__.py +0 -0
  76. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/__main__.py +0 -0
  77. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/_subprocess.py +0 -0
  78. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/builder.py +0 -0
  79. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/cli.py +0 -0
  80. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/forcefield_check.py +0 -0
  81. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/martinize_runner.py +0 -0
  82. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/mdp_templates.py +0 -0
  83. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/models.py +0 -0
  84. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/peptide_atomistic.py +0 -0
  85. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/system_packer.py +0 -0
  86. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/top_writer.py +0 -0
  87. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cg/peptide/water_box.py +0 -0
  88. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/convertcpf.py +0 -0
  89. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/core/__init__.py +0 -0
  90. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/core/system_model.py +0 -0
  91. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cpf2ifielist.py +0 -0
  92. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/cpfmanager.py +0 -0
  93. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/__init__.py +0 -0
  94. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/__main__.py +0 -0
  95. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/_subprocess.py +0 -0
  96. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/atom_distance.py +0 -0
  97. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/builder.py +0 -0
  98. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/cif_engine_ase.py +0 -0
  99. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/cif_engine_legacy.py +0 -0
  100. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/cli.py +0 -0
  101. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/forcefield_check.py +0 -0
  102. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/job_templates.py +0 -0
  103. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/legacy/__init__.py +0 -0
  104. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/models.py +0 -0
  105. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/crystal/postproc.py +0 -0
  106. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/f90/bin/readifiepiedalib.so +0 -0
  107. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/__init__.py +0 -0
  108. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/__main__.py +0 -0
  109. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/_subprocess.py +0 -0
  110. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/__init__.py +0 -0
  111. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/aggregate_transition.py +0 -0
  112. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/contact_map.py +0 -0
  113. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/hbond.py +0 -0
  114. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/plots.py +0 -0
  115. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/sasa.py +0 -0
  116. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/analysis/secondary_structure.py +0 -0
  117. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/cli.py +0 -0
  118. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/mdp_templates.py +0 -0
  119. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/models.py +0 -0
  120. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/packer.py +0 -0
  121. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/peptide_atomistic.py +0 -0
  122. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/small_molecule.py +0 -0
  123. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/small_molecule_openff.py +0 -0
  124. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/formulation/umbrella_release.py +0 -0
  125. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/__init__.py +0 -0
  126. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/__main__.py +0 -0
  127. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/auto_split.py +0 -0
  128. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/cap_attach.py +0 -0
  129. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/chain_splitter.py +0 -0
  130. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/exporter.py +0 -0
  131. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/models.py +0 -0
  132. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cg_segmenter/ring_detector.py +0 -0
  133. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/cut_apply.py +0 -0
  134. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/grouping.py +0 -0
  135. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/headless_io.py +0 -0
  136. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/models.py +0 -0
  137. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/notebook_ui.py +0 -0
  138. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/pdb_loader.py +0 -0
  139. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/fragmenter/polymer.py +0 -0
  140. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/generate_difie.py +0 -0
  141. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/generateajf.py +0 -0
  142. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/__init__.py +0 -0
  143. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/__init__.py +0 -0
  144. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/__main__.py +0 -0
  145. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/_subprocess.py +0 -0
  146. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/analysis.py +0 -0
  147. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/builder.py +0 -0
  148. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/cli.py +0 -0
  149. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/forcefield_check.py +0 -0
  150. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/grest_runner.py +0 -0
  151. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/inp_writer.py +0 -0
  152. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/models.py +0 -0
  153. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/replica_temperatures.py +0 -0
  154. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/rest_selection.py +0 -0
  155. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/grest/system_builder.py +0 -0
  156. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/__init__.py +0 -0
  157. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/__main__.py +0 -0
  158. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/_subprocess.py +0 -0
  159. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/analysis.py +0 -0
  160. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/builder.py +0 -0
  161. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/cli.py +0 -0
  162. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/forcefield_check.py +0 -0
  163. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/gbsa_runner.py +0 -0
  164. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/inp_writer.py +0 -0
  165. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/ligand_parameterize.py +0 -0
  166. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/models.py +0 -0
  167. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/pdb_splitter.py +0 -0
  168. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/genesis/mmgbsa/system_builder.py +0 -0
  169. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/geomopt/__init__.py +0 -0
  170. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/geomopt/mace_optimizer.py +0 -0
  171. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/geomopt/openff_openmm_minimizer.py +0 -0
  172. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/geomopt/pyscf_optimizer.py +0 -0
  173. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/getcharge.py +0 -0
  174. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/getifiepieda.py +0 -0
  175. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/__init__.py +0 -0
  176. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/__main__.py +0 -0
  177. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/cli.py +0 -0
  178. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/default_template.udf +0 -0
  179. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/default_template_cognac101.udf +0 -0
  180. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/exporter.py +0 -0
  181. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/gro_adapter.py +0 -0
  182. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/gro_parser.py +0 -0
  183. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/mdp_parser.py +0 -0
  184. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/top_adapter.py +0 -0
  185. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/top_exporter.py +0 -0
  186. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/top_model.py +0 -0
  187. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/top_parser.py +0 -0
  188. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/trajectory_io.py +0 -0
  189. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/gro2udf/udf_writer.py +0 -0
  190. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/__init__.py +0 -0
  191. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/__main__.py +0 -0
  192. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/bdf_reader.py +0 -0
  193. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/classifier.py +0 -0
  194. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/colorizer.py +0 -0
  195. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/distance_dist.py +0 -0
  196. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/func_tags.py +0 -0
  197. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/functional_groups.py +0 -0
  198. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/hbond_detector.py +0 -0
  199. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/lifetime.py +0 -0
  200. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/notebook_ui.py +0 -0
  201. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/hbond/pair_type_stats.py +0 -0
  202. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/log2config.py +0 -0
  203. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/log2cpf.py +0 -0
  204. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/logmanager.py +0 -0
  205. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/__init__.py +0 -0
  206. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/bilayer.py +0 -0
  207. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/builder.py +0 -0
  208. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/lipid_info.py +0 -0
  209. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/mdp_us_protocol.py +0 -0
  210. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/models.py +0 -0
  211. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/parameterize_amber.py +0 -0
  212. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/parameterize_charmm.py +0 -0
  213. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/pmf.py +0 -0
  214. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/pulling.py +0 -0
  215. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/topology_sanity.py +0 -0
  216. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/membrane/umbrella.py +0 -0
  217. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/mol_io.py +0 -0
  218. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/molcalc.py +0 -0
  219. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/pdb2fmo.py +0 -0
  220. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/pdb_io.py +0 -0
  221. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/pdbmodify.py +0 -0
  222. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/readcif.py +0 -0
  223. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/setfmo.py +0 -0
  224. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/trajectory/__init__.py +0 -0
  225. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/trajectory/__main__.py +0 -0
  226. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/trajectory/cli.py +0 -0
  227. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/trajectory/postprocess.py +0 -0
  228. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2fmo.py +0 -0
  229. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/__init__.py +0 -0
  230. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/__main__.py +0 -0
  231. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/cli.py +0 -0
  232. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/exporter.py +0 -0
  233. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/__init__.py +0 -0
  234. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/__init__.py +0 -0
  235. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/_validator.py +0 -0
  236. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/gro_writer.py +0 -0
  237. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/itp_writer.py +0 -0
  238. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/mdp_writer.py +0 -0
  239. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/gromacs/writers/top_writer.py +0 -0
  240. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf2gro/udf_adapter.py +0 -0
  241. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udf_io.py +0 -0
  242. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udfcreate.py +0 -0
  243. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udfcreate_v2.py +0 -0
  244. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools/udfrm_io.py +0 -0
  245. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools.egg-info/dependency_links.txt +0 -0
  246. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools.egg-info/entry_points.txt +0 -0
  247. {abmptools-2.1.0 → abmptools-2.2.0}/abmptools.egg-info/top_level.txt +0 -0
  248. {abmptools-2.1.0 → abmptools-2.2.0}/setup.cfg +0 -0
  249. {abmptools-2.1.0 → abmptools-2.2.0}/setup.py +0 -0
  250. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_abinit_io.py +0 -0
  251. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_amorphous_models.py +0 -0
  252. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_anlfmo.py +0 -0
  253. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_builder_integration.py +0 -0
  254. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_builder_mocked.py +0 -0
  255. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_builder_mocked.py +0 -0
  256. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_cli.py +0 -0
  257. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_forcefield_check.py +0 -0
  258. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_insane_runner.py +0 -0
  259. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_integration.py +0 -0
  260. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_mdp.py +0 -0
  261. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_models.py +0 -0
  262. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_packer.py +0 -0
  263. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_pmf.py +0 -0
  264. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_pulling.py +0 -0
  265. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_topology_composer.py +0 -0
  266. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_membrane_umbrella.py +0 -0
  267. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_atomistic.py +0 -0
  268. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_builder_mocked.py +0 -0
  269. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_cli.py +0 -0
  270. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_forcefield_check.py +0 -0
  271. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_integration.py +0 -0
  272. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_martinize_runner.py +0 -0
  273. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_mdp.py +0 -0
  274. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_models.py +0 -0
  275. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_packer.py +0 -0
  276. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_subprocess.py +0 -0
  277. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_topwriter.py +0 -0
  278. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cg_peptide_water_box.py +0 -0
  279. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cli_scripts.py +0 -0
  280. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_cpfmanager.py +0 -0
  281. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_atom_distance.py +0 -0
  282. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_builder.py +0 -0
  283. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_cif_ase.py +0 -0
  284. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_cif_legacy.py +0 -0
  285. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_cli.py +0 -0
  286. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_job_templates.py +0 -0
  287. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_models.py +0 -0
  288. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_numeric_regression.py +0 -0
  289. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_crystal_regression.py +0 -0
  290. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_density.py +0 -0
  291. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_analysis.py +0 -0
  292. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_builder.py +0 -0
  293. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_mdp.py +0 -0
  294. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_models.py +0 -0
  295. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_packer.py +0 -0
  296. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_peptide_atomistic.py +0 -0
  297. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_small_molecule.py +0 -0
  298. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_topology.py +0 -0
  299. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_formulation_umbrella_release.py +0 -0
  300. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_getifiepieda.py +0 -0
  301. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_analysis_mocked.py +0 -0
  302. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_builder_mocked.py +0 -0
  303. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_cli.py +0 -0
  304. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_inp_writer.py +0 -0
  305. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_integration.py +0 -0
  306. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_models.py +0 -0
  307. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_replica_temperatures.py +0 -0
  308. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_rest_selection.py +0 -0
  309. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_grest_system_builder.py +0 -0
  310. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_gro_adapter.py +0 -0
  311. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_gro_parser.py +0 -0
  312. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_gro_writer.py +0 -0
  313. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_interchange_adapter.py +0 -0
  314. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_logmanager.py +0 -0
  315. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mdp_parser.py +0 -0
  316. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mdp_protocol.py +0 -0
  317. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mdp_writer.py +0 -0
  318. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_membrane_charmm_translate.py +0 -0
  319. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_membrane_mixed_lipid.py +0 -0
  320. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_membrane_topology_sanity.py +0 -0
  321. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_analysis.py +0 -0
  322. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_builder_mocked.py +0 -0
  323. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_cli.py +0 -0
  324. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_forcefield_check.py +0 -0
  325. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_inp_writer.py +0 -0
  326. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_integration.py +0 -0
  327. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_models.py +0 -0
  328. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_pdb_splitter.py +0 -0
  329. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mmgbsa_system_builder.py +0 -0
  330. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_mol_io.py +0 -0
  331. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_molcalc.py +0 -0
  332. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_ndx_writer.py +0 -0
  333. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_parameterizer.py +0 -0
  334. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_pdb_io.py +0 -0
  335. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_pubchem.py +0 -0
  336. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_pyscf_optimizer.py +0 -0
  337. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_pyscf_parsers.py +0 -0
  338. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_read_ifie_hf_fallback.py +0 -0
  339. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_readcif.py +0 -0
  340. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_regression.py +0 -0
  341. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_setfmo.py +0 -0
  342. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_system_model.py +0 -0
  343. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_system_model_extensions.py +0 -0
  344. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_top_exporter_frames_override.py +0 -0
  345. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_top_model.py +0 -0
  346. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_top_parser.py +0 -0
  347. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_top_writer.py +0 -0
  348. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_trajectory_ingest.py +0 -0
  349. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_trajectory_postprocess.py +0 -0
  350. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_udf_io.py +0 -0
  351. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_udfcreate.py +0 -0
  352. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_udfcreate_v2.py +0 -0
  353. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_udfcreate_v2_byte_equivalence.py +0 -0
  354. {abmptools-2.1.0 → abmptools-2.2.0}/tests/test_udfrm_io.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abmptools
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Pre/post-processing and analysis toolkit for ABINIT-MP Fragment Molecular Orbital calculations
5
5
  Author-email: Koji Okuwaki <koujioku81@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -59,6 +59,18 @@ Provides-Extra: formulation-analysis
59
59
  Requires-Dist: MDAnalysis<3.0,>=2.6; extra == "formulation-analysis"
60
60
  Requires-Dist: networkx>=3.0; extra == "formulation-analysis"
61
61
  Requires-Dist: matplotlib>=3.5; extra == "formulation-analysis"
62
+ Provides-Extra: formulation-openff
63
+ Requires-Dist: openff-toolkit>=0.14.0; extra == "formulation-openff"
64
+ Requires-Dist: openff-interchange>=0.3.0; extra == "formulation-openff"
65
+ Requires-Dist: openff-amber-ff-ports>=0.0.3; extra == "formulation-openff"
66
+ Requires-Dist: openff-nagl>=0.3; extra == "formulation-openff"
67
+ Requires-Dist: openff-nagl-models>=0.1; extra == "formulation-openff"
68
+ Requires-Dist: openmm>=8.0; extra == "formulation-openff"
69
+ Requires-Dist: pdbfixer>=1.9; extra == "formulation-openff"
70
+ Requires-Dist: rdkit-pypi>=2022.09; extra == "formulation-openff"
71
+ Requires-Dist: matplotlib>=3.5; extra == "formulation-openff"
72
+ Requires-Dist: PeptideBuilder>=1.1; extra == "formulation-openff"
73
+ Requires-Dist: biopython>=1.79; extra == "formulation-openff"
62
74
  Provides-Extra: geomopt
63
75
  Requires-Dist: pyscf; extra == "geomopt"
64
76
  Requires-Dist: ase; extra == "geomopt"
@@ -109,6 +121,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
109
121
 
110
122
  - **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
111
123
  - **gro2udf**: Convert GROMACS files to OCTA UDF format (supports `--from-top` mode)
124
+ - **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to every same-named molecule in a bulk UDF
112
125
 
113
126
  ### Geometry Optimization (`geomopt`)
114
127
 
@@ -300,6 +313,9 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
300
313
  # Convert GROMACS to UDF
301
314
  python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
302
315
 
316
+ # Transfer charges from a single-molecule UDF to all same-named molecules in a bulk UDF
317
+ python -m abmptools.udfcharge --template mol.udf --bulk bulk.udf --out bulk_charged.udf
318
+
303
319
  # Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
304
320
  python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
305
321
  --name ketoprofen --n_mol 50 --density 0.8 --output_dir ./ketoprofen
@@ -349,6 +365,7 @@ Use `-h` with any module for full option details.
349
365
  - **[Developer Quickstart](docs/dev_quickstart.md)** — Setup and code conventions
350
366
  - **[I/O Spec](docs/io_spec.md)** — File format specifications
351
367
  - **[gro2udf](docs/gro2udf.md)** / **[udf2gro](docs/udf2gro.md)** — GROMACS ↔ OCTA conversion
368
+ - **[udfcharge](docs/udfcharge.md)** / **[tutorial_udfcharge](docs/tutorial_udfcharge.md)** — single-molecule → bulk UDF charge transfer
352
369
  - **[geomopt](docs/geomopt.md)** / **[amorphous](docs/amorphous.md)** — Optimization and structure building
353
370
  - **[membrane](docs/membrane.md)** / **[tutorial_membrane_us](docs/tutorial_membrane_us.md)** — Peptide-bilayer umbrella-sampling PMF (AA, CHARMM36 / Lipid21)
354
371
  - **[cg_membrane](docs/cg_membrane.md)** / **[tutorial_cg_membrane_us](docs/tutorial_cg_membrane_us.md)** — Martini 3 peptide-bilayer PMF (CG, 30-100× faster than AA, KGG-POPC smoke 5 min / production 45 min)
@@ -37,6 +37,7 @@ A Python toolkit for pre-processing, post-processing, and analysis of Fragment M
37
37
 
38
38
  - **udf2gro**: Convert OCTA UDF files to GROMACS format (`.gro`, `.top`, `.mdp`, `.itp`)
39
39
  - **gro2udf**: Convert GROMACS files to OCTA UDF format (supports `--from-top` mode)
40
+ - **udfcharge**: Transfer per-atom partial charges from a single-molecule UDF to every same-named molecule in a bulk UDF
40
41
 
41
42
  ### Geometry Optimization (`geomopt`)
42
43
 
@@ -228,6 +229,9 @@ python -m abmptools.udf2gro.cli -i system.udf -o output
228
229
  # Convert GROMACS to UDF
229
230
  python -m abmptools.gro2udf.cli -i system.gro -t system.top -o output.udf
230
231
 
232
+ # Transfer charges from a single-molecule UDF to all same-named molecules in a bulk UDF
233
+ python -m abmptools.udfcharge --template mol.udf --bulk bulk.udf --out bulk_charged.udf
234
+
231
235
  # Build an amorphous mixture from SMILES (50 ketoprofen molecules, density 0.8 g/cm^3)
232
236
  python -m abmptools.amorphous --smiles "OC(=O)C(C)c1cccc(C(=O)c2ccccc2)c1" \
233
237
  --name ketoprofen --n_mol 50 --density 0.8 --output_dir ./ketoprofen
@@ -277,6 +281,7 @@ Use `-h` with any module for full option details.
277
281
  - **[Developer Quickstart](docs/dev_quickstart.md)** — Setup and code conventions
278
282
  - **[I/O Spec](docs/io_spec.md)** — File format specifications
279
283
  - **[gro2udf](docs/gro2udf.md)** / **[udf2gro](docs/udf2gro.md)** — GROMACS ↔ OCTA conversion
284
+ - **[udfcharge](docs/udfcharge.md)** / **[tutorial_udfcharge](docs/tutorial_udfcharge.md)** — single-molecule → bulk UDF charge transfer
280
285
  - **[geomopt](docs/geomopt.md)** / **[amorphous](docs/amorphous.md)** — Optimization and structure building
281
286
  - **[membrane](docs/membrane.md)** / **[tutorial_membrane_us](docs/tutorial_membrane_us.md)** — Peptide-bilayer umbrella-sampling PMF (AA, CHARMM36 / Lipid21)
282
287
  - **[cg_membrane](docs/cg_membrane.md)** / **[tutorial_cg_membrane_us](docs/tutorial_cg_membrane_us.md)** — Martini 3 peptide-bilayer PMF (CG, 30-100× faster than AA, KGG-POPC smoke 5 min / production 45 min)
@@ -217,8 +217,15 @@ def _maybe_assign_partial_charges(mol: Any, method: str, nagl_model: str) -> Non
217
217
  if not method or method == "am1bcc":
218
218
  return
219
219
  if method == "nagl":
220
+ # NAGLToolkitWrapper は global toolkit registry に自動登録されないため
221
+ # 明示的に渡す (openff-nagl が登録済みか否かに依らず動く)。 これが
222
+ # ML-AM1-BCC 電荷を sqm / AmberTools 無し = Windows native で得る肝。
220
223
  try:
221
- mol.assign_partial_charges(partial_charge_method=nagl_model)
224
+ from openff.toolkit.utils.nagl_wrapper import NAGLToolkitWrapper
225
+ mol.assign_partial_charges(
226
+ partial_charge_method=nagl_model,
227
+ toolkit_registry=NAGLToolkitWrapper(),
228
+ )
222
229
  except Exception as e:
223
230
  raise RuntimeError(
224
231
  f"Failed to assign NAGL charges using model '{nagl_model}'. "
@@ -37,6 +37,8 @@ from .dpm_writer import (
37
37
  DEFAULT_PATCH_FIELDS, MESSAGE_TXT_CONTENT,
38
38
  )
39
39
  from .udf_writer import write_dpd_udf
40
+ from .udf_writer_udfm import write_dpd_udf_udfm
41
+ from .aij_assign import assign_aij_to_udf, match_aij_to_pairs, build_a_lookup
40
42
  from .orchestrator import CGDpdBuilder
41
43
 
42
44
 
@@ -54,7 +56,8 @@ __all__ = [
54
56
  "read_calc_sett",
55
57
  "patch_dpm", "propagate_virtual_mom", "write_message_txt",
56
58
  "DEFAULT_PATCH_FIELDS", "MESSAGE_TXT_CONTENT",
57
- "write_dpd_udf",
59
+ "write_dpd_udf", "write_dpd_udf_udfm",
60
+ "assign_aij_to_udf", "match_aij_to_pairs", "build_a_lookup",
58
61
  "CGDpdBuilder",
59
62
  "open_panel",
60
63
  ]
@@ -108,6 +108,21 @@ def main(argv=None) -> int:
108
108
  help="comma-separated segment 名 (single monomer 時、 例 'segA,segB,WAT')")
109
109
  p1.add_argument("--project-name", default="abmptools-cg-dpd")
110
110
 
111
+ # assign-aij: 既存 UDF の Pair_Interaction.DPD.a を aij.dat で割り当て
112
+ pa = sub.add_parser(
113
+ "assign-aij",
114
+ help="既存 cognac DPD UDF の Interactions.Pair_Interaction[].DPD.a を "
115
+ "aij.dat で割り当て (粒子名で順不同照合)",
116
+ )
117
+ pa.add_argument("--udf", required=True, help="既存 cognac DPD UDF")
118
+ pa.add_argument("--aij", required=True, help="aij.dat (mode='a' 直値 or 'chi')")
119
+ pa.add_argument("--aii", type=float, default=25.0,
120
+ help="chi モード変換の基準同種 a (a=aii+χ/0.306、default 25.0)")
121
+ pa.add_argument("--output", default=None,
122
+ help="出力 UDF (省略時は --udf を上書き)")
123
+ pa.add_argument("--all-types", action="store_true",
124
+ help="DPD 以外の Pair_Interaction も対象にする (default は DPD のみ)")
125
+
111
126
  args = parser.parse_args(argv)
112
127
 
113
128
  if args.cmd == "verify":
@@ -142,6 +157,21 @@ def main(argv=None) -> int:
142
157
  print(f"udf: {out}")
143
158
  return 0
144
159
 
160
+ if args.cmd == "assign-aij":
161
+ from .aij_assign import assign_aij_to_udf
162
+ result = assign_aij_to_udf(
163
+ args.udf, args.aij, out_path=args.output, aii=args.aii,
164
+ only_dpd=not args.all_types,
165
+ )
166
+ print(f"assigned: {len(result['assigned'])}/{result['total_pairs']} "
167
+ f"pair(s) -> {result['out_path']}")
168
+ if result["unmatched"]:
169
+ print(f" unmatched (aij.dat に無し): "
170
+ f"{[(s1, s2) for _, s1, s2 in result['unmatched']]}")
171
+ if result["unused_aij_pairs"]:
172
+ print(f" unused aij pairs (UDF に無し): {result['unused_aij_pairs']}")
173
+ return 0
174
+
145
175
  return 1
146
176
 
147
177
 
@@ -0,0 +1,173 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ abmptools.cg.dpd.aij_assign
4
+ ---------------------------
5
+ **既存の Cognac DPD 入力 UDF** の相互作用パラメータ a を、aij.dat の内容で
6
+ 割り当て直す (build-udf のように新規生成するのではなく、既存 UDF をパッチする)。
7
+
8
+ 割り当て規則:
9
+ - aij.dat が `aij` モード … 値をそのまま a に入れる
10
+ - aij.dat が `chi` モード … `a = aii + chi / 0.306` (= aii + 3.268·χ、
11
+ Groot-Warren。`AijMatrix.to_a_values()` が実施)。`aii` は基準同種 a (引数)
12
+
13
+ 照合:
14
+ UDF の `Interactions.Pair_Interaction[]` 各エントリの `Site1_Name` /
15
+ `Site2_Name` (= 粒子名ペア) を読み、aij.dat のペアと **順不同で照合**して
16
+ `Interactions.Pair_Interaction[].DPD.a` を書き換える。
17
+
18
+ 挿入パス (Cognac 標準。dpdgen `udfdpd_io` と同じ):
19
+ Interactions.Pair_Interaction[N].Site1_Name / Site2_Name / Potential_Type
20
+ Interactions.Pair_Interaction[N].DPD.a ← ここに a を put
21
+
22
+ I/O は `UDFManager` round-trip (OCTA 同梱、`abmptools.udfcharge` と同方式)。
23
+ `UDFManager.put` は numpy 値をサイレントに 0 化するため **`float()` cast 必須**
24
+ (`reference_udfmanager_put_numpy_silent_zero`)。
25
+
26
+ 照合・変換ロジック (`build_a_lookup` / `match_aij_to_pairs`) は UDFManager 非依存で
27
+ 単体テスト可能。`assign_aij_to_udf` のみ UDFManager を lazy import する。
28
+ """
29
+ from __future__ import annotations
30
+
31
+ import logging
32
+ from pathlib import Path
33
+ from typing import Any, Dict, List, Optional, Tuple, Union
34
+
35
+ from .models import AijMatrix
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ _PI = "Interactions.Pair_Interaction[]"
40
+
41
+
42
+ def _pair_key(a: str, b: str) -> frozenset:
43
+ """順不同のペアキー (同種 a==b は 1 要素 frozenset)。"""
44
+ return frozenset((a, b))
45
+
46
+
47
+ def build_a_lookup(aij: AijMatrix) -> Dict[frozenset, float]:
48
+ """AijMatrix → 順不同ペアキー dict ``{frozenset({i, j}): a}``。
49
+
50
+ chi モードは ``to_a_values()`` で a に変換済みの値が入る。
51
+ """
52
+ lut: Dict[frozenset, float] = {}
53
+ for i, j, a in aij.to_a_values():
54
+ lut[_pair_key(i, j)] = float(a)
55
+ return lut
56
+
57
+
58
+ def match_aij_to_pairs(
59
+ udf_pairs: List[Tuple[int, str, str]],
60
+ aij: AijMatrix,
61
+ ) -> Tuple[List[Tuple[int, float]], List[Tuple[int, str, str]]]:
62
+ """UDF の Pair_Interaction ペアと aij を照合し、割当値と未照合を返す。
63
+
64
+ Parameters
65
+ ----------
66
+ udf_pairs
67
+ ``(pair_index, site1_name, site2_name)`` のリスト (UDF から読んだ順)。
68
+ aij
69
+ aij.dat 由来の AijMatrix。
70
+
71
+ Returns
72
+ -------
73
+ (assignments, unmatched)
74
+ assignments : ``(pair_index, a_value)`` のリスト (aij.dat に該当あり)
75
+ unmatched : ``(pair_index, site1, site2)`` のリスト (aij.dat に無し)
76
+ """
77
+ lut = build_a_lookup(aij)
78
+ assignments: List[Tuple[int, float]] = []
79
+ unmatched: List[Tuple[int, str, str]] = []
80
+ for idx, s1, s2 in udf_pairs:
81
+ key = _pair_key(s1, s2)
82
+ if key in lut:
83
+ assignments.append((idx, lut[key]))
84
+ else:
85
+ unmatched.append((idx, s1, s2))
86
+ return assignments, unmatched
87
+
88
+
89
+ def assign_aij_to_udf(
90
+ udf_path: Union[str, Path],
91
+ aij: Union[AijMatrix, str, Path],
92
+ out_path: Optional[Union[str, Path]] = None,
93
+ aii: float = 25.0,
94
+ only_dpd: bool = True,
95
+ record: int = -1,
96
+ ) -> Dict[str, Any]:
97
+ """既存 Cognac DPD UDF の Pair_Interaction の a を aij で割り当てる。
98
+
99
+ Parameters
100
+ ----------
101
+ udf_path
102
+ 既存 DPD 入力 UDF (Cognac、`Interactions.Pair_Interaction[]` を持つ)。
103
+ aij
104
+ `AijMatrix` か、aij.dat のパス (パスなら `read_aij(path, aii)` で読む)。
105
+ out_path
106
+ 出力先。None なら ``udf_path`` を上書き。
107
+ aii
108
+ chi モード変換の基準同種 a (aij がパスのときのみ使用)。
109
+ only_dpd
110
+ True なら `Potential_Type == "DPD"` のペアのみ対象。
111
+ record
112
+ UDFManager の jump 先レコード (default -1 = static/最終)。
113
+
114
+ Returns
115
+ -------
116
+ dict
117
+ {assigned, unmatched, total_pairs, out_path, unused_aij_pairs}
118
+ """
119
+ from UDFManager import UDFManager # OCTA 同梱 (PyPI 非配布)
120
+
121
+ if not isinstance(aij, AijMatrix):
122
+ from .aij_io import read_aij
123
+ aij = read_aij(aij, aii=aii)
124
+
125
+ u = UDFManager(str(udf_path))
126
+ u.jump(record)
127
+
128
+ n = int(u.size(_PI) or 0)
129
+ udf_pairs: List[Tuple[int, str, str]] = []
130
+ skipped_non_dpd = 0
131
+ for k in range(n):
132
+ ptype = u.get(f"{_PI}.Potential_Type", [k])
133
+ if only_dpd and ptype != "DPD":
134
+ skipped_non_dpd += 1
135
+ continue
136
+ s1 = u.get(f"{_PI}.Site1_Name", [k])
137
+ s2 = u.get(f"{_PI}.Site2_Name", [k])
138
+ udf_pairs.append((k, str(s1), str(s2)))
139
+
140
+ assignments, unmatched = match_aij_to_pairs(udf_pairs, aij)
141
+
142
+ for idx, a in assignments:
143
+ u.put(float(a), f"{_PI}.DPD.a", [idx]) # float() cast 必須 (numpy silent-0)
144
+
145
+ out = Path(out_path) if out_path else Path(udf_path)
146
+ u.write(str(out))
147
+
148
+ # aij.dat 側で UDF に使われなかったペア (情報提供用)
149
+ udf_keys = {_pair_key(s1, s2) for _, s1, s2 in udf_pairs}
150
+ unused = [
151
+ (i, j) for (i, j, _a) in aij.to_a_values()
152
+ if _pair_key(i, j) not in udf_keys
153
+ ]
154
+
155
+ logger.info(
156
+ "assign_aij_to_udf: %d/%d pair(s) assigned, %d unmatched, "
157
+ "%d non-DPD skipped -> %s",
158
+ len(assignments), len(udf_pairs), len(unmatched), skipped_non_dpd, out,
159
+ )
160
+ if unmatched:
161
+ logger.warning(
162
+ "aij.dat に無く未割当のペア (UDF 側): %s",
163
+ [(s1, s2) for _, s1, s2 in unmatched],
164
+ )
165
+
166
+ return {
167
+ "assigned": assignments,
168
+ "unmatched": unmatched,
169
+ "total_pairs": len(udf_pairs),
170
+ "skipped_non_dpd": skipped_non_dpd,
171
+ "unused_aij_pairs": unused,
172
+ "out_path": str(out),
173
+ }
@@ -26,6 +26,7 @@ from .dpm_writer import (
26
26
  from .models import AijMatrix, CalcSett, DpdSystemSpec, MonomerSpec
27
27
  from .monomer_io import assign_particle_names, read_monomer
28
28
  from .udf_writer import write_dpd_udf
29
+ from .udf_writer_udfm import write_dpd_udf_udfm
29
30
 
30
31
  logger = logging.getLogger(__name__)
31
32
 
@@ -251,7 +252,11 @@ class CGDpdBuilder:
251
252
  *,
252
253
  include_file: str = "cognac112.udf",
253
254
  ) -> Path:
254
- """**R1**: Cognac DPD 入力 UDF (skeleton) plain text で出力。
255
+ """**R1**: Cognac DPD 入力 UDF を **UDFManager** で出力 (cognac112 スキーマ準拠)。
256
+
257
+ named-path put で組み立てるため cognac でロード可能な UDF になる。
258
+ ``UDFManager`` (OCTA 同梱) が必須 (`include_file` の cognac クラス定義も
259
+ UDFManager が解決できる場所に必要)。
255
260
 
256
261
  Parameters
257
262
  ----------
@@ -261,4 +266,4 @@ class CGDpdBuilder:
261
266
  冒頭 ``\\include`` で参照する Cognac class 定義 file (default
262
267
  ``"cognac112.udf"``、 J-OCTA 11.x 同梱)。
263
268
  """
264
- return write_dpd_udf(self.spec, output_path, include_file=include_file)
269
+ return write_dpd_udf_udfm(self.spec, output_path, include_file=include_file)
@@ -2,10 +2,18 @@
2
2
  """
3
3
  abmptools.cg.dpd.udf_writer
4
4
  ---------------------------
5
- **Route R1**: Cognac DPD 入力 UDF (``*_uin.udf``) を **plain text で直接書き出す**。
6
-
7
- 設計指針
8
- ~~~~~~~~
5
+ **[DEPRECATED / 非使用]** Route R1 の旧 plain-text writer。
6
+
7
+ .. warning::
8
+ この writer の出力は **cognac112 スキーマ非準拠で UDFManager にロードできない**
9
+ (``Pair_Interaction`` を ``Molecular_Attributes`` 配下に positional で書く /
10
+ ``Interaction_Site_Type[]`` 未定義)。2026-06-22 に判明し、現行 R1 は
11
+ :mod:`abmptools.cg.dpd.udf_writer_udfm` (UDFManager named-path、cognac112 準拠)
12
+ に置き換え済み。``CGDpdBuilder.build_udf`` / CLI ``build-udf`` はそちらを使う。
13
+ 本モジュールは参照用に残置 (新規利用不可)。
14
+
15
+ 設計指針 (旧)
16
+ ~~~~~~~~~~~~~
9
17
  - ``\\include{"cognac112.udf"}`` 1 行で class 定義を J-OCTA install 環境に委譲
10
18
  (abmptools 側に OCTA spec を持たない、 権利配慮)
11
19
  - UDFManager (OCTA) **に依存しない** plain text writer
@@ -0,0 +1,249 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ abmptools.cg.dpd.udf_writer_udfm
4
+ --------------------------------
5
+ **UDFManager ベース** の Cognac DPD 入力 UDF writer。
6
+
7
+ 旧 ``udf_writer.py`` は positional plain-text で UDF を手書きしていたが、
8
+ Pair_Interaction (14 union サブフィールドを持つ class) を positional で書く方式は
9
+ 脆く、生成 UDF が **cognac112 スキーマに非準拠で UDFManager ロード不可** だった
10
+ (Pair_Interaction を `Molecular_Attributes` 配下に置く / `Interaction_Site_Type[]`
11
+ 未定義、等)。
12
+
13
+ 本モジュールは dpdgen `udfdpd_io` と同じく **UDFManager の named-path put** で
14
+ 組み立てるため、cognac112 スキーマ準拠が保証される (= 実際に cognac でロード可能)。
15
+
16
+ 正しい配置 (cognac112.udf スキーマ準拠):
17
+ Molecular_Attributes.Atom_Type[].Name / Mass
18
+ Molecular_Attributes.Interaction_Site_Type[].Name / Num_of_Atoms / Range
19
+ Molecular_Attributes.Bond_Potential[].Name / Potential_Type / R0 / Harmonic.K
20
+ Molecular_Attributes.Angle_Potential[].Name / Potential_Type / theta0 / Theta.K
21
+ Interactions.Pair_Interaction[].Name / Potential_Type / Site1_Name / Site2_Name
22
+ / Cutoff / Scale_1_4_Pair / DPD.a / DPD.gamma
23
+ Set_of_Molecules.molecule[].Mol_Name / atom[] / bond[] / angle[] / interaction_Site[]
24
+
25
+ ``UDFManager`` は OCTA 同梱 (PyPI 非配布) で **lazy import**。`put` は numpy 値を
26
+ サイレント 0 化するため全数値 `float()`/`int()` cast 済 (`reference_udfmanager_
27
+ put_numpy_silent_zero`)。
28
+ """
29
+ from __future__ import annotations
30
+
31
+ import logging
32
+ from pathlib import Path
33
+ from typing import Dict, List, Tuple, Union
34
+
35
+ from .models import DpdSystemSpec
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ DEFAULT_INCLUDE = "cognac112.udf"
40
+ _MA = "Molecular_Attributes"
41
+ _PI = "Interactions.Pair_Interaction"
42
+ _SM = "Set_of_Molecules.molecule"
43
+ # cognac90 互換 calc flag [Bond, Angle, Torsion, Non_Bonding, ?, Non_Bonding_1_3, ...]
44
+ _CALC_FLAGS = [1, 1, 0, 1, 1, 0, 1, 0, 0, 0]
45
+ _DPD_GAMMA = 4.5
46
+
47
+
48
+ def _skeleton(include_file: str, project_name: str, comment: str) -> str:
49
+ """UDFManager が開ける最小 UDF (──include + header + 空 data)。"""
50
+ return (
51
+ f'\\include{{"{include_file}"}}\n'
52
+ "\\begin{header}\n\\begin{data}\n"
53
+ 'EngineType:"COGNAC"\n'
54
+ 'EngineVersion:"Ver112"\n'
55
+ 'IOType:"IN"\n'
56
+ f'ProjectName:"{project_name}"\n'
57
+ f'Comment:"{comment}"\n'
58
+ 'Action:""\n'
59
+ "\\end{data}\n\\end{header}\n"
60
+ "\\begin{data}\n\\end{data}\n"
61
+ )
62
+
63
+
64
+ def write_dpd_udf_udfm(
65
+ spec: DpdSystemSpec,
66
+ output_path: Union[str, Path],
67
+ *,
68
+ include_file: str = DEFAULT_INCLUDE,
69
+ ) -> Path:
70
+ """DpdSystemSpec から cognac DPD 入力 UDF を UDFManager で書き出す。
71
+
72
+ Returns
73
+ -------
74
+ Path
75
+ 出力 UDF path。
76
+ """
77
+ from UDFManager import UDFManager # OCTA 同梱 (PyPI 非配布)
78
+
79
+ output_path = Path(output_path)
80
+ output_path.parent.mkdir(parents=True, exist_ok=True)
81
+ output_path.write_text(
82
+ _skeleton(include_file, spec.project_name, spec.comment), encoding="utf-8"
83
+ )
84
+
85
+ u = UDFManager(str(output_path))
86
+
87
+ _put_simulation_conditions(u, spec)
88
+ _put_structure(u, spec)
89
+ _put_molecular_attributes(u, spec)
90
+ _put_interactions(u, spec)
91
+ _put_set_of_molecules(u, spec)
92
+
93
+ u.write(str(output_path))
94
+ logger.info(
95
+ "write_dpd_udf_udfm: %s (%d segment(s), %d monomer(s), %d pair(s))",
96
+ output_path, len(spec.segment_names()), len(spec.monomers),
97
+ len(spec.aij.to_a_values()),
98
+ )
99
+ return output_path
100
+
101
+
102
+ def _box(spec: DpdSystemSpec) -> float:
103
+ calc = spec.calc_sett
104
+ if calc and calc.box_size:
105
+ return float(calc.box_size[0])
106
+ return 10.0
107
+
108
+
109
+ def _put_simulation_conditions(u, spec: DpdSystemSpec) -> None:
110
+ calc = spec.calc_sett
111
+ dt = float(calc.dt) if calc else 0.05
112
+ steps = int(calc.step_list[0]) if calc and calc.step_list else 10000
113
+ out_interval = int(calc.output_interval) if calc else 100
114
+ lam = float(calc.phys_param.get("lambda", 0.65)) if calc and calc.phys_param else 0.65
115
+
116
+ u.put("DPD", "Simulation_Conditions.Solver.Dynamics.Dynamics_Algorithm")
117
+ u.put(0.65 if lam is None else lam, "Simulation_Conditions.Solver.Dynamics.DPD.lambda")
118
+ u.put(1.0e12, "Simulation_Conditions.Dynamics_Conditions.Max_Force")
119
+ u.put(dt, "Simulation_Conditions.Dynamics_Conditions.Time.delta_T")
120
+ u.put(steps, "Simulation_Conditions.Dynamics_Conditions.Time.Total_Steps")
121
+ u.put(out_interval, "Simulation_Conditions.Dynamics_Conditions.Time.Output_Interval_Steps")
122
+ u.put(1.0, "Simulation_Conditions.Dynamics_Conditions.Temperature.Temperature")
123
+ u.put(1.0, "Simulation_Conditions.Dynamics_Conditions.Pressure_Stress.Pressure")
124
+
125
+ # calc flags (cognac112: Non_Bonding は Interchain / Intrachain に分割)
126
+ cf = "Simulation_Conditions.Calc_Potential_Flags"
127
+ u.put(1, f"{cf}.Bond")
128
+ u.put(1, f"{cf}.Angle")
129
+ u.put(0, f"{cf}.Torsion")
130
+ u.put(1, f"{cf}.Non_Bonding_Interchain")
131
+ u.put(1, f"{cf}.Non_Bonding_Intrachain")
132
+ u.put(0, f"{cf}.Non_Bonding_1_3")
133
+
134
+
135
+ def _put_structure(u, spec: DpdSystemSpec) -> None:
136
+ box = _box(spec)
137
+ # initial structure: Random 生成 + density
138
+ u.put("Random", "Initial_Structure.Generate_Method.Method")
139
+ u.put(3.0, "Initial_Structure.Initial_Unit_Cell.Density")
140
+ u.put(box, "Initial_Structure.Initial_Unit_Cell.Cell_Size.a")
141
+ u.put(box, "Initial_Structure.Initial_Unit_Cell.Cell_Size.b")
142
+ u.put(box, "Initial_Structure.Initial_Unit_Cell.Cell_Size.c")
143
+ u.put(0, "Initial_Structure.Relaxation.Relaxation")
144
+ # unit cell
145
+ u.put(3.0, "Structure.Unit_Cell.Density")
146
+ u.put(box, "Structure.Unit_Cell.Cell_Size.a")
147
+ u.put(box, "Structure.Unit_Cell.Cell_Size.b")
148
+ u.put(box, "Structure.Unit_Cell.Cell_Size.c")
149
+ # unit parameter (DPD reduced units)
150
+ u.put(1.0, "Unit_Parameter.Energy")
151
+ u.put(0.71137866, "Unit_Parameter.Length")
152
+
153
+
154
+ def _bond_table(spec: DpdSystemSpec) -> Dict[Tuple[str, str], Tuple[float, float]]:
155
+ """(name_i, name_j) -> (R0, K) を全 monomer から集約 (重複は先勝ち)。"""
156
+ seen: Dict[Tuple[str, str], Tuple[float, float]] = {}
157
+ for mono in spec.monomers:
158
+ for entry in mono.bond12h:
159
+ if len(entry) < 5:
160
+ continue
161
+ _, i, j, dist, stiff = entry[:5]
162
+ ni = mono.particle_names[i] if i < mono.n_particles else f"P{i}"
163
+ nj = mono.particle_names[j] if j < mono.n_particles else f"P{j}"
164
+ key = tuple(sorted([ni, nj]))
165
+ seen.setdefault(key, (float(dist), float(stiff)))
166
+ return seen
167
+
168
+
169
+ def _angle_table(spec: DpdSystemSpec) -> Dict[Tuple[str, str, str], Tuple[float, float]]:
170
+ seen: Dict[Tuple[str, str, str], Tuple[float, float]] = {}
171
+ for mono in spec.monomers:
172
+ for entry in mono.angle13data:
173
+ if len(entry) < 5:
174
+ continue
175
+ a, b, c, eq, stiff = entry[:5]
176
+ na = mono.particle_names[a] if a < mono.n_particles else f"P{a}"
177
+ nb = mono.particle_names[b] if b < mono.n_particles else f"P{b}"
178
+ nc = mono.particle_names[c] if c < mono.n_particles else f"P{c}"
179
+ seen.setdefault((na, nb, nc), (float(eq), float(stiff)))
180
+ return seen
181
+
182
+
183
+ def _put_molecular_attributes(u, spec: DpdSystemSpec) -> None:
184
+ segs = spec.segment_names()
185
+ for n, s in enumerate(segs):
186
+ u.put(str(s), f"{_MA}.Atom_Type[{n}].Name")
187
+ u.put(1.0, f"{_MA}.Atom_Type[{n}].Mass")
188
+ u.put(str(s), f"{_MA}.Interaction_Site_Type[{n}].Name")
189
+ u.put(1, f"{_MA}.Interaction_Site_Type[{n}].Num_of_Atoms")
190
+ u.put(0.6, f"{_MA}.Interaction_Site_Type[{n}].Range")
191
+
192
+ for n, ((ni, nj), (R0, K)) in enumerate(_bond_table(spec).items()):
193
+ u.put(f"{ni}-{nj}", f"{_MA}.Bond_Potential[{n}].Name")
194
+ u.put("Harmonic", f"{_MA}.Bond_Potential[{n}].Potential_Type")
195
+ u.put(float(R0), f"{_MA}.Bond_Potential[{n}].R0")
196
+ u.put(float(K), f"{_MA}.Bond_Potential[{n}].Harmonic.K")
197
+
198
+ for n, ((na, nb, nc), (eq, K)) in enumerate(_angle_table(spec).items()):
199
+ u.put(f"{na}-{nb}-{nc}", f"{_MA}.Angle_Potential[{n}].Name")
200
+ u.put("Theta", f"{_MA}.Angle_Potential[{n}].Potential_Type")
201
+ u.put(float(eq), f"{_MA}.Angle_Potential[{n}].theta0")
202
+ u.put(float(K), f"{_MA}.Angle_Potential[{n}].Theta.K")
203
+
204
+
205
+ def _put_interactions(u, spec: DpdSystemSpec) -> None:
206
+ for n, (i, j, a) in enumerate(spec.aij.to_a_values()):
207
+ u.put(f"{i}-{j}", f"{_PI}[{n}].Name")
208
+ u.put("DPD", f"{_PI}[{n}].Potential_Type")
209
+ u.put(str(i), f"{_PI}[{n}].Site1_Name")
210
+ u.put(str(j), f"{_PI}[{n}].Site2_Name")
211
+ u.put(1.0, f"{_PI}[{n}].Cutoff")
212
+ u.put(1.0, f"{_PI}[{n}].Scale_1_4_Pair")
213
+ u.put(float(a), f"{_PI}[{n}].DPD.a")
214
+ u.put(float(_DPD_GAMMA), f"{_PI}[{n}].DPD.gamma")
215
+
216
+
217
+ def _put_set_of_molecules(u, spec: DpdSystemSpec) -> None:
218
+ """各 monomer 種を 1 molecule テンプレートとして登録 (atoms/bonds/angles)。"""
219
+ bond_names = _bond_table(spec)
220
+ angle_names = _angle_table(spec)
221
+ for mid, mono in enumerate(spec.monomers):
222
+ u.put(str(mono.name), f"{_SM}[{mid}].Mol_Name")
223
+ names = list(mono.particle_names) or [f"P{k}" for k in range(mono.n_particles)]
224
+ for k, pn in enumerate(names):
225
+ u.put(int(k), f"{_SM}[{mid}].atom[{k}].Atom_ID")
226
+ u.put(str(pn), f"{_SM}[{mid}].atom[{k}].Atom_Name")
227
+ u.put(str(pn), f"{_SM}[{mid}].atom[{k}].Atom_Type_Name")
228
+ u.put(0, f"{_SM}[{mid}].atom[{k}].Chirality")
229
+ u.put(1, f"{_SM}[{mid}].atom[{k}].Main_Chain")
230
+ u.put(str(pn), f"{_SM}[{mid}].interaction_Site[{k}].Type_Name")
231
+ u.put(int(k), f"{_SM}[{mid}].interaction_Site[{k}].atom[0]")
232
+ for bk, (i, j) in enumerate(mono.bond12):
233
+ ni = names[i] if i < len(names) else f"P{i}"
234
+ nj = names[j] if j < len(names) else f"P{j}"
235
+ key = tuple(sorted([ni, nj]))
236
+ pname = f"{key[0]}-{key[1]}" if key in bond_names else f"{ni}-{nj}"
237
+ u.put(str(pname), f"{_SM}[{mid}].bond[{bk}].Potential_Name")
238
+ u.put(int(i), f"{_SM}[{mid}].bond[{bk}].atom1")
239
+ u.put(int(j), f"{_SM}[{mid}].bond[{bk}].atom2")
240
+ u.put(1, f"{_SM}[{mid}].bond[{bk}].Order")
241
+ for ak, (a, b, c) in enumerate(mono.angle13):
242
+ na = names[a] if a < len(names) else f"P{a}"
243
+ nb = names[b] if b < len(names) else f"P{b}"
244
+ nc = names[c] if c < len(names) else f"P{c}"
245
+ pname = f"{na}-{nb}-{nc}"
246
+ u.put(str(pname), f"{_SM}[{mid}].angle[{ak}].Potential_Name")
247
+ u.put(int(a), f"{_SM}[{mid}].angle[{ak}].atom1")
248
+ u.put(int(b), f"{_SM}[{mid}].angle[{ak}].atom2")
249
+ u.put(int(c), f"{_SM}[{mid}].angle[{ak}].atom3")