高温氦气物性补全;三通四通能量计算bug修正
This commit is contained in:
1 parent
6fc9afe41d
commit
2b07d996cf
133 files changed
+5230
-253310
No files matched your search
@@ -9,6 +9,7 @@ import json
|
||||
import math
|
||||
import re
|
||||
from importlib import import_module
|
||||
from graphlib import TopologicalSorter
|
||||
|
||||
from .compiler import NativeCapabilityError, NativeProgram, _Groups, _number as num
|
||||
from .contracts import SUPPORTED_VERSIONS
|
||||
@@ -144,6 +145,8 @@ def compile_extended_program(network):
|
||||
thermal = 'T' if is_polytropic(c) else 'U'
|
||||
fields = ('m1', thermal+'1', 'm2', thermal+'2') if c.model_type == 'amesim_pnl0003' else ('m', thermal)
|
||||
add_states(c, fields, [0.0]*len(fields))
|
||||
if c.model_type == 'amesim_pnch012' and sum(c.external_volume_rates.values()) != 0:
|
||||
add_states(c, ('_volume_displacement',), (0.0,))
|
||||
elif c.model_type == 'amesim_mecmas21':
|
||||
root = groups.find((c.name, 'port_1'))
|
||||
mass_groups.setdefault(root, []).append(c)
|
||||
@@ -257,6 +260,30 @@ def compile_extended_program(network):
|
||||
if temperature and obj.model_type in NODES-{'tee'}:
|
||||
other = adjacent[(obj.name, 'port_2')]
|
||||
return f'h[{pi[other]}]'
|
||||
|
||||
# Reference nodes aggregate branch quantities towards port 2. Follow this
|
||||
# directed contract, not the undirected pressure group (which can span
|
||||
# unrelated volumes). Port-supply validation has already rejected cycles.
|
||||
reference_nodes = {c.name: c for c in components if c.model_type in NODES-{'tee'}}
|
||||
node_graph = {c.name: [other[0] for name in pnames(c) if name != 'port_2'
|
||||
for other in [adjacent[ep(c, name)]]
|
||||
if other[0] in reference_nodes and other[1] == 'port_2']
|
||||
for c in reference_nodes.values()}
|
||||
node_order = [reference_nodes[name] for name in TopologicalSorter(node_graph).static_order()]
|
||||
volume_sources = {ep(c, 'port_1'): [c] for c in pistons}
|
||||
node_energy = {ep(c, 'port_2'): f'node_energy[{i}]' for i, c in enumerate(node_order)}
|
||||
for c in node_order:
|
||||
volume_sources[ep(c, 'port_2')] = [source for name in pnames(c) if name != 'port_2'
|
||||
for source in volume_sources.get(adjacent[ep(c, name)], ())]
|
||||
|
||||
def energy_into(c, name, outflow_h):
|
||||
other = adjacent[ep(c, name)]
|
||||
# Net mass flow can be zero while the sum of branch enthalpy flows
|
||||
# remains nonzero. Carry that signed energy directly, without H/q.
|
||||
if other in node_energy:
|
||||
return node_energy[other]
|
||||
return f'{q(c,name)}*({q(c,name)}>0?{hin(c,name)}:{outflow_h})'
|
||||
|
||||
gases, anchor, port_gas, volume_rate = {}, {}, {}, {}
|
||||
anchor_partitions = {}
|
||||
gas_count = 0
|
||||
@@ -267,11 +294,19 @@ def compile_extended_program(network):
|
||||
if kind == 'amesim_pnch023':
|
||||
volume, rate = num(c.cvol), '0.0'
|
||||
elif kind == 'amesim_pnch012':
|
||||
attached = [d for d in pistons if adjacent[ep(d,'port_1')][0] == c.name]
|
||||
attached = [source for name in pnames(c)
|
||||
for source in volume_sources.get(adjacent[ep(c, name)], ())]
|
||||
volume = num(c.cvol0+sum(c.external_volumes.values()))+''.join('+'+w(d,'volume') for d in attached)
|
||||
if (c.name, '_volume_displacement') in states:
|
||||
volume += '+'+y(c, '_volume_displacement')
|
||||
target = f'dy[{states[c.name,"_volume_displacement"]}]'
|
||||
expr = num(sum(c.external_volume_rates.values()))
|
||||
lines.append(f'{target}={expr};')
|
||||
dependencies.expression(target, expr)
|
||||
put(c, 'vol', f'fmax({num(c.cvol0/100)}, {volume})')
|
||||
rate = num(sum(c.external_volume_rates.values()))+''.join('+'+w(d,'volume_flow') for d in attached)
|
||||
put(c, 'dvol', f'{w(c,"vol")} <= {num(c.cvol0/100)} ? 0.0 : ({rate})')
|
||||
limit = num(c.cvol0/100)
|
||||
put(c, 'dvol', f'({volume}) < {limit} || (({volume}) <= {limit} && ({rate}) < 0) ? 0.0 : ({rate})')
|
||||
volume, rate = w(c,'vol'), w(c,'dvol')
|
||||
elif kind in ('cylinder', 'tank'):
|
||||
volume, rate = num(c.V), '0.0'
|
||||
@@ -445,7 +480,8 @@ def compile_extended_program(network):
|
||||
elif kind in NODES:
|
||||
if kind!='tee':
|
||||
# Reference copies have no flow dependency. Keep them separate
|
||||
# from the reference port's returned energy/mixing calculation.
|
||||
# from the reference port's finite h_outflow diagnostic below;
|
||||
# actual reference energy is carried by node_energy, not q*h.
|
||||
for name in names:
|
||||
if name!='port_2':
|
||||
operations.append(Computation.assignment(f'alias:{c.name}.{name}',h(c,name),hin(c,'port_2'),'alias'))
|
||||
@@ -493,6 +529,13 @@ def compile_extended_program(network):
|
||||
dependencies.expression(target, expr)
|
||||
schedule_helpers, scheduled_lines=schedule.emit()
|
||||
lines += scheduled_lines
|
||||
if node_order:
|
||||
lines.append(f'double node_energy[{len(node_order)}];')
|
||||
for c in node_order:
|
||||
target = node_energy[ep(c, 'port_2')]
|
||||
expr = ' + '.join(energy_into(c, name, h(c, name)) for name in pnames(c) if name != 'port_2')
|
||||
lines.append(f'{target}={expr};')
|
||||
dependencies.expression(target, expr)
|
||||
for c in components:
|
||||
for name in pnames(c):
|
||||
for field,expr in [('p',p(c,name)),('m_flow',q(c,name)),('h_outflow',h(c,name))]:
|
||||
@@ -612,7 +655,7 @@ def compile_extended_program(network):
|
||||
gas=gases[c.name,half];suffix=str(half) if half else ''
|
||||
names=['port_'+suffix] if half else pnames(c)
|
||||
mass=' + '.join(q(c,name) for name in names)
|
||||
energy=' + '.join(f'{q(c,name)}*({q(c,name)}>0?{hin(c,name)}:{gas}.h)' for name in names)
|
||||
energy=' + '.join(energy_into(c, name, gas+'.h') for name in names)
|
||||
if half:
|
||||
sign='-' if half==1 else '+'
|
||||
mass+=sign+center
|
||||
@@ -682,11 +725,12 @@ def compile_extended_program(network):
|
||||
*jacobian.source_lines(),
|
||||
*schedule_helpers,
|
||||
'int model_init(double *y) {',*[f'y[{i}]={num(v)};' for i,v in enumerate(initial)],*gas_initializers,'return 1;}',
|
||||
'static int model_eval_internal(double t,const double *y,double *dy,double *w,int canonical,double *friction_drives) {',
|
||||
'static int model_eval_internal(double t,const double *y,double *dy,double *w,int canonical,double *friction_drives,NativePropertyTemperatures *temperatures) {',
|
||||
'(void)friction_drives;',
|
||||
f'NativePropertyState property_states[{min(256,max(16,4*gas_count+2*len(components)))}];',
|
||||
'NativePropertyCache property_cache, *properties=&property_cache;',
|
||||
'native_properties_init(properties,property_states,sizeof(property_states)/sizeof(property_states[0]));',
|
||||
'properties->temperatures=temperatures;',
|
||||
'NativePropertyCache *gas_properties=canonical?NULL:properties;(void)gas_properties;',
|
||||
*(['double projected[NSTATES];for(int i=0;i<NSTATES;i++) projected[i]=y[i];',*project,'y=projected;'] if project else []),
|
||||
f'double p[{np}]={{0}},h[{nq}]={{0}},q[{nq}]={{0}};NativeGas g[{ng}];',
|
||||
@@ -695,13 +739,16 @@ def compile_extended_program(network):
|
||||
'(void)t;(void)y;(void)w;(void)p;(void)h;(void)q;(void)g;',*lines,
|
||||
'for(int i=0;i<NSTATES;i++) if(!isfinite(dy[i])) return 0;',
|
||||
'for(int i=0;i<NOUTPUTS;i++) if(!isfinite(w[i])) return 0;','return 1;}',
|
||||
'int model_eval(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,0,NULL);}',
|
||||
'int model_eval_jacobian(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,1,NULL);}',
|
||||
'int model_friction_drives(double t,const double *y,double *drives) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,drives);}',
|
||||
'int model_eval(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,0,NULL,NULL);}',
|
||||
'int model_eval_jacobian(double t,const double *y,double *dy,double *w) {return model_eval_internal(t,y,dy,w,1,NULL,NULL);}',
|
||||
'int model_friction_drives(double t,const double *y,double *drives) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,drives,NULL);}',
|
||||
'int model_property_temperatures(double t,const double *y,NativePropertyTemperatures *temperatures) {double dy[NSTATES],w[NOUTPUTS];return model_eval_internal(t,y,dy,w,0,NULL,temperatures);}',
|
||||
'double model_next_break(double t,double end) { double result=end;(void)t;',*breaks,'return result;}',''])
|
||||
header=f'''#ifndef GENERATED_NATIVE_MODEL_H
|
||||
#define GENERATED_NATIVE_MODEL_H
|
||||
#include "kernels.h"
|
||||
#define MODEL_PROPERTY_TEMPERATURES {int(any(key[1] == 'peng_robinson' for key in media))}
|
||||
int model_property_temperatures(double t,const double *y,NativePropertyTemperatures *temperatures);
|
||||
#define NSTATES {nstates}
|
||||
#define NOUTPUTS {max(1,len(variables))}
|
||||
#define NSTOPS {len(stops)}
|
||||
|
||||
Reference in new issue
Block a user